Nelson:
Thanks for your detailed reply. It was, indeed a problem with memory leaks.

Best Regards.
Umesh.
----- Original Message ----- From: "Nelson B" <[EMAIL PROTECTED]>
Newsgroups: mozilla.dev.tech.crypto
To: <dev-tech-crypto@lists.mozilla.org>
Sent: Thursday, April 06, 2006 10:53 PM
Subject: Re: NSS_Shutdown failure


Umesh Bywar wrote:
Hi all:

Welcome to the list, Umesh.

   I am working on writing an xpcom component that checks which ciphers
work with a given target. So basically, I have a component which acts as
a SSL client and performs a handshake by setting a given cipher. I am
executing this in the context of the browser (and not as a independent
executable).

If your code is running in a mozilla-family browser, then your code
should let the browser do all the NSS initialization and shutdown.
You don't want to shutdown NSS in the middle of the running browser
because then the browser itself can no longer use NSS.
Your code should only ensure that it does not leak any object
references, so that when the browser shuts down NSS, NSS_Shutdown will
succeed at that time.
NSS_Shutdown will fail if there are still outstanding NSS object
references.  The browser itself probably has several such references,
which is one reason why it fails when you call it.

   The cipherCheck works correctly, but I found that the NSS_Shutdown
function fails. Due to this, I guess the cleanup operation is not
complete and hence I am not able to run the cipherCheck again.
   I have pasted the code snippet below. Please do let me know if
anybody has any ideas.

int checkCipher(const char *hostnameIP,int currPort, int currentCipher)
{

if (!certdir) {
rv = NSS_NoDB_Init(NULL);
if (rv != SECSuccess)
{
OutputDebugString("NSS Init failed");
PRErrorCode retError = PR_GetError();
return retError;
}
SECMOD_AddNewModule("Builtins", "nssckbi.dll",0,0);
}

Indentation is your friend.  :)

r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
if (r != PR_SUCCESS) {
OutputDebugString(" PR_GetHostByName failure");
return PR_GetError();
}
PR_EnumerateHostEnt(0,&hp,0,&na);
if (r != PR_SUCCESS) {
OutputDebugString("PR_EnumerateHostEnt failure");
return PR_GetError();
}
PR_InitializeNetAddr(PR_IpAddrNull,portnum,&na);
if (r != PR_SUCCESS) {
OutputDebugString("PR_InitializeNetAddr failure");
return PR_GetError();
}
fd = PR_NewTCPSocket();
if (fd == NULL) {
OutputDebugString("PR_NewTCPSocket failure");
return PR_GetError();
}
OutputDebugString("before ImportFD");
s = SSL_ImportFD(NULL,fd);
if (s == NULL) {
OutputDebugString("could not import fd into SSL");
return PR_GetError();

Here you leak the fd.

}
OutputDebugString("before SSL_OptionSet");
rv = SSL_OptionSet(s, SSL_SECURITY, PR_TRUE);
if (rv != SECSuccess)
{
OutputDebugString("SSL_OptionSet error for SSL_SECURITY");
return PR_GetError();
here you leak the fd.
}
OutputDebugString("after SSL_OptionSet");
rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
if (rv != SECSuccess) {
OutputDebugString("SSL_OptionSet error for SSL_HANDSHAKE_AS_CLIENT");
return PR_GetError();
leak
}
whichCiphers = NSS_SetDomesticPolicy();

This needs to be done before any SSL calls.
The browser should already have done this for you.

if (whichCiphers != SECSuccess)
{
OutputDebugString("NSS_SetDomesticPolicy error");
return PR_GetError();
leak
}
SSL_ClearSessionCache();
if (policy) {
SetPolicy(s,currentCipher,policy);
}
rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
if (rv != SECSuccess) {
OutputDebugString(" SSL_OptionSet error for SSL_HANDSHAKE_AS_CLIENT");
return PR_GetError();
leak
}
if (SSL_AuthCertificateHook(s, MyAuthCertificateHook, (void *)handle) !=
SECSuccess)
{
OutputDebugString("auth cert hook() issues");
return PR_GetError();
leak
}
if (SSL_BadCertHook(s,MyBadCertHandler,NULL) != SECSuccess)
{
OutputDebugString(" bad cert hook() issues");
return PR_GetError();
leak
}

r = PR_Connect(s, &na, PR_TicksPerSecond()*100);
if (r != PR_SUCCESS) {
OutputDebugString("PR_Connect failure");
return PR_GetError();
leak
}

rv = SSL_ForceHandshake(s);
if (rv != SECSuccess) {
OutputDebugString(" SSL Handshake failed");
PR_Close(s);
PRErrorCode retError = PR_GetError();
return retError;
}
rv = SSL_SecurityStatus(s, &ss_on, &ss_cipher,
&ss_keysize, &ss_secretsize,
&ss_issuer, &ss_subject);

SSL_SecurityStatus is deprecated.  It was designed for SSL2, and
cannot convey all the information relevant to SSl3+TLS.
Try using  SSL_GetChannelInfo() and  SSL_GetCipherSuiteInfo()
instead.  I think you'll find their results much more complete and
useful.

c = SSL_PeerCertificate(s);
if (!c)
{
currRemainingTime = 0;
}
else
{
CERT_GetCertTimes(c,&notbeforeT,&notafterT);
PRTime currTime = PR_Now();
currRemainingTime = currTime - notafterT;
}

SSL_PeerCertificate returns a new reference to the cert.  You must
destroy the reference before you return or else you will leak it.
That leak will make NSS_Shutdown fail.
Use CERT_DestroyCertificate on that reference.

PR_Close(s);

good

if (NSS_Shutdown() != SECSuccess)
{
return 1;
}

I doubt you want to do that.  The browser won't be able to use NSS
after that.

if (!isSSLv2Gl)
{
if (currentCipher >= startSSLv2 || currentCipher <= endSSLv2)
{
isSSLv2Gl=1;
}

This is undeclared.  Assuming it is global, it has the problem that
once you've encountered an SSLv2 cipher suite, you will think that
all cipher suites thereafter are SSLv2, whether they are or not.
That is, you will get the wrong result if you test any V3 cipher suites
after testing v2 cipher suites

}
return ss_secretsize;
}
Best Regards.
Umesh.


--
Nelson B
12345678901234567890123456789012345678901234567890123456789012345678901234567890
00000000011111111112222222222333333333344444444445555555555666666666677777777778
_______________________________________________
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

_______________________________________________
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to