| Conditions | 43 |
| Paths | > 20000 |
| Total Lines | 207 |
| Code Lines | 120 |
| Lines | 21 |
| Ratio | 10.14 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 288 | function verify($token, $use_timestamp = null, $wait_for_all = False, |
||
| 289 | $sl = null, $timeout = null) |
||
| 290 | { |
||
| 291 | /* Construct parameters string */ |
||
| 292 | $ret = $this->parsePasswordOTP($token); |
||
| 293 | if (!$ret) { |
||
| 294 | return PEAR::raiseError('Could not parse Yubikey OTP'); |
||
| 295 | } |
||
| 296 | $params = array('id'=>$this->_id, |
||
| 297 | 'otp'=>$ret['otp'], |
||
| 298 | 'nonce'=>md5(uniqid(rand()))); |
||
| 299 | /* Take care of protocol version 2 parameters */ |
||
| 300 | if ($use_timestamp) { |
||
| 301 | $params['timestamp'] = 1; |
||
| 302 | } |
||
| 303 | if ($sl) { |
||
| 304 | $params['sl'] = $sl; |
||
| 305 | } |
||
| 306 | if ($timeout) { |
||
| 307 | $params['timeout'] = $timeout; |
||
| 308 | } |
||
| 309 | ksort($params); |
||
| 310 | $parameters = ''; |
||
| 311 | foreach ($params as $p=>$v) { |
||
| 312 | $parameters .= "&".$p."=".$v; |
||
| 313 | } |
||
| 314 | $parameters = ltrim($parameters, "&"); |
||
| 315 | |||
| 316 | /* Generate signature. */ |
||
| 317 | if ($this->_key <> "") { |
||
| 318 | $signature = base64_encode(hash_hmac('sha1', $parameters, |
||
| 319 | $this->_key, true)); |
||
| 320 | $signature = preg_replace('/\+/', '%2B', $signature); |
||
| 321 | $parameters .= '&h='.$signature; |
||
| 322 | } |
||
| 323 | |||
| 324 | /* Generate and prepare request. */ |
||
| 325 | $this->_lastquery = null; |
||
| 326 | $this->URLreset(); |
||
| 327 | $mh = curl_multi_init(); |
||
| 328 | $ch = array(); |
||
| 329 | while ($URLpart = $this->getNextURLpart()) |
||
| 330 | { |
||
| 331 | /* Support https. */ |
||
| 332 | if ($this->_https) { |
||
| 333 | $query = "https://"; |
||
| 334 | } else { |
||
| 335 | $query = "http://"; |
||
| 336 | } |
||
| 337 | $query .= $URLpart."?".$parameters; |
||
| 338 | |||
| 339 | if ($this->_lastquery) { $this->_lastquery .= " "; } |
||
| 340 | $this->_lastquery .= $query; |
||
| 341 | |||
| 342 | $handle = curl_init($query); |
||
| 343 | curl_setopt($handle, CURLOPT_USERAGENT, "PEAR Auth_Yubico"); |
||
| 344 | curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); |
||
| 345 | if (!$this->_httpsverify) { |
||
| 346 | curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, 0); |
||
| 347 | curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0); |
||
| 348 | } |
||
| 349 | curl_setopt($handle, CURLOPT_FAILONERROR, true); |
||
| 350 | /* If timeout is set, we better apply it here as well |
||
| 351 | in case the validation server fails to follow it. |
||
| 352 | */ |
||
| 353 | if ($timeout) { |
||
| 354 | curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); |
||
| 355 | } |
||
| 356 | curl_multi_add_handle($mh, $handle); |
||
| 357 | |||
| 358 | $ch[(int) $handle] = $handle; |
||
| 359 | } |
||
| 360 | |||
| 361 | /* Execute and read request. */ |
||
| 362 | $this->_response = null; |
||
| 363 | $replay = False; |
||
| 364 | $valid = False; |
||
| 365 | do { |
||
| 366 | /* Let curl do its work. */ |
||
| 367 | while (($mrc = curl_multi_exec($mh, $active)) |
||
| 368 | == CURLM_CALL_MULTI_PERFORM) |
||
| 369 | ; |
||
| 370 | |||
| 371 | while ($info = curl_multi_info_read($mh)) { |
||
| 372 | if ($info['result'] == CURLE_OK) { |
||
| 373 | |||
| 374 | /* We have a complete response from one server. */ |
||
| 375 | |||
| 376 | $str = curl_multi_getcontent($info['handle']); |
||
| 377 | $cinfo = curl_getinfo($info['handle']); |
||
| 378 | |||
| 379 | if ($wait_for_all) { # Better debug info |
||
| 380 | $this->_response .= 'URL='.$cinfo['url']."\n" |
||
| 381 | . $str."\n"; |
||
| 382 | } |
||
| 383 | |||
| 384 | if (preg_match("/status=([a-zA-Z0-9_]+)/", $str, $out)) { |
||
| 385 | $status = $out[1]; |
||
| 386 | |||
| 387 | /* |
||
| 388 | * There are 3 cases. |
||
| 389 | * |
||
| 390 | * 1. OTP or Nonce values doesn't match - ignore |
||
| 391 | * response. |
||
| 392 | * |
||
| 393 | * 2. We have a HMAC key. If signature is invalid - |
||
| 394 | * ignore response. Return if status=OK or |
||
| 395 | * status=REPLAYED_OTP. |
||
| 396 | * |
||
| 397 | * 3. Return if status=OK or status=REPLAYED_OTP. |
||
| 398 | */ |
||
| 399 | if (!preg_match("/otp=".$params['otp']."/", $str) || |
||
| 400 | !preg_match("/nonce=".$params['nonce']."/", $str)) { |
||
| 401 | /* Case 1. Ignore response. */ |
||
| 402 | } elseif ($this->_key <> "") { |
||
| 403 | /* Case 2. Verify signature first */ |
||
| 404 | $rows = explode("\r\n", trim($str)); |
||
| 405 | $response = array(); |
||
| 406 | while (list($key, $val) = each($rows)) { |
||
| 407 | /* = is also used in BASE64 encoding so we only replace the first = by # which is not used in BASE64 */ |
||
| 408 | $val = preg_replace('/=/', '#', $val, 1); |
||
| 409 | $row = explode("#", $val); |
||
| 410 | $response[$row[0]] = $row[1]; |
||
| 411 | } |
||
| 412 | |||
| 413 | $parameters = array('nonce', 'otp', 'sessioncounter', 'sessionuse', 'sl', 'status', 't', 'timeout', 'timestamp'); |
||
| 414 | sort($parameters); |
||
| 415 | $check = Null; |
||
| 416 | foreach ($parameters as $param) { |
||
| 417 | if (array_key_exists($param, $response)) { |
||
| 418 | if ($check) { |
||
| 419 | $check = $check.'&'; |
||
| 420 | } |
||
| 421 | $check = $check.$param.'='.$response[$param]; |
||
| 422 | } |
||
| 423 | } |
||
| 424 | |||
| 425 | $checksignature = |
||
| 426 | base64_encode(hash_hmac('sha1', utf8_encode($check), |
||
| 427 | $this->_key, true)); |
||
| 428 | |||
| 429 | if ($response['h'] == $checksignature) { |
||
| 430 | if ($status == 'REPLAYED_OTP') { |
||
| 431 | if (!$wait_for_all) { $this->_response = $str; } |
||
| 432 | $replay = True; |
||
| 433 | } |
||
| 434 | if ($status == 'OK') { |
||
| 435 | if (!$wait_for_all) { $this->_response = $str; } |
||
| 436 | $valid = True; |
||
| 437 | } |
||
| 438 | } |
||
| 439 | } else { |
||
| 440 | /* Case 3. We check the status directly */ |
||
| 441 | if ($status == 'REPLAYED_OTP') { |
||
| 442 | if (!$wait_for_all) { $this->_response = $str; } |
||
| 443 | $replay = True; |
||
| 444 | } |
||
| 445 | if ($status == 'OK') { |
||
| 446 | if (!$wait_for_all) { $this->_response = $str; } |
||
| 447 | $valid = True; |
||
| 448 | } |
||
| 449 | } |
||
| 450 | } |
||
| 451 | if (!$wait_for_all && ($valid || $replay)) |
||
| 452 | { |
||
| 453 | /* We have status=OK or status=REPLAYED_OTP, return. */ |
||
| 454 | foreach ($ch as $h) { |
||
| 455 | curl_multi_remove_handle($mh, $h); |
||
| 456 | curl_close($h); |
||
| 457 | } |
||
| 458 | curl_multi_close($mh); |
||
| 459 | if ($replay) { |
||
| 460 | return PEAR::raiseError('REPLAYED_OTP'); |
||
| 461 | } |
||
| 462 | if ($valid) { |
||
| 463 | return true; |
||
| 464 | } |
||
| 465 | return PEAR::raiseError($status); |
||
| 466 | } |
||
| 467 | |||
| 468 | curl_multi_remove_handle($mh, $info['handle']); |
||
| 469 | curl_close($info['handle']); |
||
| 470 | unset ($ch[(int) $info['handle']]); |
||
| 471 | } |
||
| 472 | curl_multi_select($mh); |
||
| 473 | } |
||
| 474 | } while ($active); |
||
| 475 | |||
| 476 | /* Typically this is only reached for wait_for_all=true or |
||
| 477 | * when the timeout is reached and there is no |
||
| 478 | * OK/REPLAYED_REQUEST answer (think firewall). |
||
| 479 | */ |
||
| 480 | |||
| 481 | foreach ($ch as $h) { |
||
| 482 | curl_multi_remove_handle($mh, $h); |
||
| 483 | curl_close($h); |
||
| 484 | } |
||
| 485 | curl_multi_close($mh); |
||
| 486 | |||
| 487 | if ($replay) { |
||
| 488 | return PEAR::raiseError('REPLAYED_OTP'); |
||
| 489 | } |
||
| 490 | if ($valid) { |
||
| 491 | return true; |
||
| 492 | } |
||
| 493 | return PEAR::raiseError('NO_VALID_ANSWER'); |
||
| 494 | } |
||
| 495 | } |
||
| 497 |