00001 00009 #include "PKIFNSSPasswordStorage.h" 00010 #include "PKIFNSSHelper.h" 00011 00012 #include "ToolkitUtils.h" 00013 #include "PKIFMemoryUtils.h" 00014 #include "IPKIFPasswordCallback.h" 00015 00016 #include "PKIFNSSConfig.h" 00017 #include "nspr.h" 00019 struct PKIFNSSPasswordStorageImpl 00020 { 00021 static char * GetPassword(PK11SlotInfo * slot, PRBool retry, void * arg); 00022 IPKIFPasswordCallback * m_pwfunc; 00023 }; 00025 00026 CPKIFNSSPasswordStorage * CPKIFNSSPasswordStorage::s_instance = 0; 00027 00035 char * PKIFNSSPasswordStorageImpl::GetPassword( 00037 PK11SlotInfo * slot, 00039 PRBool retry, 00041 void * arg) 00042 { 00043 CPKIFNSSPasswordStorage * ps = CPKIFNSSPasswordStorage::GetInstance(); 00044 if(!ps->m_impl->m_pwfunc) return PORT_Strdup(""); 00045 char * token = PK11_GetSlotName(slot); 00046 char * gotpass = (*(ps->m_impl->m_pwfunc))(token, 00047 retry == PR_TRUE ? true : false); 00048 if(!gotpass) return 0; 00049 // NSS will free the returned value, so we need to copy it using NSS's allocator 00050 char * rv = PORT_Strdup(gotpass); 00051 // securely zero the memory 00052 PKIFZero(gotpass,strlen(gotpass)); 00053 PKIFDelete(gotpass); 00054 return rv; 00055 } 00063 void CPKIFNSSPasswordStorage::InstallCallback(void) 00064 { 00065 if(!s_instance) { 00066 s_instance = new CPKIFNSSPasswordStorage(); 00067 } 00068 // sun pro didn't like the address operator here. 00069 PK11_SetPasswordFunc(s_instance->m_impl->GetPassword); 00070 } 00081 void CPKIFNSSPasswordStorage::SetUserCallback( 00083 IPKIFPasswordCallback * cb) 00084 { 00085 // if NSS can't be used, just return. This will be caught elsewhere 00086 if(!CPKIFNSSHelper::NSSAvaliable()) return; 00087 if(!cb) { 00088 PKIFDelete(s_instance); 00089 s_instance = 0; 00090 PK11_SetPasswordFunc(0); 00091 } else { 00092 if(!s_instance) { 00093 s_instance = new CPKIFNSSPasswordStorage(); 00094 } 00095 s_instance->m_impl->m_pwfunc = cb; 00096 } 00097 } 00105 CPKIFNSSPasswordStorage * CPKIFNSSPasswordStorage::GetInstance(void) 00106 { 00107 if(!s_instance) { 00108 // this will be caught elsewhere if NSS is unavailable. No need 00109 // to throw here 00110 if(!CPKIFNSSHelper::NSSAvaliable()) return 0; 00111 s_instance = new CPKIFNSSPasswordStorage(); 00112 } 00113 return s_instance; 00114 } 00122 CPKIFNSSPasswordStorage::CPKIFNSSPasswordStorage() 00123 :m_impl(new PKIFNSSPasswordStorageImpl) 00124 { 00125 m_impl->m_pwfunc = 0; 00126 } 00127