--- /dev/null
+#! /bin/sh
+
+while getopts a:c:e:h:n:o:s:t: c
+ do
+ case $c in
+ c) CERT=$OPTARG;;
+ e) ENTITYID=$OPTARG;;
+ h) HOSTS[${#HOSTS[*]}]=$OPTARG;;
+ n) NAKEDHOSTS[${#NAKEDHOSTS[*]}]=$OPTARG;;
+ o) ORGNAME=$OPTARG;;
+ a) ADMIN[${#ADMIN[*]}]=$OPTARG;;
+ s) SUP[${#SUP[*]}]=$OPTARG;;
+ t) TECH[${#TECH[*]}]=$OPTARG;;
+ \?) echo metagen -c certificate -h host1 [-h host2 ...] [-e entityID]
+ exit 1;;
+ esac
+ done
+
+if [ ${#HOSTS[*]} -eq 0 -a ${#NAKEDHOSTS[*]} -eq 0 ] ; then
+ echo metagen -c certificate -h host1 [-h host2 ...] [-e entityID]
+ exit 1
+fi
+
+if [ -z $CERT ] ; then
+ CERT=sp-cert.pem
+fi
+
+if [ ! -s $CERT ] ; then
+ echo Certificate file $CERT does not exist!
+ exit 2
+fi
+
+if [ -z $ENTITYID ] ; then
+ ENTITYID=https://${HOSTS[0]}/shibboleth
+fi
+
+cat <<EOF
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${ENTITYID}">
+ <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol">
+ <md:Extensions>
+EOF
+
+count=1
+for h in ${HOSTS[@]}
+do
+ cat << EOF
+ <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://$h/Shibboleth.sso/DS" index="$count"/>
+EOF
+ let "count++"
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+ cat << EOF
+ <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://$h/Shibboleth.sso/DS" index="$count"/>
+EOF
+ let "count++"
+done
+
+cat << EOF
+ </md:Extensions>
+ <md:KeyDescriptor>
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>
+EOF
+
+grep -v ^- $CERT
+
+cat <<EOF
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <!--
+EOF
+
+for h in ${HOSTS[@]}
+do
+ cat <<EOF
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://$h/Shibboleth.sso/SLO/SOAP"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://$h/Shibboleth.sso/SLO/Redirect"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/SLO/POST"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/SLO/Artifact"/>
+EOF
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+ cat <<EOF
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://$h/Shibboleth.sso/SLO/SOAP"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://$h/Shibboleth.sso/SLO/Redirect"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/SLO/POST"/>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/SLO/Artifact"/>
+EOF
+done
+
+for h in ${HOSTS[@]}
+do
+ cat <<EOF
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://$h/Shibboleth.sso/NIM/SOAP"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://$h/Shibboleth.sso/NIM/Redirect"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/NIM/POST"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/NIM/Artifact"/>
+EOF
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+ cat <<EOF
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://$h/Shibboleth.sso/NIM/SOAP"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://$h/Shibboleth.sso/NIM/Redirect"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/NIM/POST"/>
+ <md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/NIM/Artifact"/>
+EOF
+done
+
+cat <<EOF
+ -->
+EOF
+
+count=0
+for h in ${HOSTS[@]}
+do
+ cat <<EOF
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://$h/Shibboleth.sso/SAML2/POST" index="$((count+1))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://$h/Shibboleth.sso/SAML2/POST-SimpleSign" index="$((count+2))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://$h/Shibboleth.sso/SAML2/Artifact" index="$((count+3))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://$h/Shibboleth.sso/SAML2/ECP" index="$((count+4))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://$h/Shibboleth.sso/SAML/POST" index="$((count+5))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://$h/Shibboleth.sso/SAML/Artifact" index="$((count+6))"/>
+EOF
+ let "count+=6"
+done
+
+for h in ${NAKEDHOSTS[@]}
+do
+ cat <<EOF
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://$h/Shibboleth.sso/SAML2/POST" index="$((count+1))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="http://$h/Shibboleth.sso/SAML2/POST-SimpleSign" index="$((count+2))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://$h/Shibboleth.sso/SAML2/Artifact" index="$((count+3))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="http://$h/Shibboleth.sso/SAML2/ECP" index="$((count+4))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="http://$h/Shibboleth.sso/SAML/POST" index="$((count+5))"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="http://$h/Shibboleth.sso/SAML/Artifact" index="$((count+6))"/>
+EOF
+ let "count+=6"
+done
+
+cat <<EOF
+ </md:SPSSODescriptor>
+EOF
+
+if [ -n "$ORGNAME" ] ; then
+ cat <<EOF
+ <md:Organization>
+ <md:OrganizationName xml:lang="en">$ORGNAME</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="en">$ORGNAME</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="en">$ENTITYID</md:OrganizationURL>
+ </md:Organization>
+EOF
+fi
+
+for c in ${ADMIN[@]}
+do
+ c=(${c//\// })
+ cat <<EOF
+ <md:ContactPerson contactType="administrative">
+ <md:GivenName>${c[0]}</md:GivenName>
+ <md:SurName>${c[1]}</md:SurName>
+ <md:EmailAddress>${c[2]}</md:EmailAddress>
+ </md:ContactPerson>
+EOF
+done
+
+for c in ${SUP[@]}
+do
+ c=(${c//\// })
+ cat <<EOF
+ <md:ContactPerson contactType="support">
+ <md:GivenName>${c[0]}</md:GivenName>
+ <md:SurName>${c[1]}</md:SurName>
+ <md:EmailAddress>${c[2]}</md:EmailAddress>
+ </md:ContactPerson>
+EOF
+done
+
+for c in ${TECH[@]}
+do
+ c=(${c//\// })
+ cat <<EOF
+ <md:ContactPerson contactType="technical">
+ <md:GivenName>${c[0]}</md:GivenName>
+ <md:SurName>${c[1]}</md:SurName>
+ <md:EmailAddress>${c[2]}</md:EmailAddress>
+ </md:ContactPerson>
+EOF
+done
+
+cat <<EOF
+</md:EntityDescriptor>
+EOF