Thanks for the help, but I'm still having problems. Calling SSL_ForceHandshake following SSL_ResetHandshake fails with -8179. If I avoid this (which I assume shouldn't be needed anyways, as polling should just not return until I can successfully perform IO?) and try polling for write, the poll succeeds but PR_Write returns -1 and sets the nspr error to -8179 again. The same happens with reads.
Please see my new and improved silly test script below :)
-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>
static void
nspr_poll (PRFileDesc *ssl_fdesc, short flags)
{
int result;
PRPollDesc pd;
pd.fd = ssl_fdesc;
pd.in_flags = flags | PR_POLL_ERR | PR_POLL_NVAL | PR_POLL_HUP;
while (1) {
result = PR_Poll (&pd, 1, PR_INTERVAL_NO_WAIT);
if (result == 0)
continue;
if (result == -1) {
printf ("Failed!\n");
exit (1);
} else if (pd.out_flags & PR_POLL_ERR) {
printf ("Poll error!\n");
exit (1);
} else if (pd.out_flags & PR_POLL_NVAL) {
printf ("Invalid FD!\n");
exit (1);
} else if (pd.out_flags & PR_POLL_HUP) {
printf ("Connection Died!\n");
exit (1);
} else {
printf ("OK\n");
break;
}
printf (".");
}
}
int
main (int argc, char **argv)
{
char *nss_dir = "/home/orph/evolution";
PRFileDesc *ssl_fdesc;
int sockfd;
struct hostent *host;
struct sockaddr_in sa;
int result;
unsigned char buf [8192];
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 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? */);
printf ("Calling PR_ImportTCPSocket\n");
ssl_fdesc = PR_ImportTCPSocket (sockfd);
if (!ssl_fdesc) {
printf ("SSL socket creation failure");
exit (1);
}
printf ("Calling SSL_ImportFD\n");
ssl_fdesc = SSL_ImportFD (NULL, ssl_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]);
printf ("Calling SSL_ResetHandshake\n");
if (SSL_ResetHandshake (ssl_fdesc, 0) == PR_FAILURE) {
printf ("SSL handshake failure.");
exit (1);
}
/* -- Hopefully don't need this. Fails anyway.
if (SSL_ForceHandshake (ssl_fdesc) == PR_FAILURE) {
printf ("SSL forced handshake failure: ");
PR_GetErrorText (buf);
printf ("nspr error %d: %s, oserr: %d\n",
PR_GetError (),
buf,
PR_GetOSError ());
exit (1);
}
*/
printf ("Polling for Write: ");
nspr_poll (ssl_fdesc, PR_POLL_WRITE);
printf ("Writing: %s\n", argv [2]);
PR_SetError (0, 0);
do {
result = PR_Write (ssl_fdesc, argv [2], strlen (argv [2]));
} while (result < 0 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
if (result < 0) {
PR_GetErrorText (buf);
printf ("Write failed: %d, nspr error %d: %s, oserr: %d\n",
result,
PR_GetError (),
buf,
PR_GetOSError ());
exit (1);
}
printf ("Polling for Read: ");
nspr_poll (ssl_fdesc, PR_POLL_READ);
printf ("Reading\n");
do {
result = PR_Read (ssl_fdesc, buf, sizeof (buf));
} while (result < 0 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
if (result < 0) {
PR_GetErrorText (buf);
printf ("Read failed: %d, nspr error %d: %s, oserr: %d\n",
result,
PR_GetError (),
buf,
PR_GetOSError ());
exit (1);
} else if (result == 0) {
printf ("Read 0 bytes\n");
}
buf [result] = '\0';
printf ("Read %s\n", buf);
return 0;
}
