geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/HandShake.java
public static Properties readCredentials(DataInputStream dis, DataOutputStream dos,
      DistributedSystem system, SecurityService securityService)
      throws GemFireSecurityException, IOException {

    boolean requireAuthentication = securityService.isClientSecurityRequired();
    Properties credentials = null;
    try {
      byte secureMode = dis.readByte();
      throwIfMissingRequiredCredentials(requireAuthentication, secureMode != CREDENTIALS_NONE);
      if (secureMode == CREDENTIALS_NORMAL) {
        if (requireAuthentication) {
          credentials = DataSerializer.readProperties(dis);
        } else {
          DataSerializer.readProperties(dis); // ignore the credentials
        }
      } else if (secureMode == CREDENTIALS_DHENCRYPT) {
        boolean sendAuthentication = dis.readBoolean();
        InternalLogWriter securityLogWriter = (InternalLogWriter) system.getSecurityLogWriter();
        // Get the symmetric encryption algorithm to be used
        String skAlgo = DataSerializer.readString(dis);
        // Get the public key of the other side
        byte[] keyBytes = DataSerializer.readByteArray(dis);
        byte[] challenge = null;
        PublicKey pubKey = null;
        if (requireAuthentication) {
          // Generate PublicKey from encoded form
          X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
          KeyFactory keyFact = KeyFactory.getInstance("DH");
          pubKey = keyFact.generatePublic(x509KeySpec);

          // Send the public key to other side
          keyBytes = dhPublicKey.getEncoded();
          challenge = new byte[64];
          random.nextBytes(challenge);

          // If the server has to also authenticate itself then
          // sign the challenge from client.
          if (sendAuthentication) {
            // Get the challenge string from client
            byte[] clientChallenge = DataSerializer.readByteArray(dis);
            if (privateKeyEncrypt == null) {
              throw new AuthenticationFailedException(
                  LocalizedStrings.HandShake_SERVER_PRIVATE_KEY_NOT_AVAILABLE_FOR_CREATING_SIGNATURE
                      .toLocalizedString());
            }
            // Sign the challenge from client and send it to the client
            Signature sig = Signature.getInstance(privateKeySignAlgo);
            sig.initSign(privateKeyEncrypt);
            sig.update(clientChallenge);
            byte[] signedBytes = sig.sign();
            dos.writeByte(REPLY_OK);
            DataSerializer.writeByteArray(keyBytes, dos);
            // DataSerializer.writeString(privateKeyAlias, dos);
            DataSerializer.writeString(privateKeySubject, dos);
            DataSerializer.writeByteArray(signedBytes, dos);
            securityLogWriter.fine("HandShake: sent the signed client challenge");
          } else {
            // These two lines should not be moved before the if{} statement in
            // a common block for both if...then...else parts. This is to handle
            // the case when an AuthenticationFailedException is thrown by the
            // if...then part when sending the signature.
            dos.writeByte(REPLY_OK);
            DataSerializer.writeByteArray(keyBytes, dos);
          }
          // Now send the server challenge
          DataSerializer.writeByteArray(challenge, dos);
          securityLogWriter.fine("HandShake: sent the public key and challenge");
          dos.flush();

          // Read and decrypt the credentials
          byte[] encBytes = DataSerializer.readByteArray(dis);
          KeyAgreement ka = KeyAgreement.getInstance("DH");
          ka.init(dhPrivateKey);
          ka.doPhase(pubKey, true);

          Cipher decrypt;

          int keysize = getKeySize(skAlgo);
          int blocksize = getBlockSize(skAlgo);

          if (keysize == -1 || blocksize == -1) {
            SecretKey sKey = ka.generateSecret(skAlgo);
            decrypt = Cipher.getInstance(skAlgo);
            decrypt.init(Cipher.DECRYPT_MODE, sKey);
          } else {
            String algoStr = getDhAlgoStr(skAlgo);

            byte[] sKeyBytes = ka.generateSecret();
            SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr);
            IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize);

            decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding");
            decrypt.init(Cipher.DECRYPT_MODE, sks, ivps);
          }

          byte[] credentialBytes = decrypt.doFinal(encBytes);
          ByteArrayInputStream bis = new ByteArrayInputStream(credentialBytes);
          DataInputStream dinp = new DataInputStream(bis);
          credentials = DataSerializer.readProperties(dinp);
          byte[] challengeRes = DataSerializer.readByteArray(dinp);
          // Check the challenge string
          if (!Arrays.equals(challenge, challengeRes)) {
            throw new AuthenticationFailedException(
                LocalizedStrings.HandShake_MISMATCH_IN_CHALLENGE_BYTES_MALICIOUS_CLIENT
                    .toLocalizedString());
          }
          dinp.close();
        } else {
          if (sendAuthentication) {
            // Read and ignore the client challenge
            DataSerializer.readByteArray(dis);
          }
          dos.writeByte(REPLY_AUTH_NOT_REQUIRED);
          dos.flush();
        }
      } else if (secureMode == SECURITY_MULTIUSER_NOTIFICATIONCHANNEL) {
        // hitesh there will be no credential CCP will get credential(Principal) using
        // ServerConnection..
        logger.debug("readCredential where multiuser mode creating callback connection");
      }
    } catch (IOException ex) {
      throw ex;
    } catch (GemFireSecurityException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new AuthenticationFailedException(
          LocalizedStrings.HandShake_FAILURE_IN_READING_CREDENTIALS.toLocalizedString(), ex);
    }
    return credentials;
  }
