David,

Sorry for the lack of information, let me try to fill in the blanks.

We're using Perl (IO::Socket::SSL) on the sending side to establish a secure
socket to a C agent on the receiving side. The C agent uses native OpenSSL
APIs. On the Perl side, we create a TCP socket and then do a startSSL
afterwards. The same exact code works fine with Perl running on Windows
going to a C agent on Windows. If fails when Perl is running on Solaris
going to the same C agent on Windows. This same Perl SSL code on Solaris
works fine going to a Java server on Solaris.

# Start the SSL handshake
if (defined($self->{'_sslconf'})) {
$self->{'_Socket'} = BfSSLSocket::startSSL($self->{'_Socket'},
$AddrIsIpv6, $self->{'_sslconf'}) if ($self->{'_Socket'});
}

The above startSSL method basically comes down to this, which works on
Windows.

print "SSL connection to agent.\n";

$sock = IO::Socket::SSL->start_SSL($sock,
'SSL_version' => $ssl_ver,
'SSL_cipher_list' => $ssl_cipher_list,
'SSL_verify_mode' => hex $ssl_verify_mode,
'SSL_use_cert' => $use_cert,
'SSL_key_file' => $key_location,
'SSL_passwd_cb' => sub{return $key_pass},
'SSL_cert_file' => $cert_location,
'SSL_ca_file' => $ca_location,
'SSL_startHandshake' => 0

) || die "Encountered an SSL handshake problem:
".IO::Socket::SSL::errstr();

$sock->connect_SSL;


On the Agent side, there's a dispatch process which receives requests and
spawns a new Agent when it gets the connection. It hands the socket over to
the new Agent process which then starts SSL.

Once the SSL handshake is successful, it goes into the main loop which
starts read/writes.

} else if (NULL != start_SSL() || SS_OK == ssl_state) {
agent_main_loop();
stop_SSL();
}



void *start_SSL(void) {
char err_buf[1024];
const char *sbuf=NULL;
int err=0, rc=0;
X509* client_cert;

BFTRACE("In start_SSL");

/* Specify the context configuration options */
ssl_state = init_CTX();

/* You cannot send a hello in the middle of an SSL handshake. Defer
the SSL hello until the end. Send the TCP hello now, if the state
is SS_OK.
*/
switch (ssl_state) {
case SS_OK:
send_hello(CODE_HELLO);
return NULL;
default:
break; /* Continue to do the SSL handshake. */
}

BFTRACE("Calling SSL_new");
/* Create a new SSL context */
ssl = SSL_new(ctx);
if (NULL == ssl) {
sbuf = ERR_error_string(err, err_buf);
send_msg("SSL", "SSLErrorNoSSL", "s", sbuf);
ssl_state = SS_FAILED;
return NULL;
}

/* hRemote is the duplicate file descriptor from the dispatch thread. */
SSL_set_fd(ssl, hRemote);
SSL_set_accept_state(ssl);
BFTRACE("Calling SSL_accept.");
rc = SSL_accept(ssl);
sprintf(err_buf, "SSL_accept rc=%d (1 is good, 0 is handshake failure,<0
is fatal)", rc);
BFTRACE(err_buf);

if (rc <= 0) {
err = SSL_get_error(ssl, rc);
sprintf(err_buf, "Error code: %d", err);
BFTRACE(err_buf);
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
BFTRACE(err_buf);

switch (err)
{
case SSL_ERROR_NONE:
sprintf(err_buf, "No error reported.");
BFTRACE(err_buf);
break;
case SSL_ERROR_WANT_WRITE:
sprintf(err_buf, "Error: SSL_ERROR_WANT_WRITE");
BFTRACE(err_buf);
break;
case SSL_ERROR_WANT_READ:
sprintf(err_buf, "Error: SSL_ERROR_WANT_READ");
BFTRACE(err_buf);
break;
case SSL_ERROR_WANT_X509_LOOKUP:
sprintf(err_buf, "Error: SSL_ERROR_WANT_X509_LOOKUP");
BFTRACE(err_buf);
break;
case SSL_ERROR_SYSCALL:
sprintf(err_buf, "Error: SSL_ERROR_SYSCALL, errlist: %s",
sys_errlist[errno]);
BFTRACE(err_buf);
break;
case SSL_ERROR_SSL:
sprintf(err_buf, "Error: SSL_ERROR_SSL");
BFTRACE(err_buf);
break;
case SSL_ERROR_ZERO_RETURN:
sprintf(err_buf, "Error: SSL_ERROR_ZERO_RETURN");
BFTRACE(err_buf);
break;
}

ssl_state = SS_FAILED;
SSL_free(ssl);
return NULL;
}

sbuf = SSL_get_cipher_name(ssl);

if (sbuf != NULL) {
sprintf(err_buf, "Cipher chosen: %s", sbuf);
BFTRACE(err_buf);
}

client_cert = SSL_get_peer_certificate (ssl);

if (client_cert != NULL) {
sbuf = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
sprintf(err_buf, "Client certificate: %s", sbuf);
BFTRACE(err_buf);
}

switch (ssl_state) {
case SS_OK:
BFTRACE("ssl_state = SS_OK");
send_hello(CODE_HELLO);
return NULL;
case SS_SECURE:
BFTRACE("ssl_state = SS_SECURE");
send_hello(CODE_SECURE_HELLO);
break;
case SS_CERTIFIED:
BFTRACE("ssl_state = SS_CERTIFIED");
send_hello(CODE_CERTIFIED_HELLO);
break;
default:
return NULL;
}

return ssl;
}

Here's what we should see from the first READ on the sending side:

