ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
Signer.php
Go to the documentation of this file.
1 <?php
2 
3 
11 {
12 
25  private static function findKeyCert($config, $entityMetadata, $type)
26  {
27  // first we look for metadata.privatekey and metadata.certificate in the metadata
28  if (array_key_exists('metadata.sign.privatekey', $entityMetadata)
29  || array_key_exists('metadata.sign.certificate', $entityMetadata)
30  ) {
31 
32  if (!array_key_exists('metadata.sign.privatekey', $entityMetadata)
33  || !array_key_exists('metadata.sign.certificate', $entityMetadata)
34  ) {
35 
36  throw new Exception(
37  'Missing either the "metadata.sign.privatekey" or the'.
38  ' "metadata.sign.certificate" configuration option in the metadata for'.
39  ' the '.$type.' "'.$entityMetadata['entityid'].'". If one of'.
40  ' these options is specified, then the other must also be specified.'
41  );
42  }
43 
44  $ret = array(
45  'privatekey' => $entityMetadata['metadata.sign.privatekey'],
46  'certificate' => $entityMetadata['metadata.sign.certificate']
47  );
48 
49  if (array_key_exists('metadata.sign.privatekey_pass', $entityMetadata)) {
50  $ret['privatekey_pass'] = $entityMetadata['metadata.sign.privatekey_pass'];
51  }
52 
53  return $ret;
54  }
55 
56  // then we look for default values in the global configuration
57  $privatekey = $config->getString('metadata.sign.privatekey', null);
58  $certificate = $config->getString('metadata.sign.certificate', null);
59  if ($privatekey !== null || $certificate !== null) {
60  if ($privatekey === null || $certificate === null) {
61  throw new Exception(
62  'Missing either the "metadata.sign.privatekey" or the'.
63  ' "metadata.sign.certificate" configuration option in the global'.
64  ' configuration. If one of these options is specified, then the other'.
65  ' must also be specified.'
66  );
67  }
68  $ret = array('privatekey' => $privatekey, 'certificate' => $certificate);
69 
70  $privatekey_pass = $config->getString('metadata.sign.privatekey_pass', null);
71  if ($privatekey_pass !== null) {
72  $ret['privatekey_pass'] = $privatekey_pass;
73  }
74 
75  return $ret;
76  }
77 
78  // as a last resort we attempt to use the privatekey and certificate option from the metadata
79  if (array_key_exists('privatekey', $entityMetadata)
80  || array_key_exists('certificate', $entityMetadata)
81  ) {
82 
83  if (!array_key_exists('privatekey', $entityMetadata)
84  || !array_key_exists('certificate', $entityMetadata)
85  ) {
86  throw new Exception(
87  'Both the "privatekey" and the "certificate" option must'.
88  ' be set in the metadata for the '.$type.' "'.
89  $entityMetadata['entityid'].'" before it is possible to sign metadata'.
90  ' from this entity.'
91  );
92  }
93 
94  $ret = array(
95  'privatekey' => $entityMetadata['privatekey'],
96  'certificate' => $entityMetadata['certificate']
97  );
98 
99  if (array_key_exists('privatekey_pass', $entityMetadata)) {
100  $ret['privatekey_pass'] = $entityMetadata['privatekey_pass'];
101  }
102 
103  return $ret;
104  }
105 
106  throw new Exception(
107  'Could not find what key & certificate should be used to sign the metadata'.
108  ' for the '.$type.' "'.$entityMetadata['entityid'].'".'
109  );
110  }
111 
112 
124  private static function isMetadataSigningEnabled($config, $entityMetadata, $type)
125  {
126  // first check the metadata for the entity
127  if (array_key_exists('metadata.sign.enable', $entityMetadata)) {
128  if (!is_bool($entityMetadata['metadata.sign.enable'])) {
129  throw new Exception(
130  'Invalid value for the "metadata.sign.enable" configuration option for'.
131  ' the '.$type.' "'.$entityMetadata['entityid'].'". This option'.
132  ' should be a boolean.'
133  );
134  }
135 
136  return $entityMetadata['metadata.sign.enable'];
137  }
138 
139  $enabled = $config->getBoolean('metadata.sign.enable', false);
140 
141  return $enabled;
142  }
143 
144 
162  private static function getMetadataSigningAlgorithm($config, $entityMetadata, $type)
163  {
164  // configure the algorithm to use
165  if (array_key_exists('metadata.sign.algorithm', $entityMetadata)) {
166  if (!is_string($entityMetadata['metadata.sign.algorithm'])) {
167  throw new \SimpleSAML\Error\CriticalConfigurationError(
168  "Invalid value for the 'metadata.sign.algorithm' configuration option for the ".$type.
169  "'".$entityMetadata['entityid']."'. This option has restricted values"
170  );
171  }
172  $alg = $entityMetadata['metadata.sign.algorithm'];
173  } else {
174  $alg = $config->getString('metadata.sign.algorithm', XMLSecurityKey::RSA_SHA1);
175  }
176 
177  $supported_algs = array(
178  XMLSecurityKey::RSA_SHA1,
179  XMLSecurityKey::RSA_SHA256,
180  XMLSecurityKey::RSA_SHA384,
181  XMLSecurityKey::RSA_SHA512,
182  );
183 
184  if (!in_array($alg, $supported_algs, true)) {
185  throw new \SimpleSAML\Error\CriticalConfigurationError("Unknown signature algorithm '$alg'");
186  }
187 
188  switch ($alg) {
189  case XMLSecurityKey::RSA_SHA256:
190  $digest = XMLSecurityDSig::SHA256;
191  break;
192  case XMLSecurityKey::RSA_SHA384:
193  $digest = XMLSecurityDSig::SHA384;
194  break;
195  case XMLSecurityKey::RSA_SHA512:
196  $digest = XMLSecurityDSig::SHA512;
197  break;
198  default:
199  $digest = XMLSecurityDSig::SHA1;
200  }
201 
202  return array(
203  'algorithm' => $alg,
204  'digest' => $digest,
205  );
206  }
207 
208 
219  public static function sign($metadataString, $entityMetadata, $type)
220  {
222 
223  // check if metadata signing is enabled
224  if (!self::isMetadataSigningEnabled($config, $entityMetadata, $type)) {
225  return $metadataString;
226  }
227 
228  // find the key & certificate which should be used to sign the metadata
229  $keyCertFiles = self::findKeyCert($config, $entityMetadata, $type);
230 
231  $keyFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['privatekey']);
232  if (!file_exists($keyFile)) {
233  throw new Exception('Could not find private key file ['.$keyFile.'], which is needed to sign the metadata');
234  }
235  $keyData = file_get_contents($keyFile);
236 
237  $certFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['certificate']);
238  if (!file_exists($certFile)) {
239  throw new Exception(
240  'Could not find certificate file ['.$certFile.'], which is needed to sign the metadata'
241  );
242  }
243  $certData = file_get_contents($certFile);
244 
245 
246  // convert the metadata to a DOM tree
247  try {
248  $xml = \SAML2\DOMDocumentFactory::fromString($metadataString);
249  } catch(Exception $e) {
250  throw new Exception('Error parsing self-generated metadata.');
251  }
252 
253  $signature_cf = self::getMetadataSigningAlgorithm($config, $entityMetadata, $type);
254 
255  // load the private key
256  $objKey = new XMLSecurityKey($signature_cf['algorithm'], array('type' => 'private'));
257  if (array_key_exists('privatekey_pass', $keyCertFiles)) {
258  $objKey->passphrase = $keyCertFiles['privatekey_pass'];
259  }
260  $objKey->loadKey($keyData, false);
261 
262  // get the EntityDescriptor node we should sign
263  $rootNode = $xml->firstChild;
264 
265  // sign the metadata with our private key
266  if ($type == 'ADFS IdP') {
267  $objXMLSecDSig = new sspmod_adfs_XMLSecurityDSig($metadataString);
268  } else {
269  $objXMLSecDSig = new XMLSecurityDSig();
270  }
271 
272  $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
273 
274  $objXMLSecDSig->addReferenceList(
275  array($rootNode),
276  $signature_cf['digest'],
277  array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
278  array('id_name' => 'ID')
279  );
280 
281  $objXMLSecDSig->sign($objKey);
282 
283  // add the certificate to the signature
284  $objXMLSecDSig->add509Cert($certData, true);
285 
286  // add the signature to the metadata
287  $objXMLSecDSig->insertSignature($rootNode, $rootNode->firstChild);
288 
289  // return the DOM tree as a string
290  return $xml->saveXML();
291  }
292 }
$type
static findKeyCert($config, $entityMetadata, $type)
This functions finds what key & certificate files should be used to sign the metadata for the given e...
Definition: Signer.php:25
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
$xml
Definition: metadata.php:240
static getMetadataSigningAlgorithm($config, $entityMetadata, $type)
Determine the signature and digest algorithms to use when signing metadata.
Definition: Signer.php:162
Create styles array
The data for the language used.
static sign($metadataString, $entityMetadata, $type)
Signs the given metadata if metadata signing is enabled.
Definition: Signer.php:219
static isMetadataSigningEnabled($config, $entityMetadata, $type)
Determine whether metadata signing is enabled for the given metadata.
Definition: Signer.php:124
static getCertPath($path)
Resolves a path that may be relative to the cert-directory.
Definition: Config.php:22
$ret
Definition: parser.php:6
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.