// This assumes that authentication is the last piece of info in handshake
This assumes that authentication is the last piece of info in handshake
This assumes that authentication is the last piece of info in handshake
public static Properties readCredentials(DataInputStream dis, DataOutputStream dos,
      DistributedSystem system, SecurityService securityService)
      throws GemFireSecurityException, IOException {
    boolean requireAuthentication = securityService.isClientSecurityRequired();
    Properties credentials = null;
    try {
      byte secureMode = dis.readByte();
      throwIfMissingRequiredCredentials(requireAuthentication, secureMode != CREDENTIALS_NONE);
      if (secureMode == CREDENTIALS_NORMAL) {
        if (requireAuthentication) {
          credentials = DataSerializer.readProperties(dis);
        } else {
          DataSerializer.readProperties(dis); 
        }
      } else if (secureMode == CREDENTIALS_DHENCRYPT) {
        boolean sendAuthentication = dis.readBoolean();
        InternalLogWriter securityLogWriter = (InternalLogWriter) system.getSecurityLogWriter();
        String skAlgo = DataSerializer.readString(dis);
        byte[] keyBytes = DataSerializer.readByteArray(dis);
        byte[] challenge = null;
        PublicKey pubKey = null;
        if (requireAuthentication) {
          X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
          KeyFactory keyFact = KeyFactory.getInstance("DH");
          pubKey = keyFact.generatePublic(x509KeySpec);
          keyBytes = dhPublicKey.getEncoded();
          challenge = new byte[64];
          random.nextBytes(challenge);
          if (sendAuthentication) {
            byte[] clientChallenge = DataSerializer.readByteArray(dis);
            if (privateKeyEncrypt == null) {
              throw new AuthenticationFailedException(
                  LocalizedStrings.HandShake_SERVER_PRIVATE_KEY_NOT_AVAILABLE_FOR_CREATING_SIGNATURE
                      .toLocalizedString());
            }
            Signature sig = Signature.getInstance(privateKeySignAlgo);
            sig.initSign(privateKeyEncrypt);
            sig.update(clientChallenge);
            byte[] signedBytes = sig.sign();
            dos.writeByte(REPLY_OK);
            DataSerializer.writeByteArray(keyBytes, dos);
            DataSerializer.writeString(privateKeySubject, dos);
            DataSerializer.writeByteArray(signedBytes, dos);
            securityLogWriter.fine("HandShake: sent the signed client challenge");
          } else {
            dos.writeByte(REPLY_OK);
            DataSerializer.writeByteArray(keyBytes, dos);
          }
          DataSerializer.writeByteArray(challenge, dos);
          securityLogWriter.fine("HandShake: sent the public key and challenge");
          dos.flush();
          byte[] encBytes = DataSerializer.readByteArray(dis);
          KeyAgreement ka = KeyAgreement.getInstance("DH");
          ka.init(dhPrivateKey);
          ka.doPhase(pubKey, true);
          Cipher decrypt;
          int keysize = getKeySize(skAlgo);
          int blocksize = getBlockSize(skAlgo);
          if (keysize == -1 || blocksize == -1) {
            SecretKey sKey = ka.generateSecret(skAlgo);
            decrypt = Cipher.getInstance(skAlgo);
            decrypt.init(Cipher.DECRYPT_MODE, sKey);
          } else {
            String algoStr = getDhAlgoStr(skAlgo);
            byte[] sKeyBytes = ka.generateSecret();
            SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr);
            IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize);
            decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding");
            decrypt.init(Cipher.DECRYPT_MODE, sks, ivps);
          }
          byte[] credentialBytes = decrypt.doFinal(encBytes);
          ByteArrayInputStream bis = new ByteArrayInputStream(credentialBytes);
          DataInputStream dinp = new DataInputStream(bis);
          credentials = DataSerializer.readProperties(dinp);
          byte[] challengeRes = DataSerializer.readByteArray(dinp);
          if (!Arrays.equals(challenge, challengeRes)) {
            throw new AuthenticationFailedException(
                LocalizedStrings.HandShake_MISMATCH_IN_CHALLENGE_BYTES_MALICIOUS_CLIENT
                    .toLocalizedString());
          }
          dinp.close();
        } else {
          if (sendAuthentication) {
            DataSerializer.readByteArray(dis);
          }
          dos.writeByte(REPLY_AUTH_NOT_REQUIRED);
          dos.flush();
        }
      } else if (secureMode == SECURITY_MULTIUSER_NOTIFICATIONCHANNEL) {
        logger.debug("readCredential where multiuser mode creating callback connection");
      }
    } catch (IOException ex) {
      throw ex;
    } catch (GemFireSecurityException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new AuthenticationFailedException(
          LocalizedStrings.HandShake_FAILURE_IN_READING_CREDENTIALS.toLocalizedString(), ex);
    }
    return credentials;
  }
