@@ -120,42 +120,27 @@ public function send(AbstractMessage $message): ResponseInterface
120120 */
121121 public function receive (ServerRequestInterface $ request ): AbstractMessage
122122 {
123- $ query = $ this ->parseQuery ();
124- $ signedQuery = $ query ['SignedQuery ' ];
125-
126- /**
127- * Get the SAMLRequest/SAMLResponse from the exact same signed data that will be verified later in
128- * validateSignature into $res using the actual SignedQuery
129- */
130- $ res = [];
131- foreach (explode ('& ' , $ signedQuery ) as $ e ) {
132- $ tmp = explode ('= ' , $ e , 2 );
133- $ name = $ tmp [0 ];
134- if (count ($ tmp ) === 2 ) {
135- $ value = $ tmp [1 ];
136- } else {
137- /* No value for this parameter. */
138- $ value = '' ;
139- }
140- $ name = urldecode ($ name );
141- $ res [$ name ] = urldecode ($ value );
142- }
123+ $ query = $ request ->getQueryParams ();
143124
144125 /**
145126 * Put the SAMLRequest/SAMLResponse from the actual query string into $message,
146127 * and assert that the result from parseQuery() in $query and the parsing of the SignedQuery in $res agree
147128 */
148- if (array_key_exists ('SAMLRequest ' , $ res )) {
149- Assert:: same ( $ res [ ' SAMLRequest ' ], $ query ['SAMLRequest ' ], ' Parse failure. ' );
150- $ message = $ res ['SAMLRequest ' ];
151- } elseif (array_key_exists ('SAMLResponse ' , $ res )) {
152- Assert:: same ( $ res [ ' SAMLResponse ' ], $ query ['SAMLResponse ' ], ' Parse failure. ' );
153- $ message = $ res ['SAMLResponse ' ];
129+ if (array_key_exists ('SAMLRequest ' , $ query )) {
130+ $ message = urldecode ( $ query ['SAMLRequest ' ]);
131+ $ signedQuery = ' SAMLRequest= ' . $ query ['SAMLRequest ' ];
132+ } elseif (array_key_exists ('SAMLResponse ' , $ query )) {
133+ $ message = urldecode ( $ query ['SAMLResponse ' ]);
134+ $ signedQuery = ' SAMLResponse= ' . $ query ['SAMLResponse ' ];
154135 } else {
155136 throw new Exception ('Missing SAMLRequest or SAMLResponse parameter. ' );
156137 }
157138
158- if (isset ($ query ['SAMLEncoding ' ]) && $ query ['SAMLEncoding ' ] !== C::BINDING_HTTP_REDIRECT_DEFLATE ) {
139+ if (array_key_exists ('SAMLRequest ' , $ query ) && array_key_exists ('SAMLResponse ' , $ query )) {
140+ throw new Exception ('Both SAMLRequest and SAMLResponse provided. ' );
141+ }
142+
143+ if (isset ($ query ['SAMLEncoding ' ]) && urldecode ($ query ['SAMLEncoding ' ]) !== C::BINDING_HTTP_REDIRECT_DEFLATE ) {
159144 throw new Exception (sprintf ('Unknown SAMLEncoding: %s ' , $ query ['SAMLEncoding ' ]));
160145 }
161146
@@ -174,7 +159,8 @@ public function receive(ServerRequestInterface $request): AbstractMessage
174159 $ message = MessageFactory::fromXML ($ document ->documentElement );
175160
176161 if (array_key_exists ('RelayState ' , $ query )) {
177- $ this ->setRelayState ($ query ['RelayState ' ]);
162+ $ this ->setRelayState (urldecode ($ query ['RelayState ' ]));
163+ $ signedQuery .= '&RelayState= ' . $ query ['RelayState ' ];
178164 }
179165
180166 if (!array_key_exists ('Signature ' , $ query )) {
@@ -192,83 +178,22 @@ public function receive(ServerRequestInterface $request): AbstractMessage
192178
193179 if (!array_key_exists ('SigAlg ' , $ query )) {
194180 throw new Exception ('Missing signature algorithm. ' );
181+ } else {
182+ $ signedQuery .= '&SigAlg= ' . $ query ['SigAlg ' ];
195183 }
196184
197185 $ container = ContainerSingleton::getInstance ();
198186 $ blacklist = $ container ->getBlacklistedEncryptionAlgorithms ();
199187 $ verifier = (new SignatureAlgorithmFactory ($ blacklist ))->getAlgorithm (
200- $ query ['SigAlg ' ],
188+ urldecode ( $ query ['SigAlg ' ]) ,
201189 // TODO: Need to use the key from the metadata
202190 PEMCertificatesMock::getPublicKey (PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY ),
203191 );
204192
205- if ($ verifier ->verify ($ signedQuery , base64_decode ($ query ['Signature ' ])) === false ) {
193+ if ($ verifier ->verify ($ signedQuery , base64_decode (urldecode ( $ query ['Signature ' ]) )) === false ) {
206194 throw new SignatureVerificationFailedException ('Failed to verify signature. ' );
207195 }
208196
209197 return $ message ;
210198 }
211-
212-
213- /**
214- * Helper function to parse query data.
215- *
216- * This function returns the query string split into key=>value pairs.
217- * It also adds a new parameter, SignedQuery, which contains the data that is
218- * signed.
219- *
220- * @return array The query data that is signed.
221- * @throws \Exception
222- */
223- private static function parseQuery (): array
224- {
225- /*
226- * Parse the query string. We need to do this ourself, so that we get access
227- * to the raw (urlencoded) values. This is required because different software
228- * can urlencode to different values.
229- */
230- $ data = [];
231- $ relayState = '' ;
232- $ sigAlg = '' ;
233- $ sigQuery = '' ;
234-
235- foreach (explode ('& ' , $ _SERVER ['QUERY_STRING ' ]) as $ e ) {
236- $ tmp = explode ('= ' , $ e , 2 );
237- $ name = $ tmp [0 ];
238- if (count ($ tmp ) === 2 ) {
239- $ value = $ tmp [1 ];
240- } else {
241- /* No value for this parameter. */
242- $ value = '' ;
243- }
244-
245- $ name = urldecode ($ name );
246- // Prevent keys from being set more than once
247- if (array_key_exists ($ name , $ data )) {
248- throw new Exception ('Duplicate parameter. ' );
249- }
250- $ data [$ name ] = urldecode ($ value );
251-
252- switch ($ name ) {
253- case 'SAMLRequest ' :
254- case 'SAMLResponse ' :
255- $ sigQuery = $ name . '= ' . $ value ;
256- break ;
257- case 'RelayState ' :
258- $ relayState = '&RelayState= ' . $ value ;
259- break ;
260- case 'SigAlg ' :
261- $ sigAlg = '&SigAlg= ' . $ value ;
262- break ;
263- }
264- }
265-
266- if (array_key_exists ('SAMLRequest ' , $ data ) && array_key_exists ('SAMLResponse ' , $ data )) {
267- throw new Exception ('Both SAMLRequest and SAMLResponse provided. ' );
268- }
269-
270- $ data ['SignedQuery ' ] = $ sigQuery . $ relayState . $ sigAlg ;
271-
272- return $ data ;
273- }
274199}
0 commit comments