コード例 #1
0
 /**
  * 
  * @param string $user
  * @param string $byte_array_challenge
  * @param string $wsdl
  * @param string $endpoint
  * @param string $responsys_public_cert_path
  * @param string $client_private_key_path
  */
 public function loginWithCertificate($user, $byte_array_challenge, $wsdl, $endpoint, $responsys_public_cert_path, $client_private_key_path)
 {
     if (self::$isLoggedIn) {
         if ($this->debug) {
             echo "Attempt to loginWithCertificate when already logged in";
         }
         return false;
     }
     // RESPONSYS PUBLIC CERT
     $responsys_certificate_file = file_get_contents($responsys_public_cert_path);
     // PRIVATE KEY REQUIRED FOR ENCRYPTING SERVER CHALLENGE - obtained from openssl cert & key creation process
     $mdixon_certificate_file = file_get_contents($client_private_key_path);
     $byte_array = array();
     $container = array();
     $container2 = array();
     $container3 = array();
     // Convert to integer for java
     $len = strlen($byte_array_challenge);
     for ($i = 0; $i < $len; $i++) {
         $byte_array[] = ord($byte_array_challenge[$i]);
     }
     // Run authServer call to verify user and get a temporary sessionId for login call
     $result = $this->authServer($user, $byte_array, $wsdl, $endpoint);
     //print_r( $result );
     $authId = $result->result->authSessionId;
     $encServerChallenge = $result->result->encryptedClientChallenge;
     $serverChallenge = $result->result->serverChallenge;
     // Hack to deal with null returns in challenge strings ( weak! )
     // The trick is setting the null value to 128 - which should actually be out of range for java since it uses -128 through 127 but it works...
     foreach ($encServerChallenge as $key => $val) {
         $val = trim($val);
         if (isset($val) && $val !== null && $val !== "") {
             $container[] = $val;
         } else {
             $container[] = 128;
         }
     }
     // Now we have to decrypt the binary string
     $decryptMe = $this->packer($container);
     // USE RESP CERT TO DECYRPT THE VALUE AND DIFF ON ORIGINAL STRING VALUE !!!
     // GET A X509 INSTANCE, THEN GET THE PUBLIC KEY FOR openssl_public_decrypt
     $x509 = openssl_x509_read($responsys_certificate_file);
     openssl_x509_export($x509, $newX509);
     $pubKey = openssl_get_publickey($newX509);
     if (openssl_public_decrypt($decryptMe, $decrypted, $pubKey, OPENSSL_PKCS1_PADDING)) {
         $data = $decrypted;
     } else {
         throw new Exception("Failed to decrypt the challenge " . openssl_error_string());
     }
     // Compare the original string to the decrypted data string
     // If this matches then the decryption logic is proper, and we proceed to login call
     if ($byte_array_challenge == $data) {
         // Get the private key for encrypting the return
         $private_key = openssl_get_privatekey($mdixon_certificate_file);
         foreach ($serverChallenge as $j => $b) {
             $val2 = trim($b);
             if (isset($val2) && $val2 !== null && $val2 !== "") {
                 $container2[] = $val2;
             } else {
                 $container2[] = 128;
             }
         }
         $encryptMe = $this->packer($container2);
         if (!openssl_private_encrypt($encryptMe, $encryptedData, $private_key, OPENSSL_PKCS1_PADDING)) {
             throw new Exception("Failed to Encrypt data with Private Key - exiting");
         }
         // Now we have to unpack data which converts unsigned encrypted data to signed byte type
         // to play nice with java signed byte type
         $unpackedData = unpack('c*', $encryptedData);
         // Now iterate through bytes, and set the 128 values to null since API allows / sends nulls
         foreach ($unpackedData as $m => $d) {
             $val3 = trim($d);
             if ($val3 == 128) {
                 $container3[] = null;
             } else {
                 $container3[] = $val3;
             }
         }
         // Now we have all of the parts, set the authId as the session id for the login call, and send in the prepared encrypted server challenge
         // If all goes well we will get a sessionId in the result of the upcoming call.
         $this->setSoapHeaders($authId);
         $this->setSessionCookie();
         $loginWithCertObj = new loginWithCertificate($container3);
         $result = $this->execute($loginWithCertObj);
         if ($result) {
             $this->sessionId = $result->result->sessionId;
             if (!$this->setSoapHeaders() || !$this->setSessionCookie()) {
                 throw new Exception(self::SOAP_ERROR_HEADER);
             }
             self::$isLoggedIn = true;
         } else {
             throw new Exception(self::SOAP_ERROR_LOGIN);
         }
         //print_r( $result );
         return $result;
     } else {
         throw new SoapFault("Problem during handshake - exiting");
     }
 }