public static Properties readCredentials ( DataInputStream dis , DataOutputStream dos , DistributedSystem system , SecurityService securityService ) throws GemFireSecurityException , IOException { boolean requireAuthentication = securityService . isClientSecurityRequired ( ) ; Properties credentials = null ; try { byte secureMode = dis . readByte ( ) ; throwIfMissingRequiredCredentials ( requireAuthentication , secureMode != CREDENTIALS_NONE ) ; if ( secureMode == CREDENTIALS_NORMAL ) { if ( requireAuthentication ) { credentials = DataSerializer . readProperties ( dis ) ; } else { DataSerializer . readProperties ( dis ) ; } } else if ( secureMode == CREDENTIALS_DHENCRYPT ) { boolean sendAuthentication = dis . readBoolean ( ) ; InternalLogWriter securityLogWriter = ( InternalLogWriter ) system . getSecurityLogWriter ( ) ; String skAlgo = DataSerializer . readString ( dis ) ; byte [ ] keyBytes = DataSerializer . readByteArray ( dis ) ; byte [ ] challenge = null ; PublicKey pubKey = null ; if ( requireAuthentication ) { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec ( keyBytes ) ; KeyFactory keyFact = KeyFactory . getInstance ( "DH" ) ; pubKey = keyFact . generatePublic ( x509KeySpec ) ; keyBytes = dhPublicKey . getEncoded ( ) ; challenge = new byte [ 64 ] ; random . nextBytes ( challenge ) ; if ( sendAuthentication ) { byte [ ] clientChallenge = DataSerializer . readByteArray ( dis ) ; if ( privateKeyEncrypt == null ) { throw new AuthenticationFailedException ( LocalizedStrings . HandShake_SERVER_PRIVATE_KEY_NOT_AVAILABLE_FOR_CREATING_SIGNATURE . toLocalizedString ( ) ) ; } Signature sig = Signature . getInstance ( privateKeySignAlgo ) ; sig . initSign ( privateKeyEncrypt ) ; sig . update ( clientChallenge ) ; byte [ ] signedBytes = sig . sign ( ) ; dos . writeByte ( REPLY_OK ) ; DataSerializer . writeByteArray ( keyBytes , dos ) ; DataSerializer . writeString ( privateKeySubject , dos ) ; DataSerializer . writeByteArray ( signedBytes , dos ) ; securityLogWriter . fine ( "HandShake: sent the signed client challenge" ) ; } else { dos . writeByte ( REPLY_OK ) ; DataSerializer . writeByteArray ( keyBytes , dos ) ; } DataSerializer . writeByteArray ( challenge , dos ) ; securityLogWriter . fine ( "HandShake: sent the public key and challenge" ) ; dos . flush ( ) ; byte [ ] encBytes = DataSerializer . readByteArray ( dis ) ; KeyAgreement ka = KeyAgreement . getInstance ( "DH" ) ; ka . init ( dhPrivateKey ) ; ka . doPhase ( pubKey , true ) ; Cipher decrypt ; int keysize = getKeySize ( skAlgo ) ; int blocksize = getBlockSize ( skAlgo ) ; if ( keysize == - 1 || blocksize == - 1 ) { SecretKey sKey = ka . generateSecret ( skAlgo ) ; decrypt = Cipher . getInstance ( skAlgo ) ; decrypt . init ( Cipher . DECRYPT_MODE , sKey ) ; } else { String algoStr = getDhAlgoStr ( skAlgo ) ; byte [ ] sKeyBytes = ka . generateSecret ( ) ; SecretKeySpec sks = new SecretKeySpec ( sKeyBytes , 0 , keysize , algoStr ) ; IvParameterSpec ivps = new IvParameterSpec ( sKeyBytes , keysize , blocksize ) ; decrypt = Cipher . getInstance ( algoStr + "/CBC/PKCS5Padding" ) ; decrypt . init ( Cipher . DECRYPT_MODE , sks , ivps ) ; } byte [ ] credentialBytes = decrypt . doFinal ( encBytes ) ; ByteArrayInputStream bis = new ByteArrayInputStream ( credentialBytes ) ; DataInputStream dinp = new DataInputStream ( bis ) ; credentials = DataSerializer . readProperties ( dinp ) ; byte [ ] challengeRes = DataSerializer . readByteArray ( dinp ) ; if ( ! Arrays . equals ( challenge , challengeRes ) ) { throw new AuthenticationFailedException ( LocalizedStrings . HandShake_MISMATCH_IN_CHALLENGE_BYTES_MALICIOUS_CLIENT . toLocalizedString ( ) ) ; } dinp . close ( ) ; } else { if ( sendAuthentication ) { DataSerializer . readByteArray ( dis ) ; } dos . writeByte ( REPLY_AUTH_NOT_REQUIRED ) ; dos . flush ( ) ; } } else if ( secureMode == SECURITY_MULTIUSER_NOTIFICATIONCHANNEL ) { logger . debug ( "readCredential where multiuser mode creating callback connection" ) ; } } catch ( IOException ex ) { throw ex ; } catch ( GemFireSecurityException ex ) { throw ex ; } catch ( Exception ex ) { throw new AuthenticationFailedException ( LocalizedStrings . HandShake_FAILURE_IN_READING_CREDENTIALS . toLocalizedString ( ) , ex ) ; } return credentials ; }
This assumes that authentication is the last piece of info in handshake
This assumes that authentication is the last piece of info in handshake
// ignore the credentials // Get the symmetric encryption algorithm to be used // Get the public key of the other side // Generate PublicKey from encoded form // Send the public key to other side // If the server has to also authenticate itself then // sign the challenge from client. // Get the challenge string from client // Sign the challenge from client and send it to the client // DataSerializer.writeString(privateKeyAlias, dos); // These two lines should not be moved before the if{} statement in // a common block for both if...then...else parts. This is to handle // the case when an AuthenticationFailedException is thrown by the // if...then part when sending the signature. // Now send the server challenge // Read and decrypt the credentials // Check the challenge string // Read and ignore the client challenge // hitesh there will be no credential CCP will get credential(Principal) using // ServerConnection..