cURLで、エラー”Initializing NSS with certpath: none”出る理由を、ソースから調べてみた

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番地であることを仮定したコードになっていて、ちょっと良くないですね…


関連記事

コメントを残す

メールアドレスが公開されることはありません。