Hi,
I am trying to import a newly connected Unix socket fd using
PR_ImportTCPSocket(), to then use NSS for SSL. I am using the following
sequence:
PR_Init
NSS_InitReadWrite
NSS_SetDomesticPolicy
...
socket
connect
...
PR_ImportTCPSocket
SSL_ImportFD
SSL_OptionSet (SSL_SECURITY)
SSL_OptionSet (SSL_HANDSHAKE_AS_CLIENT)
SSL_SetURL
SSL_ForceHandshake
...
PR_Write
All of these succeed (SECSuccess is returned and PR_GetError returns
0). However when I call PR_Write, only the plaintext message is written
to the socket. The server then terminates the connection.
PR_Write eventually calls ssl2_SendClear (which seems to be a fallback)
to actually write the data. At a glance the sslSocket has no version or
handshake data.
Attached is a quick example which demonstrates the behaviour.
Please help.
-Alex
--
Please do not bomb innocent people.
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <nspr.h>
#include <prthread.h>
#include <private/pprio.h>
#include "nss.h"
#include <ssl.h>
#include <pk11func.h>
int
main (int argc, char **argv)
{
char *nss_dir = "/home/orph/evolution";
PRFileDesc *fdesc, *ssl_fdesc;
int sockfd;
struct hostent *host;
struct sockaddr_in sa;
int result;
if (argc < 3) {
printf ("Usage: testnss hostname content");
exit (1);
}
printf ("Creating socket\n");
sockfd = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf ("socket() failed\n");
exit (1);
}
printf ("Looking up hostname: %s\n", argv [1]);
host = gethostbyname (argv [1]);
if (!host) {
printf ("cannot resolve hostname\n");
exit (1);
}
sa.sin_family = host->h_addrtype;
sa.sin_port = htons (443);
memcpy (&sa.sin_addr, host->h_addr, host->h_length);
printf ("Connecting\n");
if (connect (sockfd, &sa, sizeof (sa)) < 0) {
printf ("connect() failed\n");
exit (1);
}
printf ("Calling PR_Init\n");
PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10);
printf ("Calling NSS_InitReadWrite\n");
if (NSS_InitReadWrite (nss_dir) != SECSuccess) {
if (NSS_NoDB_Init (nss_dir) == SECFailure) {
printf ("Unable to initialize NSS SSL Library.");
exit (1);
}
}
NSS_SetDomesticPolicy ();
SSL_OptionSetDefault (SSL_ENABLE_SSL2, PR_TRUE);
SSL_OptionSetDefault (SSL_ENABLE_SSL3, PR_TRUE);
SSL_OptionSetDefault (SSL_ENABLE_TLS, PR_TRUE);
SSL_OptionSetDefault (SSL_V2_COMPATIBLE_HELLO, PR_TRUE /* maybe? */);
fdesc = PR_ImportTCPSocket (sockfd);
if (!fdesc) {
printf ("SSL socket creation failure");
exit (1);
}
ssl_fdesc = SSL_ImportFD (NULL, fdesc);
if (!ssl_fdesc) {
printf ("SSL object creation failure.");
exit (1);
}
SSL_OptionSet (ssl_fdesc, SSL_SECURITY, PR_TRUE);
SSL_OptionSet (ssl_fdesc, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
SSL_SetURL (ssl_fdesc, argv [1]);
if (SSL_ForceHandshake (ssl_fdesc) == PR_FAILURE) {
printf ("SSL handshake failure.");
exit (1);
}
printf ("Writing: %s\n", argv [2]);
do {
result = PR_Write (ssl_fdesc, argv [2], strlen (argv [2]));
} while (result < 0 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
if (result < 0 || PR_GetError () != 0) {
printf ("Write successful\n");
exit (1);
}
return 0;
}