SSL_ca_file: ./keystore/buildForgeCA.pem
SSL_cert_file: ./keystore/buildForgeCert.pem
SSL_key_file: ./keystore/buildForgeKey.pem
SSL_verify_mode: 0x01
SSL_version: TLSv1
SSL_cipher_list: ALL
SSL_use_cert: 1
Making as SSL connection using socket IO::Socket::INET=GLOB(0x1faf924).
SSL connection to agent.
DEBUG: .../IO/Socket/SSL.pm:1387: new ctx 32890752
DEBUG: .../IO/Socket/SSL.pm:880: dont start handshake:
IO::Socket::SSL=GLOB(0x1f
af924)
DEBUG: .../IO/Socket/SSL.pm:284: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:327: Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:382: ssl handshake done
Socket is of type: ref(IO::Socket::SSL=GLOB(0x1faf924))
READ:202 HELLO TLS - BuildForge Agent v_VERSION_

However, what comes across here is encrypted data instead.

Looks like I'm missing all this debug statements from the failing trace..
This is taken from a successful trace on Windows. Note the "dont start
handshake, then ssl handshake done after

DEBUG: .../IO/Socket/SSL.pm:1387: new ctx 32890752
DEBUG: .../IO/Socket/SSL.pm:880: dont start handshake:
IO::Socket::SSL=GLOB(0x1f
af924)
DEBUG: .../IO/Socket/SSL.pm:284: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:327: Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:382: ssl handshake done
Socket is of type: ref(IO::Socket::SSL=GLOB(0x1faf924))

Hmm.. It appears that this call to IO::Socket::SSL is bombing out somewhere
as it's not starting the handshake at all. The "connect_SSL" should begin
that as shown above.

$sock = IO::Socket::SSL->start_SSL($sock,
'SSL_version' => $ssl_ver,
'SSL_cipher_list' => $ssl_cipher_list,
'SSL_verify_mode' => hex $ssl_verify_mode,
'SSL_use_cert' => $use_cert,
'SSL_key_file' => $key_location,
'SSL_passwd_cb' => sub{return $key_pass},
'SSL_cert_file' => $cert_location,
'SSL_ca_file' => $ca_location,
'SSL_startHandshake' => 0

) || die "Encountered an SSL handshake problem:
".IO::Socket::SSL::errstr();

$sock->connect_SSL;

In the failing state, there's no debug output, although there should be as I
have debug enabled there the same way via eval "use IO::Socket::SSL
qw($debug $inetValue)";. Here's the failing trace again.

Making as SSL connection using socket IO::Socket::INET=GLOB(0x29bd6a0).
SSL connection to agent.
Socket is of type: ref(IO::Socket::SSL=GLOB(0x29bd6a0))
READ:
ReadyLine: .
Agent Connecting...
READ:^V^C^AJ^BF^C^AI^Q╣

In fact, I can see on the same system when it connects successfully to Java,
that the debug prints out for the same code (although I do a
'SSL_startHandshake' => 1 in that case as Java is ready to accept SSL
immediately where as the Agent is not due to the dispatch process).

Making as SSL connection using socket GLOB(0x29d4fc8).
SSL connection to services.
DEBUG: .../IO/Socket/SSL.pm:1387: new ctx 3028608
DEBUG: .../IO/Socket/SSL.pm:872: start handshake
DEBUG: .../IO/Socket/SSL.pm:284: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:327: Net::SSLeay::connect -> 1
DEBUG: .../IO/Socket/SSL.pm:382: ssl handshake done
Socket is of type: ref(IO::Socket::SSL=GLOB(0x29d4fc8))

Any ideas? I will try changing 'SSL_startHandshake' => 1, w/o the
$sock->connect_SSL, but that didn't work from Windows -> Windows in this
environment. It just seems like even the general start_SSL code is not
getting invoked although it's definately going through that path.

Regards,
Pete


David Schwartz wrote:
>
>
>> So I can now see the Solaris side. It appears it gets
>> "gibberish", probably
>> encrypted data. Does anyone know why it would appear that the socket is
>> not decrypting the data? This same code works fine on a Windows system..
>>
>> SSL_ca_file: /opt/bf-567/Platform/keystore/CA.pem
>> SSL_cert_file: /opt/bf-567/Platform/keystore/Cert.pem
>> SSL_key_file: /opt/bf-567/Platform/keystore/Key.pem
>> SSL_verify_mode: 0x01
>> SSL_version: TLSv1
>> SSL_cipher_list: ALL
>> SSL_use_cert: 1
>> Making as SSL connection using socket IO::Socket::INET=GLOB(0x29bdfe8)..
>> SSL connection to agent.
>> Socket is of type: ref(IO::Socket::SSL=GLOB(0x29bdfe8))
>> READ:
>> ReadyLine: .
>> Agent Connecting...
>> READ:

>
> Well, we're kind of back to square one trying to help you, since we're
> looking someplace else entirely now. You really haven't given us any idea
> what your application is actually doing or what these log entries mean.
>
> If the 'READ' entries are displaying raw socket data as text, then it's
> logical that they would make no apparent sense. If it's decrypt SSL
> output,
> then that you're getting any output at all means that your code thinks the
> SSL negotation completed successfully, which is inconsistent with what I
> think you were seeing on the other side (accept failing, therefore no data
> could have been exchanged).
>
> My best guess is that your 'READ' lines are in fact showing raw socket
> data,
> so it's not surprising it looks like gibberish. That you expected it to be
> decrypted data suggests that there's some disconnect between what your
> code
> is doing and what you expect it to be doing.
>
> It's hard to tell without more details.
>
> DS
>
>
> __________________________________________________ ____________________
> OpenSSL Project http://www.openssl.org
> User Support Mailing List openssl-users@openssl.org
> Automated List Manager majordomo@openssl.org
>
>


--
View this message in context: http://www.nabble.com/SSL_ERROR_SYSC...p20344466.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 majordomo@openssl.org