Hi, I'm having a problem with an OpenSSL client and server application I wrote. Client 1 uses certificate A and client 2 uses certificate B.
I create a CA file on the server that contains A followed by B. In this c ase, client 1 works correctly and client 2 does not. If I change the CA file such that the file contains B followed by A, now client 2 works correctly and client 1 does not. I don't know if this is a problem on the server or the client. My first thought is that it's a server problem and for some reason it's only using the first certificate in the CA file (but I'm using the SSL_CTX_set_client_CA_list() call). It could be something I'm not doing on the client side where when the server sends the CAs to the client, maybe it's only looking at the first certificate and not seeing its certificate? If anyone can see what I'm missing to allow multiple certificates to work for a given server, I'm grateful for the help! Here is the server code block: if (SSL_library_init() != 1) { throw new SSLServerError("Error initializing SSL library!", -1); } // Store the cert file name and path if (strlen(sslCertFile) > sizeof(rpdCertFile)) { throw new SSLServerError("Server cert file path too large!", -1); } strcpy(rpdCertFile, sslCertFile); // Store the key file name and path if (strlen(sslKeyFile) > sizeof(rpdKeyFile)) { throw new SSLServerError("Server key file path too large!", -1); } strcpy(rpdKeyFile, sslKeyFile); // Store the CA file name and path if (strlen(sslCAFile) > sizeof(rpdCAFile)) { throw new SSLServerError("Server CA file path too large!", -1); } strcpy(rpdCAFile, sslCAFile); // Initialize the OpenSSL environment ERR_clear_error(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // ERR_load_BIO_strings(); // ERR_load_SSL_strings(); // Create the server instance and context method = SSLv3_server_method(); // DBG("Returned method pointer = %p", method); if ((ctx = SSL_CTX_new(method)) == NULL) { throw new SSLServerError("Error creating SSL ctx object", errno); } DBG("SSLSrvr: Set valid ciphers list to [%s]", SRVR_CIPHER_LIST); if ((err = SSL_CTX_set_cipher_list(ctx, SRVR_CIPHER_LIST) != 1)) { MESSAGE("***Error %d setting cipher list", err); SSL_CTX_free(ctx); throw new SSLServerError("Error setting cipher list", err); } // Indicate the certificate file to be used DBG("SSLSrvr: Certificate file we're using is [%s]", rpdCertFile); if ((err = SSL_CTX_use_certificate_file(ctx, rpdCertFile, SSL_FILETYPE_PEM) != 1)) { MESSAGE("***ERROR %d setting cert file %s: %s", err, rpdCertFile, strerror(errno)); SSL_CTX_free(ctx); throw new SSLServerError("Error setting cert file", err); } #if 0 // Our private key doesn't contain any encrypted data // Load the password for the Private Key SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)KEY_PASSWD); #endif // Indicate the key file to be used DBG("SSLSrvr: Private key file we're using is [%s]", rpdKeyFile); if (SSL_CTX_use_PrivateKey_file(ctx, rpdKeyFile, SSL_FILETYPE_PEM) <= 0){ MESSAGE("***ERROR %d setting private key file %s: %s", err, rpdKeyFile, strerror(errno)); SSL_CTX_free(ctx); throw new SSLServerError("Error setting private key file", errno); } // Make sure the key and certificate file match if (!SSL_CTX_check_private_key(ctx)) { MESSAGE("***ERROR private key doesn't match the cert public key!"); SSL_CTX_free(ctx); throw new SSLServerError("Error setting private key file", errno); } // Set the list of trusted CAs based on the file and/or directory // provided. The NULL is the CA directory if the caller wishes to // separate the file name from the directory path. DBG("SSLSrvr: Trusted CAs file we're using is [%s]", rpdCAFile); if (SSL_CTX_load_verify_locations(ctx, rpdCAFile, NULL) < 1) { MESSAGE("***ERROR verifying CA file/dir location [%s][%s]", rpdCAFile, NULL); SSL_CTX_free(ctx); throw new SSLServerError("Error verifying CA locations", errno); } // Load the list of acceptable CAs to send to the client when the // SSL connection request comes in from the SSL client. DBG("SSLSrvr: Set the client CA list with file [%s]", rpdCAFile); SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(rpdCAFile)); // Set for server verification SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); if ((ssl = SSL_new(ctx)) == NULL) { throw new SSLServerError("Error creating SSL structure", errno); } DBG("SSL Server created successfully. Now set file descriptor..."); HEre is the client code block: if (SSL_library_init() != 1) { throw new SSLClientError("Error initializing SSL library!", -1); } // Initialize the OpenSSL environment ERR_clear_error(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // ERR_load_BIO_strings(); // ERR_load_SSL_strings(); // Create the client instance and context method = SSLv3_client_method(); // DBG("Returned method pointer = %p", method); if ((ctx = SSL_CTX_new(method)) == NULL) { throw new SSLClientError("Error creating SSL ctx object", errno); } if (security == OUTSEC_AUTH) { DBG("SSLClient: Set valid ciphers list to [%s]", CLNT_CIPHER_AUTHONLY); if ((err = SSL_CTX_set_cipher_list(ctx, CLNT_CIPHER_AUTHONLY) != 1)) { MESSAGE("***Error %d setting authentication-only cipher list [%s]", err, CLNT_CIPHER_AUTHONLY); SSL_CTX_free(ctx); throw new SSLClientError("Error setting authentication-only cipher list", err); } } else if (security == OUTSEC_ENCRYPT) { DBG("SSLClient: Set valid ciphers list to [%s]", CLNT_CIPHER_ENCRYPT); if ((err = SSL_CTX_set_cipher_list(ctx, CLNT_CIPHER_ENCRYPT) != 1)) { MESSAGE("***Error %d setting full encryption cipher list", err); SSL_CTX_free(ctx); throw new SSLClientError("Error setting full encryption cipher list", err); } } else { MESSAGE("****ERROR: unknown client security setting %d!:", security); throw new SSLClientError("Unknown output security value for SSLClient", err); } // Indicate the certificate file to be used DBG("SSLClient: Certificate file we're using is [%s]", sslCertFile); if ((err = SSL_CTX_use_certificate_file(ctx, sslCertFile, SSL_FILETYPE_PEM) != 1)) { MESSAGE("***ERROR %d setting cert file %s: %s", err, sslCertFile, strerror(errno)); SSL_CTX_free(ctx); throw new SSLClientError("Error setting cert file", err); } #if 0 // Our private key doesn't contain any encrypted data // Load the password for the Private Key SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)KEY_PASSWD); #endif // Indicate the key file to be used DBG("SSLClient: Private key file we're using is [%s]", sslKeyFile); if (SSL_CTX_use_PrivateKey_file(ctx, sslKeyFile, SSL_FILETYPE_PEM) <= 0){ MESSAGE("***ERROR %d setting private key file %s: %s", err, sslKeyFile, strerror(errno)); SSL_CTX_free(ctx); throw new SSLClientError("Error setting private key file", errno); } // Make sure the key and certificate file match if (!SSL_CTX_check_private_key(ctx)) { MESSAGE("***ERROR private key doesn't match the cert public key!"); SSL_CTX_free(ctx); throw new SSLClientError("Error setting private key file", errno); } // Set the list of trusted CAs based on the file and/or directory // provided DBG("SSLClient: Trusted CAs file we're using is [%s]", sslCAFile); if (SSL_CTX_load_verify_locations(ctx, sslCAFile, NULL) < 1) { MESSAGE("***ERROR verifying CA file/dir location [%s]", sslCAFile); SSL_CTX_free(ctx); throw new SSLClientError("Error verifying CA locations", errno); } // Set for server verification SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); if ((ssl = SSL_new(ctx)) == NULL) { throw new SSLClientError("Error creating SSL structure", errno); } DBG("SSL client created successfully."); -- View this message in context: http://old.nabble.com/CA-file-with-multiple-certificates%2C-only-the-1st-one-in-the-file-works-tp28615249p28615249.html Sent from the OpenSSL - User mailing list archive at Nabble.com. ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org