Linux上で実行するPHPのスクリプト内で、curlを使用したプログラムを書いていたのですが、テスト中に下記のエラーが出力されました。
Initializing NSS with certpath: none Unable to initialize NSS |
メッセージ通りcertファイルがあるPATHがわからないせいで、初期化に失敗したのだろうとは思っていたのですが、このエラーが具体的にどの条件で出力されるか気になったので、curlのソースを確認してみました。
該当のメッセージでgrepしてみると、エラー出力をしているのは”curl/lib/nss.c”でした。関数の中身は以下のような感じになってます。
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; } |
上記のロジックを見ると、cert_dirが0のときエラー”Initializing NSS with certpath: none”が出力されます。それでは関数nss_init_core()を誰がコールしているかというと、同じファイルにあるnss_init()から呼ばれています。
nss_init()の中身は以下の通りです。
static CURLcode nss_init(struct SessionHandle *data) { char *cert_dir; struct_stat st; CURLcode rv; 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; } } rv = nss_init_core(data, cert_dir); if(rv) return rv; if(num_enabled_ciphers() == 0) NSS_SetDomesticPolicy(); initialized = 1; return CURLE_OK; } |
このコードを見ると、下記のルールでcert_dirを決定しています。
・環境変数SSL_DIRで指定されたディレクトリが存在するかチェックし、存在すればこれをcert_dirとみなす。
・存在しない場合や、SSL_DIRが未定義の場合は、定数SSL_DIRで指定されたディレクトリが存在するかチェックする。
・どちらもない場合は、cert_dirにNULLをセットする。
SSL_DIRは、こちらも同じファイルで定義されており、/etc/pki/nssdbを決めうちで指定しています。
#define SSL_DIR "/etc/pki/nssdb" |
というわけで、環境変数SSL_DIR、および/etc/pki/nssdbを検索し、これがなければエラー”Initializing NSS with certpath: none”が出力されるようです。
※本件とは直接関係ないですがこのコード、NULLが0番地であることを仮定したコードになっていて、ちょっと良くないですね…
関連記事
コメントを残す