Re: PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read
Oops, I forgot some details - we are using NSS-3.11.4 and NSPR-4.6.4 on a RedHat Linux with Kernel 2.4, using gcc 3.4.5. On Jul 10, 5:36 pm, Yahel Zamir <[EMAIL PROTECTED]> wrote: > Hi, > > I have encountered a problem in using SSL sockets in blocking mode. My > application is multi threaded, with one thread waiting to read and > another that is waiting to write. Upon some external input, a third > thread tries to shutdown the connection and then close the socket. > However, calling PR_Shutdown or PR_Close never returns from > SSL_LOCK_READER(ss). > > Following are a simple client and server that demonstrate the problem > (search the client for 999 and the server for "delayed_close"). > > Thanks, > Yahel Zamir, > SW Engineer at CWNT > > === > M_DIST = /usr/home/yahel/programs/nss/mozilla/dist > > M_DIST_LINUX = ${M_DIST}/Linux2.4_x86_glibc_PTH_DBG.OBJ > > M_INC = -I${M_DIST_LINUX}/include > M_INC += -I${M_DIST}/public/nss > M_INC += -I${M_DIST}/private/nss # for error strings > > M_FLAGS = -g -Wall -pthread > > M_LIBS = -L${M_DIST_LINUX}/lib > M_LIBS += -lssl3 -lnss3 -lnspr4 -lplds4 -lplc4 -lsoftokn3 > M_LIBS += -lfreebl3 -lsectool -lpthread -ldl -lc > > all: server client > @echo done > > clean: > rm -f client server client.o server.o > > server.o: server.c > gcc server.c -c ${M_FLAGS} ${M_INC} -o server.o > > client.o: client.c > gcc client.c -c ${M_FLAGS} ${M_INC} -o client.o > > server: server.o > gcc server.o ${M_FLAGS} ${M_LIBS} -o server > > client: client.o > gcc client.o ${M_FLAGS} ${M_LIBS} -o client > > === > > // client.c > // > > #include > #include > #include > #include > #include > #include > #include > #include > #include // a private API needed for SECU_Strerror > > static char *s_progName = NULL; > static char *s_password = NULL; > static char *s_hostName = NULL; > > /* > * errWarn() > * > * Print a warning message for NSS and NSPR errors. > * More detailed explanations for the error can be found at: > *http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html > */ > static void > errWarn(char * funcString) > { > PRErrorCode perr = PR_GetError(); > const char * errString = SECU_Strerror(perr); > fprintf(stderr, "%s: %s returned error %d (%s)\n", s_progName, > funcString, perr, errString); > return; > > } > > static void > errExit(char * funcString) > { > errWarn(funcString); > exit(3); > > } > > static void > Usage(const char *progName) > { > fprintf(stderr, "Usage: %s hostname -n cert_name -p port -d cert_dir - > w password \n", progName); > exit(1); > > } > > /* fakePasswd() > * > * This function is our custom password handler that is called by > * SSL when retreiving private certs and keys from the database. > Returns a > * pointer to a string that with a password for the database. Password > pointer > * should point to dynamically allocated memory that will be freed > later. > * We set "arg" to give the correct password, using > SSL_SetPKCS11PinArg(). > */ > char * > fakePasswd(PK11SlotInfo *info, PRBool retry, void *arg) > { > char * passwd = NULL; > > if ((!retry) && (arg != NULL)) { > passwd = PL_strdup((char *)arg); > } > > return passwd; > > } > > /* Function: setupSSLSocket() > * > * Purpose: Configure a socket for SSL. > */ > PRFileDesc * > setupSSLSocket() > { > PRFileDesc *sslSocket; > PRFileDesc *tcpSocket; > SECStatus secStatus; > PRSocketOptionData socketOption; > PRStatusprStatus; > > tcpSocket = PR_NewTCPSocket(); > if (tcpSocket == NULL) { > errWarn("PR_NewTCPSocket"); > return NULL; > } > > // Ensure the socket is blocking. > socketOption.option = PR_SockOpt_Nonblocking; > socketOption.value.non_blocking = PR_FALSE; > > prStatus = PR_SetSocketOption(tcpSocket, &socketOption); > if (prStatus != PR_SUCCESS) { > errWarn("PR_SetSocketOption"); > PR_Close(tcpSocket); > return NULL; > } > > sslSocket = SSL_ImportFD(NULL, tcpSocket); > if (sslSocket == NULL) { > errWarn("SSL_ImportFD"); > PR_Close(tcpSocket); > return NULL; > } > > // ensure original socket is not used > tcpSocket = NULL; > > do { > > // handshake as client > secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, > PR_TRUE); > if (secStatus != SECSuccess) { > errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT"); > break; > } > > // enable full duplex > secStatus = SSL_OptionSet(sslSocket, SSL_ENABLE_FDX, PR_TRUE); > if (secStatus != SECSuccess) { > errWarn("SSL_OptionSet(SSL_ENABLE_FDX)"); > break; > } > > // allow communication without encryption (YZ - must be onl
PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read
Hi, I have encountered a problem in using SSL sockets in blocking mode. My application is multi threaded, with one thread waiting to read and another that is waiting to write. Upon some external input, a third thread tries to shutdown the connection and then close the socket. However, calling PR_Shutdown or PR_Close never returns from SSL_LOCK_READER(ss). Following are a simple client and server that demonstrate the problem (search the client for 999 and the server for "delayed_close"). Thanks, Yahel Zamir, SW Engineer at CWNT === M_DIST = /usr/home/yahel/programs/nss/mozilla/dist M_DIST_LINUX = ${M_DIST}/Linux2.4_x86_glibc_PTH_DBG.OBJ M_INC = -I${M_DIST_LINUX}/include M_INC += -I${M_DIST}/public/nss M_INC += -I${M_DIST}/private/nss # for error strings M_FLAGS = -g -Wall -pthread M_LIBS = -L${M_DIST_LINUX}/lib M_LIBS += -lssl3 -lnss3 -lnspr4 -lplds4 -lplc4 -lsoftokn3 M_LIBS += -lfreebl3 -lsectool -lpthread -ldl -lc all: server client @echo done clean: rm -f client server client.o server.o server.o: server.c gcc server.c -c ${M_FLAGS} ${M_INC} -o server.o client.o: client.c gcc client.c -c ${M_FLAGS} ${M_INC} -o client.o server: server.o gcc server.o ${M_FLAGS} ${M_LIBS} -o server client: client.o gcc client.o ${M_FLAGS} ${M_LIBS} -o client === // client.c // #include #include #include #include #include #include #include #include #include // a private API needed for SECU_Strerror static char *s_progName = NULL; static char *s_password = NULL; static char *s_hostName = NULL; /* * errWarn() * * Print a warning message for NSS and NSPR errors. * More detailed explanations for the error can be found at: * http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslerr.html */ static void errWarn(char * funcString) { PRErrorCode perr = PR_GetError(); const char * errString = SECU_Strerror(perr); fprintf(stderr, "%s: %s returned error %d (%s)\n", s_progName, funcString, perr, errString); return; } static void errExit(char * funcString) { errWarn(funcString); exit(3); } static void Usage(const char *progName) { fprintf(stderr, "Usage: %s hostname -n cert_name -p port -d cert_dir - w password \n", progName); exit(1); } /* fakePasswd() * * This function is our custom password handler that is called by * SSL when retreiving private certs and keys from the database. Returns a * pointer to a string that with a password for the database. Password pointer * should point to dynamically allocated memory that will be freed later. * We set "arg" to give the correct password, using SSL_SetPKCS11PinArg(). */ char * fakePasswd(PK11SlotInfo *info, PRBool retry, void *arg) { char * passwd = NULL; if ((!retry) && (arg != NULL)) { passwd = PL_strdup((char *)arg); } return passwd; } /* Function: setupSSLSocket() * * Purpose: Configure a socket for SSL. */ PRFileDesc * setupSSLSocket() { PRFileDesc *sslSocket; PRFileDesc *tcpSocket; SECStatus secStatus; PRSocketOptionData socketOption; PRStatusprStatus; tcpSocket = PR_NewTCPSocket(); if (tcpSocket == NULL) { errWarn("PR_NewTCPSocket"); return NULL; } // Ensure the socket is blocking. socketOption.option = PR_SockOpt_Nonblocking; socketOption.value.non_blocking = PR_FALSE; prStatus = PR_SetSocketOption(tcpSocket, &socketOption); if (prStatus != PR_SUCCESS) { errWarn("PR_SetSocketOption"); PR_Close(tcpSocket); return NULL; } sslSocket = SSL_ImportFD(NULL, tcpSocket); if (sslSocket == NULL) { errWarn("SSL_ImportFD"); PR_Close(tcpSocket); return NULL; } // ensure original socket is not used tcpSocket = NULL; do { // handshake as client secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); if (secStatus != SECSuccess) { errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT"); break; } // enable full duplex secStatus = SSL_OptionSet(sslSocket, SSL_ENABLE_FDX, PR_TRUE); if (secStatus != SECSuccess) { errWarn("SSL_OptionSet(SSL_ENABLE_FDX)"); break; } // allow communication without encryption (YZ - must be only upon client request) if (SECSuccess != SSL_CipherPrefSet(sslSocket, SSL_RSA_WITH_NULL_SHA, PR_TRUE) || SECSuccess != SSL_CipherPrefSet(sslSocket, SSL_RSA_WITH_NULL_MD5, PR_TRUE)) { errWarn("SSL_CipherPrefSet - Null Cipher"); break; } secStatus = SSL_SetPKCS11PinArg(sslSocket, s_password); if (secStatus != SECSuccess) { errWarn("SSL_SetPKCS11PinArg"); break; } secStatus = SSL_SetURL(sslSocket, s
Re: PR_Close and PR_Shutdown hang if an SSL socket is blocking on Read
Yahel Zamir wrote: > Hi, > > I have encountered a problem in using SSL sockets in blocking mode. My > application is multi threaded, with one thread waiting to read and > another that is waiting to write. Upon some external input, a third > thread tries to shutdown the connection and then close the socket. > However, calling PR_Shutdown or PR_Close never returns from > SSL_LOCK_READER(ss). Calling PR_Close then is a programming error. While one thread is blocking in PR_Recv, another thread cannot call PR_Close on that socket because PR_Close will free the PRFileDesc structure representing that socket. That is, one thread should not free the memory still in use by another thread. I believe the SSL_LOCK_READER(ss) macros are intended to detect or prevent such programming errors from crashing NSS. Off the top of my head, I don't know why we can't call PR_Shutdown while another thread is blocking in PR_Recv. The presence of the SSL_LOCK_READER(ss) macro in ssl_Shutdown (http://lxr.mozilla.org/mozilla1.8/ident?i=ssl_Shutdown) shows it is also considered a programming error. I just don't know why. Wan-Teh ___ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto
Re: Getting public/private keys into/out of NSS
Hi Bob, thanks for all your help by the way, got me much further so far. Robert Relyea wrote: > You really only want to store and retrieve the private keys if you you > need to transport them (or back them up). Doing the latter needs to be > handled carefully, and can be a source of errors in your protocol. This is fine for my uses I think. So long as the private key is somewhere safe that is backupable (the nss certificate database is fine by me) then thats all good. > A better way to handle it (if you absolutely must use bare keys), is > store your private keys as persistant keys. You can use the KeyID and > the slot the key is stored in to find the key again (PK11_FindKeyByID to > find it PK11_GetLowLevelKeyIDForPrivatekey() to get the KeyID). I'm not totally sure I follow you. Let me just quickyl explain what I am wanting to present to the user. They should pretty much not have to worry about certificates or anything like that. All that matters is that they can create a public/private key pair and that my app can show them a list of what key pairs they have created before and then use them. I have this pretty much working but I think I've slightly hacked it. What I've done is assigned a nickname to the private key when it's created. That seems nice until I come to retrieve the key, it seems there isnt a way to retrieve a key by nickname instead I just have to enumerate all keys till I find the one with the nickname. This isn't so bad, there shouldn't be many keys but maybe I'm going about this the wrong way? > Usually NSS uses the certificate. There are functions to help you find > the most appropriate certificate, and then from that certificate find > the private key that is associated with it. I probably have the wrong view of certificates, but my understanding is that they have all sorts of other associated data about then, CN etc and more crucially expiries. Is this right or am I wrong? In which case I'd happily switch over to certificates if that helps me achieve my above goal. One other final thing I'm stumbling over is key and hash types. I recognise the names RSA and DSA but is there a particular advantage of using one over the other? And likewise when I'm signing my data should I hash it using MD5, SHA-1 or any of the other SHAs. I think I read somewhere that RSA keys should be used with MD5 hashes and DSA with SHA-1, is this right? Dave ___ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto
Re: Getting public/private keys into/out of NSS
Dave Townsend wrote: Hi Bob, thanks for all your help by the way, got me much further so far. Robert Relyea wrote: You really only want to store and retrieve the private keys if you you need to transport them (or back them up). Doing the latter needs to be handled carefully, and can be a source of errors in your protocol. This is fine for my uses I think. So long as the private key is somewhere safe that is backupable (the nss certificate database is fine by me) then thats all good. Then I would just use the database and use extracting the key as a backup. That would also allow storing the keys in a token without any modification of your code. A better way to handle it (if you absolutely must use bare keys), is store your private keys as persistant keys. You can use the KeyID and the slot the key is stored in to find the key again (PK11_FindKeyByID to find it PK11_GetLowLevelKeyIDForPrivatekey() to get the KeyID). I'm not totally sure I follow you. Let me just quickyl explain what I am wanting to present to the user. They should pretty much not have to worry about certificates or anything like that. All that matters is that they can create a public/private key pair and that my app can show them a list of what key pairs they have created before and then use them. I have this pretty much working but I think I've slightly hacked it. What I've done is assigned a nickname to the private key when it's created. That seems nice until I come to retrieve the key, it seems there isnt a way to retrieve a key by nickname instead I just have to enumerate all keys till I find the one with the nickname. This isn't so bad, there shouldn't be many keys but maybe I'm going about this the wrong way? No, there usually aren't very many keys. KeyID's are a unique handle to the private keys, nickname/labels aren't always set. Usually NSS uses the certificate. There are functions to help you find the most appropriate certificate, and then from that certificate find the private key that is associated with it. I probably have the wrong view of certificates, but my understanding is that they have all sorts of other associated data about then, CN etc and more crucially expiries. Is this right or am I wrong? In which case I'd happily switch over to certificates if that helps me achieve my above goal. Certs are basically bindings of identity to a public key, so the cert has the user's identity (in the form of a Distinguished name), they public key, some house keeping (the identity of the CA that verified the cert, expiration, etc.), usually some optional information telling what the certificate is good for (signing, encryption, code signing, authentication, etc.), and a signature. Usually the user doesn't bother looking at the cert itself, the cert contains enough information to allow the software to process it and verify it's validity. They help with thing like validating a signature. With a certificate, I can validate a signature was signed by the identity specified in the certificate without having to trust a bare public keys. Most protocols that need to scale beyond 20 or 30 people need to use something like certificates. One other final thing I'm stumbling over is key and hash types. I recognise the names RSA and DSA but is there a particular advantage of using one over the other? RSA and DSA have different performance characteristics, RSA has a fairly fast verification compared to signing. It's also more widely understood. At one time DSA was the only one of the two that were not patent encumbered. And likewise when I'm signing my data should I hash it using MD5, SHA-1 or any of the other SHAs. I think I read somewhere that RSA keys should be used with MD5 hashes and DSA with SHA-1, is this right? I would always use at least SHA-1. DSA can only use exactly SHA-1. Both MD-5 and SHA-1 have been shown to be weak against collision attacks (attacks in which I can generate 2 different messages that hash to the same value), though they are still strong against preimage (trying to calculate a second message the hashes to the same value of a given message). If you're protocol depends on collision resistance, then you should think about using SHA-256 or greater. The only issue is there is still a fair amount of code that does not support the larger hash functions, so if you need to interoperate with that older code you will need to stick to SHA-1, otherwise I strongly encourage you to use the longer SHA algorithms. bob Dave ___ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto smime.p7s Description: S/MIME Cryptographic Signature ___ dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto