@Test
  public void testServerNotTrustedByClient() throws Exception {
    final SaslClientFactory clientFactory = obtainSaslClientFactory(EntitySaslClientFactory.class);
    assertNotNull(clientFactory);

    final SaslServer saslServer =
        createSaslServer(
            SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
            "testserver1.example.com",
            getX509KeyManager(serverKeyStore, KEYSTORE_PASSWORD),
            getX509TrustManager(serverTrustStore));

    final String[] mechanisms =
        new String[] {SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC};
    CallbackHandler cbh =
        createClientCallbackHandler(
            mechanisms, clientKeyStore, CLIENT_KEYSTORE_ALIAS, KEYSTORE_PASSWORD, null);
    final SaslClient saslClient =
        clientFactory.createSaslClient(
            mechanisms,
            null,
            "test",
            "testserver1.example.com",
            Collections.<String, Object>emptyMap(),
            cbh);

    byte[] message = saslServer.evaluateResponse(new byte[0]);
    message = saslClient.evaluateChallenge(message);
    message = saslServer.evaluateResponse(message);
    try {
      saslClient.evaluateChallenge(message);
      fail("Expected SaslException not thrown");
    } catch (SaslException expected) {
    }
  }
  @Test
  public void testServerAuthDirect_Client() {
    SaslClientFactory factory = obtainSaslClientFactory(EntitySaslClientFactory.class);
    assertNotNull("SaslClientFactory not registered", factory);

    String[] mechanisms;
    Map<String, Object> props = new HashMap<String, Object>();

    // No properties set
    mechanisms = factory.getMechanismNames(props);
    assertMechanisms(
        new String[] {
          SaslMechanismInformation.Names.IEC_ISO_9798_U_RSA_SHA1_ENC,
              SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
              SaslMechanismInformation.Names.IEC_ISO_9798_U_DSA_SHA1,
          SaslMechanismInformation.Names.IEC_ISO_9798_M_DSA_SHA1,
              SaslMechanismInformation.Names.IEC_ISO_9798_U_ECDSA_SHA1,
              SaslMechanismInformation.Names.IEC_ISO_9798_M_ECDSA_SHA1
        },
        mechanisms);

    // Request server auth
    props.put(Sasl.SERVER_AUTH, Boolean.toString(true));
    mechanisms = factory.getMechanismNames(props);
    assertMechanisms(
        new String[] {
          SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
          SaslMechanismInformation.Names.IEC_ISO_9798_M_DSA_SHA1,
          SaslMechanismInformation.Names.IEC_ISO_9798_M_ECDSA_SHA1
        },
        mechanisms);
  }
  @Test
  public void testMutualAuthenticationWithDNSInCNField() throws Exception {
    // Although specifying a DNS name using the Common Name field has been deprecated, it is
    // still used in practice (e.g., see http://tools.ietf.org/html/rfc2818). This test makes
    // sure that general name matching during authentication still works in this case.
    final SaslClientFactory clientFactory = obtainSaslClientFactory(EntitySaslClientFactory.class);
    assertNotNull(clientFactory);

    final KeyStore keyStore = loadKeyStore(serverKeyStore);
    final Certificate[] certificateChain = keyStore.getCertificateChain("dnsInCNServer");
    final SaslServer saslServer =
        createSaslServer(
            SaslMechanismInformation.Names.IEC_ISO_9798_M_DSA_SHA1,
            "testserver2.example.com",
            getX509TrustManager(serverTrustStore),
            (PrivateKey) keyStore.getKey("dnsInCNServer", KEYSTORE_PASSWORD),
            Arrays.copyOf(certificateChain, certificateChain.length, X509Certificate[].class));

    final String[] mechanisms =
        new String[] {SaslMechanismInformation.Names.IEC_ISO_9798_M_DSA_SHA1};
    CallbackHandler cbh =
        createClientCallbackHandler(
            mechanisms,
            clientKeyStore,
            "dnsInCNClient",
            KEYSTORE_PASSWORD,
            getX509TrustManager(clientTrustStore));
    final SaslClient saslClient =
        clientFactory.createSaslClient(
            mechanisms,
            null,
            "test",
            "testserver2.example.com",
            Collections.<String, Object>emptyMap(),
            cbh);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    byte[] message = saslServer.evaluateResponse(new byte[0]);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    message = saslClient.evaluateChallenge(message);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    message = saslServer.evaluateResponse(message);
    assertNotNull(message);

    message = saslClient.evaluateChallenge(message);
    assertNull(message);
    assertTrue(saslClient.isComplete());
    assertTrue(saslServer.isComplete());
    assertEquals(
        "cn=testclient2.example.com,ou=jboss,o=red hat,l=raleigh,st=north carolina,c=us",
        saslServer.getAuthorizationID());
  }
  @Test
  public void testSimpleMutualSha1WithRsaAuthentication() throws Exception {
    final SaslClientFactory clientFactory = obtainSaslClientFactory(EntitySaslClientFactory.class);
    assertNotNull(clientFactory);

    final SaslServer saslServer =
        createSaslServer(
            SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
            "testserver1.example.com",
            getX509KeyManager(serverKeyStore, KEYSTORE_PASSWORD),
            getX509TrustManager(serverTrustStore));

    final String[] mechanisms =
        new String[] {SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC};
    CallbackHandler cbh =
        createClientCallbackHandler(
            mechanisms,
            clientKeyStore,
            CLIENT_KEYSTORE_ALIAS,
            KEYSTORE_PASSWORD,
            getX509TrustManager(clientTrustStore));
    final SaslClient saslClient =
        clientFactory.createSaslClient(
            mechanisms,
            null,
            "test",
            "testserver1.example.com",
            Collections.<String, Object>emptyMap(),
            cbh);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    byte[] message = saslServer.evaluateResponse(new byte[0]);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    message = saslClient.evaluateChallenge(message);
    assertFalse(saslServer.isComplete());
    assertFalse(saslClient.isComplete());

    message = saslServer.evaluateResponse(message);
    assertNotNull(message);
    message = saslClient.evaluateChallenge(message);
    assertNull(message);
    assertTrue(saslClient.isComplete());
    assertTrue(saslServer.isComplete());
    assertEquals(
        "cn=test client 1,ou=jboss,o=red hat,l=raleigh,st=north carolina,c=us",
        saslServer.getAuthorizationID());
  }
  @Ignore // todo: this test could be modified to use the wrong key of the write algorithm, or it
          // could be removed
  @Test
  public void testServerPrivateKeyPublicKeyMismatch() throws Exception {
    final SaslClientFactory clientFactory = obtainSaslClientFactory(EntitySaslClientFactory.class);
    assertNotNull(clientFactory);

    // A certificate that does not correspond to the server's private key will be used
    final KeyStore keyStore = loadKeyStore(serverKeyStore);
    final Certificate[] certificateChain = keyStore.getCertificateChain(WRONG_KEYSTORE_ALIAS);
    final SaslServer saslServer =
        createSaslServer(
            SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
            "testserver1.example.com",
            getX509TrustManager(serverTrustStore),
            (PrivateKey) keyStore.getKey(SERVER_KEYSTORE_ALIAS, KEYSTORE_PASSWORD),
            Arrays.copyOf(certificateChain, certificateChain.length, X509Certificate[].class));

    final String[] mechanisms =
        new String[] {SaslMechanismInformation.Names.IEC_ISO_9798_M_RSA_SHA1_ENC};
    CallbackHandler cbh =
        createClientCallbackHandler(
            mechanisms,
            clientKeyStore,
            CLIENT_KEYSTORE_ALIAS,
            KEYSTORE_PASSWORD,
            getX509TrustManager(clientTrustStore));
    final SaslClient saslClient =
        clientFactory.createSaslClient(
            mechanisms, null, "test", "", Collections.<String, Object>emptyMap(), cbh);

    byte[] message = saslServer.evaluateResponse(new byte[0]);
    message = saslClient.evaluateChallenge(message);
    message = saslServer.evaluateResponse(message);
    try {
      saslClient.evaluateChallenge(message);
      fail("Expected SaslException not thrown");
    } catch (SaslException expected) {
    }
  }