int crypto_init(cert_policy *policy) { SECStatus rv; DBG("Initializing NSS ..."); if (NSS_IsInitialized()) { app_has_NSS = 1; /* we should save the app's password function */ PK11_SetPasswordFunc(password_passthrough); DBG("... NSS is initialized"); return 0; } if (policy->nss_dir) { /* initialize with read only databases */ DBG1("Initializing NSS ... database=%s", policy->nss_dir); rv = NSS_Init(policy->nss_dir); } else { /* not database secified */ DBG("Initializing NSS ... with no db"); rv = NSS_NoDB_Init(NULL); } if (rv != SECSuccess) { DBG1("NSS_Initialize failed: %s", SECU_Strerror(PR_GetError())); return -1; } /* register a callback */ PK11_SetPasswordFunc(password_passthrough); if (policy->ocsp_policy == OCSP_ON) { CERT_EnableOCSPChecking(CERT_GetDefaultCertDB()); } DBG("... NSS Complete"); return 0; }
static int nss_hash_init(void **pctx, SECOidTag hash_alg) { PK11Context *ctx; /* we have to initialize NSS if not initialized alraedy */ #ifdef HAVE_NSS_INITCONTEXT if(!NSS_IsInitialized() && !nss_context) { static NSSInitParameters params; params.length = sizeof params; nss_context = NSS_InitContext("", "", "", "", ¶ms, NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); } #endif ctx = PK11_CreateDigestContext(hash_alg); if(!ctx) return /* failure */ 0; if(PK11_DigestBegin(ctx) != SECSuccess) { PK11_DestroyContext(ctx, PR_TRUE); return /* failure */ 0; } *pctx = ctx; return /* success */ 1; }
static X509* nss_get_cert(NSS_CTX *ctx, const char *s) { X509 *x509 = NULL; CERTCertificate *cert = NULL; CALL_TRACE("nss_get_cert...\n"); if (ctx == NULL) { NSSerr(NSS_F_GET_CERT, NSS_R_INVALID_ARGUMENT); goto done; } if (!NSS_IsInitialized()) { NSSerr(NSS_F_GET_CERT, NSS_R_DB_IS_NOT_INITIALIZED); goto done; } nss_debug(ctx, "search certificate '%s'", s); cert = PK11_FindCertFromNickname(s, NULL); nss_trace(ctx, "found certificate mem='%p'", cert); if (cert == NULL) goto done; x509 = X509_from_CERTCertificate(cert); done: if (cert) CERT_DestroyCertificate(cert); nss_debug(ctx, "certificate %s", (x509 ? "found": "not found")); return(x509); }
static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) { if(NSS_IsInitialized()) return CURLE_OK; if(cert_dir) { SECStatus rv; const bool use_sql = NSS_VersionCheck("3.12.0"); char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir); if(!certpath) return CURLE_OUT_OF_MEMORY; infof(data, "Initializing NSS with certpath: %s\n", certpath); rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); free(certpath); if(rv == SECSuccess) return CURLE_OK; infof(data, "Unable to initialize NSS database\n"); } infof(data, "Initializing NSS with certpath: none\n"); if(NSS_NoDB_Init(NULL) == SECSuccess) return CURLE_OK; infof(data, "Unable to initialize NSS\n"); return CURLE_SSL_CACERT_BADFILE; }
static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) { #ifdef HAVE_NSS_INITCONTEXT NSSInitParameters initparams; if(nss_context != NULL) return CURLE_OK; memset((void *) &initparams, '\0', sizeof(initparams)); initparams.length = sizeof(initparams); #else /* HAVE_NSS_INITCONTEXT */ SECStatus rv; if(NSS_IsInitialized()) return CURLE_OK; #endif if(cert_dir) { const bool use_sql = NSS_VersionCheck("3.12.0"); char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir); if(!certpath) return CURLE_OUT_OF_MEMORY; infof(data, "Initializing NSS with certpath: %s\n", certpath); #ifdef HAVE_NSS_INITCONTEXT nss_context = NSS_InitContext(certpath, "", "", "", &initparams, NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); free(certpath); if(nss_context != NULL) return CURLE_OK; #else /* HAVE_NSS_INITCONTEXT */ rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); free(certpath); if(rv == SECSuccess) return CURLE_OK; #endif infof(data, "Unable to initialize NSS database\n"); } infof(data, "Initializing NSS with certpath: none\n"); #ifdef HAVE_NSS_INITCONTEXT nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); if(nss_context != NULL) return CURLE_OK; #else /* HAVE_NSS_INITCONTEXT */ if(NSS_NoDB_Init(NULL) == SECSuccess) return CURLE_OK; #endif infof(data, "Unable to initialize NSS\n"); return CURLE_SSL_CACERT_BADFILE; }
/** * Shutdown the crypto library and release resources. * * It is safe to shut down twice. */ static apr_status_t crypto_shutdown(void) { if (NSS_IsInitialized()) { SECStatus s = NSS_Shutdown(); if (s != SECSuccess) { return APR_EINIT; } } return APR_SUCCESS; }
static CURLcode init_nss(struct SessionHandle *data) { char *cert_dir; struct_stat st; if(initialized) return CURLE_OK; /* First we check if $SSL_DIR points to a valid dir */ cert_dir = getenv("SSL_DIR"); if(cert_dir) { if((stat(cert_dir, &st) != 0) || (!S_ISDIR(st.st_mode))) { cert_dir = NULL; } } /* Now we check if the default location is a valid dir */ if(!cert_dir) { if((stat(SSL_DIR, &st) == 0) && (S_ISDIR(st.st_mode))) { cert_dir = (char *)SSL_DIR; } } if(!NSS_IsInitialized()) { SECStatus rv; initialized = 1; infof(data, "Initializing NSS with certpath: %s\n", cert_dir ? cert_dir : "none"); if(!cert_dir) { rv = NSS_NoDB_Init(NULL); } else { char *certpath = PR_smprintf("%s%s", NSS_VersionCheck("3.12.0") ? "sql:" : "", cert_dir); rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); PR_smprintf_free(certpath); } if(rv != SECSuccess) { infof(data, "Unable to initialize NSS database\n"); initialized = 0; return CURLE_SSL_CACERT_BADFILE; } } if(num_enabled_ciphers() == 0) NSS_SetDomesticPolicy(); return CURLE_OK; }
void sipe_core_init(void) { srand(time(NULL)); sip_sec_init(); #ifdef ENABLE_NLS SIPE_DEBUG_INFO("bindtextdomain = %s", bindtextdomain(PACKAGE_NAME, LOCALEDIR)); SIPE_DEBUG_INFO("bind_textdomain_codeset = %s", bind_textdomain_codeset(PACKAGE_NAME, "UTF-8")); textdomain(PACKAGE_NAME); #endif #ifdef HAVE_NSS if (!NSS_IsInitialized()) { NSS_NoDB_Init("."); SIPE_DEBUG_INFO_NOFORMAT("NSS initialised"); } #endif #ifdef HAVE_GMIME g_mime_init(0); #endif }
static int __pkcs11h_crypto_nss_initialize ( IN void * const global_data ) { int ret = FALSE; if (NSS_IsInitialized ()) { *(int *)global_data = FALSE; } else { if (NSS_NoDB_Init (NULL) != SECSuccess) { goto cleanup; } *(int *)global_data = TRUE; } ret = TRUE; cleanup: return ret; }
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) { PRInt32 err; PRFileDesc *model = NULL; PRBool ssl2, ssl3, tlsv1; struct SessionHandle *data = conn->data; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECStatus rv; char *certDir = NULL; int curlerr; const int *cipher_to_enable; curlerr = CURLE_SSL_CONNECT_ERROR; if (connssl->state == ssl_connection_complete) return CURLE_OK; connssl->data = data; #ifdef HAVE_PK11_CREATEGENERICOBJECT connssl->cacert[0] = NULL; connssl->cacert[1] = NULL; connssl->key = NULL; #endif /* FIXME. NSS doesn't support multiple databases open at the same time. */ PR_Lock(nss_initlock); if(!initialized) { struct_stat st; /* First we check if $SSL_DIR points to a valid dir */ certDir = getenv("SSL_DIR"); if(certDir) { if((stat(certDir, &st) != 0) || (!S_ISDIR(st.st_mode))) { certDir = NULL; } } /* Now we check if the default location is a valid dir */ if(!certDir) { if((stat(SSL_DIR, &st) == 0) && (S_ISDIR(st.st_mode))) { certDir = (char *)SSL_DIR; } } if (!NSS_IsInitialized()) { initialized = 1; infof(conn->data, "Initializing NSS with certpath: %s\n", certDir ? certDir : "none"); if(!certDir) { rv = NSS_NoDB_Init(NULL); } else { char *certpath = PR_smprintf("%s%s", NSS_VersionCheck("3.12.0") ? "sql:" : "", certDir); rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); PR_smprintf_free(certpath); } if(rv != SECSuccess) { infof(conn->data, "Unable to initialize NSS database\n"); curlerr = CURLE_SSL_CACERT_BADFILE; initialized = 0; PR_Unlock(nss_initlock); goto error; } } if(num_enabled_ciphers() == 0) NSS_SetDomesticPolicy(); #ifdef HAVE_PK11_CREATEGENERICOBJECT if(!mod) { char *configstring = aprintf("library=%s name=PEM", pem_library); if(!configstring) { PR_Unlock(nss_initlock); goto error; } mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE); free(configstring); if(!mod || !mod->loaded) { if(mod) { SECMOD_DestroyModule(mod); mod = NULL; } infof(data, "WARNING: failed to load NSS PEM library %s. Using OpenSSL " "PEM certificates will not work.\n", pem_library); } } #endif PK11_SetPasswordFunc(nss_get_password); } PR_Unlock(nss_initlock); model = PR_NewTCPSocket(); if(!model) goto error; model = SSL_ImportFD(NULL, model); if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) goto error; if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) goto error; if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) goto error; ssl2 = ssl3 = tlsv1 = PR_FALSE; switch (data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: ssl3 = tlsv1 = PR_TRUE; break; case CURL_SSLVERSION_TLSv1: tlsv1 = PR_TRUE; break; case CURL_SSLVERSION_SSLv2: ssl2 = PR_TRUE; break; case CURL_SSLVERSION_SSLv3: ssl3 = PR_TRUE; break; } if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess) goto error; if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess) goto error; if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess) goto error; if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess) goto error; /* enable all ciphers from enable_ciphers_by_default */ cipher_to_enable = enable_ciphers_by_default; while (SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) { if (SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) { curlerr = CURLE_SSL_CIPHER; goto error; } cipher_to_enable++; } if(data->set.ssl.cipher_list) { if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { curlerr = CURLE_SSL_CIPHER; goto error; } } if(data->set.ssl.verifyhost == 1) infof(data, "warning: ignoring unsupported value (1) of ssl.verifyhost\n"); data->set.ssl.certverifyresult=0; /* not checked yet */ if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, conn) != SECSuccess) { goto error; } if(SSL_HandshakeCallback(model, (SSLHandshakeCallback) HandshakeCallback, NULL) != SECSuccess) goto error; if(!data->set.ssl.verifypeer) /* skip the verifying of the peer */ ; else if(data->set.ssl.CAfile) { int rc = nss_load_cert(&conn->ssl[sockindex], data->set.ssl.CAfile, PR_TRUE); if(!rc) { curlerr = CURLE_SSL_CACERT_BADFILE; goto error; } } else if(data->set.ssl.CApath) { struct_stat st; PRDir *dir; PRDirEntry *entry; if(stat(data->set.ssl.CApath, &st) == -1) { curlerr = CURLE_SSL_CACERT_BADFILE; goto error; } if(S_ISDIR(st.st_mode)) { int rc; dir = PR_OpenDir(data->set.ssl.CApath); do { entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN); if(entry) { char fullpath[PATH_MAX]; snprintf(fullpath, sizeof(fullpath), "%s/%s", data->set.ssl.CApath, entry->name); rc = nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE); /* FIXME: check this return value! */ } /* This is purposefully tolerant of errors so non-PEM files * can be in the same directory */ } while(entry != NULL); PR_CloseDir(dir); } } infof(data, " CAfile: %s\n" " CApath: %s\n", data->set.ssl.CAfile ? data->set.ssl.CAfile : "none", data->set.ssl.CApath ? data->set.ssl.CApath : "none"); if (data->set.ssl.CRLfile) { int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE); if (!rc) { curlerr = CURLE_SSL_CRL_BADFILE; goto error; } infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none"); } if(data->set.str[STRING_CERT]) { bool nickname_alloc = FALSE; char *nickname = fmt_nickname(data->set.str[STRING_CERT], &nickname_alloc); if(!nickname) return CURLE_OUT_OF_MEMORY; if(!cert_stuff(conn, sockindex, data->set.str[STRING_CERT], data->set.str[STRING_KEY])) { /* failf() is already done in cert_stuff() */ if(nickname_alloc) free(nickname); return CURLE_SSL_CERTPROBLEM; } /* this "takes over" the pointer to the allocated name or makes a dup of it */ connssl->client_nickname = nickname_alloc?nickname:strdup(nickname); if(!connssl->client_nickname) return CURLE_OUT_OF_MEMORY; } else connssl->client_nickname = NULL; if(SSL_GetClientAuthDataHook(model, SelectClientCert, (void *)connssl) != SECSuccess) { curlerr = CURLE_SSL_CERTPROBLEM; goto error; } /* Import our model socket onto the existing file descriptor */ connssl->handle = PR_ImportTCPSocket(sockfd); connssl->handle = SSL_ImportFD(model, connssl->handle); if(!connssl->handle) goto error; PR_Close(model); /* We don't need this any more */ /* This is the password associated with the cert that we're using */ if (data->set.str[STRING_KEY_PASSWD]) { SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); } /* Force handshake on next I/O */ SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); SSL_SetURL(connssl->handle, conn->host.name); /* Force the handshake now */ if(SSL_ForceHandshakeWithTimeout(connssl->handle, PR_SecondsToInterval(HANDSHAKE_TIMEOUT)) != SECSuccess) { if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) curlerr = CURLE_PEER_FAILED_VERIFICATION; else if(conn->data->set.ssl.certverifyresult!=0) curlerr = CURLE_SSL_CACERT; goto error; } connssl->state = ssl_connection_complete; display_conn_info(conn, connssl->handle); if (data->set.str[STRING_SSL_ISSUERCERT]) { SECStatus ret; bool nickname_alloc = FALSE; char *nickname = fmt_nickname(data->set.str[STRING_SSL_ISSUERCERT], &nickname_alloc); if(!nickname) return CURLE_OUT_OF_MEMORY; ret = check_issuer_cert(connssl->handle, nickname); if(nickname_alloc) free(nickname); if(SECFailure == ret) { infof(data,"SSL certificate issuer check failed\n"); curlerr = CURLE_SSL_ISSUER_ERROR; goto error; } else { infof(data, "SSL certificate issuer check ok\n"); } } return CURLE_OK; error: err = PR_GetError(); infof(data, "NSS error %d\n", err); if(model) PR_Close(model); return curlerr; }
static int nss_cmd_list_cert(NSS_CTX *ctx, long i) { int ret = 0; BIO *out = NULL; void *wincx = NULL; CERTCertList *list; CERTCertListNode *node; PK11CertListType type; CALL_TRACE("nss_cmd_list_cert: %ld\n", i); if (ctx == NULL) { NSSerr(NSS_F_CMD_LIST_CERT, NSS_R_INVALID_ARGUMENT); goto done; } if (!NSS_IsInitialized()) { NSSerr(NSS_F_CMD_LIST_CERT, NSS_R_DB_IS_NOT_INITIALIZED); goto done; } #if 0 softoken/secmodt.h: PK11CertListUnique = 0, /* get one instance of all certs */ softoken/secmodt.h: PK11CertListUser = 1, /* get all instances of user certs */ softoken/secmodt.h: PK11CertListRootUnique = 2, /* get one instance of CA certs without a private key. */ softoken/secmodt.h: PK11CertListCA = 3, /* get all instances of CA certs */ softoken/secmodt.h: PK11CertListCAUnique = 4, /* get one instance of CA certs */ softoken/secmodt.h: PK11CertListUserUnique = 5, /* get one instance of user certs */ softoken/secmodt.h: PK11CertListAll = 6 /* get all instances of all certs */ #endif switch (i) { case 1: type = PK11CertListUser; break; case 2: type = PK11CertListCA ; break; case 3: type = PK11CertListAll ; break; default: goto done; break; } out = BIO_new_fp(stdout, BIO_NOCLOSE); list = PK11_ListCerts(type, wincx); for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node) ) { CERTCertificate *cert = node->cert; BIO_printf(out, "nickname='%s'\n" , cert->nickname); BIO_printf(out, " subject_name='%s'\n", cert->subjectName); /* NOTE: * - NSS cut long strings in cert->subjectName (?) * - RFC 3280 : For UTF8String or UniversalString at least four * times the upper bound should be allowed. * => lets perform own output */ BIO_printf_CERTName(out, &cert->subject, " "); BIO_printf(out, " email_addr ='%s'\n", cert->emailAddr); } CERT_DestroyCertList(list); ret = 1; done: if (out) BIO_free(out); return(ret); }
/** * Initialise the crypto library and perform one time initialisation. */ static apr_status_t crypto_init(apr_pool_t *pool, const char *params, int *rc) { SECStatus s; const char *dir = NULL; const char *keyPrefix = NULL; const char *certPrefix = NULL; const char *secmod = NULL; int noinit = 0; PRUint32 flags = 0; struct { const char *field; const char *value; int set; } fields[] = { { "dir", NULL, 0 }, { "key3", NULL, 0 }, { "cert7", NULL, 0 }, { "secmod", NULL, 0 }, { "noinit", NULL, 0 }, { NULL, NULL, 0 } }; const char *ptr; size_t klen; char **elts = NULL; char *elt; int i = 0, j; apr_status_t status; if (params) { if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) { return status; } while ((elt = elts[i])) { ptr = strchr(elt, '='); if (ptr) { for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen) ; ptr++; } else { for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen) ; } elt[klen] = 0; for (j = 0; fields[j].field != NULL; ++j) { if (klen && !strcasecmp(fields[j].field, elt)) { fields[j].set = 1; if (ptr) { fields[j].value = ptr; } break; } } i++; } dir = fields[0].value; keyPrefix = fields[1].value; certPrefix = fields[2].value; secmod = fields[3].value; noinit = fields[4].set; } /* if we've been asked to bypass, do so here */ if (noinit) { return APR_SUCCESS; } /* sanity check - we can only initialise NSS once */ if (NSS_IsInitialized()) { return APR_EREINIT; } apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper, apr_pool_cleanup_null); if (keyPrefix || certPrefix || secmod) { s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags); } else if (dir) { s = NSS_InitReadWrite(dir); } else { s = NSS_NoDB_Init(NULL); } if (s != SECSuccess) { if (rc) { *rc = PR_GetError(); } return APR_ECRYPT; } return APR_SUCCESS; }
gint camel_init (const gchar *configdir, gboolean nss_init) { CamelCertDB *certdb; gchar *path; if (initialised) return 0; bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); camel_debug_init (); if (nss_init) { static gchar v2_enabled = -1, weak_ciphers = -1; gchar *nss_configdir = NULL; gchar *nss_sql_configdir = NULL; SECStatus status = SECFailure; #if NSS_VMAJOR < 3 || (NSS_VMAJOR == 3 && NSS_VMINOR < 14) /* NSS pre-3.14 has most of the ciphers disabled, thus enable * weak ciphers, if it's compiled against such */ weak_ciphers = 1; #endif /* check camel-tcp-stream-ssl.c for the same "CAMEL_SSL_V2_ENABLE" */ if (v2_enabled == -1) v2_enabled = g_strcmp0 (g_getenv ("CAMEL_SSL_V2_ENABLE"), "1") == 0 ? 1 : 0; if (weak_ciphers == -1) weak_ciphers = g_strcmp0 (g_getenv ("CAMEL_SSL_WEAK_CIPHERS"), "1") == 0 ? 1 : 0; if (nss_initlock == NULL) { PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10); nss_initlock = PR_NewLock (); } PR_Lock (nss_initlock); if (NSS_IsInitialized ()) goto skip_nss_init; #ifndef G_OS_WIN32 nss_configdir = g_strdup (configdir); #else nss_configdir = g_win32_locale_filename_from_utf8 (configdir); #endif if (nss_has_system_db ()) { nss_sql_configdir = g_strdup ("sql:" NSS_SYSTEM_DB ); } else { /* On Windows, we use the Evolution configdir. On other * operating systems we use ~/.pki/nssdb/, which is where * the user-specific part of the "shared system db" is * stored and is what Chrome uses too. * * We have to create the configdir if it does not exist, * to prevent camel from bailing out on first run. */ #ifdef G_OS_WIN32 g_mkdir_with_parents (configdir, 0700); nss_sql_configdir = g_strconcat ( "sql:", nss_configdir, NULL); #else gchar *user_nss_dir = g_build_filename ( g_get_home_dir (), ".pki/nssdb", NULL ); if (g_mkdir_with_parents (user_nss_dir, 0700)) g_warning ( "Failed to create SQL " "database directory %s: %s\n", user_nss_dir, strerror (errno)); nss_sql_configdir = g_strconcat ( "sql:", user_nss_dir, NULL); g_free (user_nss_dir); #endif } #if NSS_VMAJOR > 3 || (NSS_VMAJOR == 3 && NSS_VMINOR >= 12) /* See: https://wiki.mozilla.org/NSS_Shared_DB, * particularly "Mode 3A". Note that the target * directory MUST EXIST. */ status = NSS_InitWithMerge ( nss_sql_configdir, /* dest dir */ "", "", /* new DB name prefixes */ SECMOD_DB, /* secmod name */ nss_configdir, /* old DB dir */ "", "", /* old DB name prefixes */ nss_configdir, /* unique ID for old DB */ "Evolution S/MIME", /* UI name for old DB */ 0); /* flags */ if (status == SECFailure) { g_warning ( "Failed to initialize NSS SQL database in %s: NSS error %d", nss_sql_configdir, PORT_GetError ()); /* Fall back to opening the old DBM database */ } #endif /* Support old versions of libnss, pre-sqlite support. */ if (status == SECFailure) status = NSS_InitReadWrite (nss_configdir); if (status == SECFailure) { /* Fall back to using volatile dbs? */ status = NSS_NoDB_Init (nss_configdir); if (status == SECFailure) { g_free (nss_configdir); g_free (nss_sql_configdir); g_warning ("Failed to initialize NSS"); PR_Unlock (nss_initlock); return -1; } } nss_initialized = TRUE; skip_nss_init: NSS_SetDomesticPolicy (); if (weak_ciphers) { PRUint16 indx; /* enable SSL3/TLS cipher-suites */ for (indx = 0; indx < SSL_NumImplementedCiphers; indx++) { if (!SSL_IS_SSL2_CIPHER (SSL_ImplementedCiphers[indx]) && SSL_ImplementedCiphers[indx] != SSL_RSA_WITH_NULL_SHA && SSL_ImplementedCiphers[indx] != SSL_RSA_WITH_NULL_MD5) SSL_CipherPrefSetDefault (SSL_ImplementedCiphers[indx], PR_TRUE); } } SSL_OptionSetDefault (SSL_ENABLE_SSL2, v2_enabled ? PR_TRUE : PR_FALSE); SSL_OptionSetDefault (SSL_V2_COMPATIBLE_HELLO, PR_FALSE); SSL_OptionSetDefault (SSL_ENABLE_SSL3, PR_TRUE); SSL_OptionSetDefault (SSL_ENABLE_TLS, PR_TRUE); PR_Unlock (nss_initlock); g_free (nss_configdir); g_free (nss_sql_configdir); } path = g_strdup_printf ("%s/camel-cert.db", configdir); certdb = camel_certdb_new (); camel_certdb_set_filename (certdb, path); g_free (path); /* if we fail to load, who cares? it'll just be a volatile certdb */ camel_certdb_load (certdb); /* set this certdb as the default db */ camel_certdb_set_default (certdb); g_object_unref (certdb); initialised = TRUE; return 0; }
pubkey_error_code pubkey_from_base64 (const char *pubkstr, pubkey_data **dst) { /* This is the ugly part. Inspired by https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/nss_sample_code/NSS_Sample_Code_sample5 */ if (!NSS_IsInitialized ()) { if (SECSuccess != NSS_NoDB_Init (".")) { return pubkey_ec_nss_internal; } } PK11SlotInfo *slot = PK11_GetInternalKeySlot (); if (slot == NULL) { return pubkey_ec_nss_internal; } SECItem der; der.data = NULL; der.len = 0; der.type = 0; if (SECSuccess != ATOB_ConvertAsciiToItem (&der, pubkstr)) { PK11_FreeSlot(slot); return pubkey_ec_nss_internal; } SECKEYPublicKey *pubkey = my_SECKEY_DecodeDERPublicKey (&der); pubkey_error_code ec = pubkey_ec_ok; if (!pubkey) { ec = pubkey_ec_nss_internal; } SECITEM_FreeItem (&der, 0); // if (!ec && rsaKey != pubkey->keyType) { // ec = pubkey_ec_nss_internal; // } if (!ec && (siUnsignedInteger != pubkey->u.rsa.modulus.type)) { ec = pubkey_ec_nss_internal; } if (!ec && (siUnsignedInteger != pubkey->u.rsa.publicExponent.type)) { ec = pubkey_ec_nss_internal; } if (!ec && (PUBKEY_USE_MAX_MOD_LEN < pubkey->u.rsa.modulus.len)) { ec = pubkey_ec_too_large; } if (!ec && (4 < pubkey->u.rsa.publicExponent.len)) { ec = pubkey_ec_too_large; } *dst = NULL; if (!ec) { *dst = malloc (sizeof (pubkey_data)); if (!*dst) { ec = pubkey_ec_nss_internal; // Lie. } } if (!ec) { assert(*dst); (*dst)->exponent = 0; const unsigned int e_len = pubkey->u.rsa.publicExponent.len; for (unsigned int i = 0; i < e_len; ++i) { (*dst)->exponent <<= 8; (*dst)->exponent |= pubkey->u.rsa.publicExponent.data[i]; } const unsigned int m_len = pubkey->u.rsa.modulus.len; assert (m_len <= PUBKEY_USE_MAX_MOD_LEN); (*dst)->modulus_length = m_len; memcpy ((*dst)->modulus, pubkey->u.rsa.modulus.data, m_len); } if (pubkey) { SECKEY_DestroyPublicKey (pubkey); } assert (slot); PK11_FreeSlot (slot); return ec; }