diff options
-rw-r--r-- | RELEASE-NOTES | 2 | ||||
-rw-r--r-- | docs/curl.1 | 5 | ||||
-rw-r--r-- | docs/libcurl/curl_easy_setopt.3 | 5 | ||||
-rw-r--r-- | lib/nss.c | 73 |
4 files changed, 47 insertions, 38 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 3fce8e78f..aa67721ab 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -26,7 +26,7 @@ This release includes the following bugfixes: o Curl_nss_connect: avoid PATH_MAX o Curl_do: avoid using stale conn pointer o tftpd test server: avoid buffer overflow report from glibc - o + o nss: avoid CURLE_OUT_OF_MEMORY given a file name without any slash This release includes the following known bugs: diff --git a/docs/curl.1 b/docs/curl.1 index e8216d45a..53ae8d787 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -358,11 +358,12 @@ this option assumes a \&"certificate" file that is the private key and the private certificate concatenated! See \fI--cert\fP and \fI--key\fP to specify them independently. -If curl is built against the NSS SSL library then this option tells +If curl is built against the NSS SSL library then this option can tell curl the nickname of the certificate to use within the NSS database defined by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be -loaded. +loaded. If you want to use a file from the current directory, please precede +it with "./" prefix, in order to avoid confusion with a nickname. If this option is used several times, the last one will be used. .IP "--cert-type <type>" diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index a725b33cb..8c14c7dcc 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -1811,8 +1811,9 @@ Pass a pointer to a zero terminated string as parameter. The string should be the file name of your certificate. The default format is "PEM" and can be changed with \fICURLOPT_SSLCERTTYPE\fP. -With NSS this is the nickname of the certificate you wish to authenticate -with. +With NSS this can also be the nickname of the certificate you wish to +authenticate with. If you want to use a file from the current directory, please +precede it with "./" prefix, in order to avoid confusion with a nickname. .IP CURLOPT_SSLCERTTYPE Pass a pointer to a zero terminated string as parameter. The string should be the format of your certificate. Supported formats are "PEM" and "DER". (Added @@ -277,22 +277,35 @@ static int is_file(const char *filename) return 0; } -static char *fmt_nickname(char *str, bool *nickname_alloc) +/* Return on heap allocated filename/nickname of a certificate. The returned + * string should be later deallocated using free(). *is_nickname is set to TRUE + * if the given string is treated as nickname; FALSE if the given string is + * treated as file name. + */ +static char *fmt_nickname(struct SessionHandle *data, enum dupstring cert_kind, + bool *is_nickname) { - char *nickname = NULL; - *nickname_alloc = FALSE; - - if(is_file(str)) { - char *n = strrchr(str, '/'); - if(n) { - *nickname_alloc = TRUE; - n++; /* skip last slash */ - nickname = aprintf("PEM Token #%d:%s", 1, n); - } - return nickname; + const char *str = data->set.str[cert_kind]; + const char *n; + *is_nickname = TRUE; + + if(!is_file(str)) + /* no such file exists, use the string as nickname */ + return strdup(str); + + /* search the last slash; we require at least one slash in a file name */ + n = strrchr(str, '/'); + if(!n) { + infof(data, "warning: certificate file name \"%s\" handled as nickname; " + "please use \"./%s\" to force file name\n", str, str); + return strdup(str); } - return str; + /* we'll use the PEM reader to read the certificate from file */ + *is_nickname = FALSE; + + n++; /* skip last slash */ + return aprintf("PEM Token #%d:%s", 1, n); } static int nss_load_cert(struct ssl_connect_data *ssl, @@ -1304,25 +1317,20 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) } if(data->set.str[STRING_CERT]) { - bool nickname_alloc = FALSE; - char *nickname = fmt_nickname(data->set.str[STRING_CERT], &nickname_alloc); + bool is_nickname; + char *nickname = fmt_nickname(data, STRING_CERT, &is_nickname); if(!nickname) return CURLE_OUT_OF_MEMORY; - if(!cert_stuff(conn, sockindex, data->set.str[STRING_CERT], - data->set.str[STRING_KEY])) { + if(!is_nickname && !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); + 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; - + /* store the nickname for SelectClientCert() called during handshake */ + connssl->client_nickname = nickname; } else connssl->client_nickname = NULL; @@ -1376,18 +1384,17 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) 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); - + SECStatus ret = SECFailure; + bool is_nickname; + char *nickname = fmt_nickname(data, STRING_SSL_ISSUERCERT, &is_nickname); if(!nickname) return CURLE_OUT_OF_MEMORY; - ret = check_issuer_cert(connssl->handle, nickname); + if(is_nickname) + /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ + ret = check_issuer_cert(connssl->handle, nickname); - if(nickname_alloc) - free(nickname); + free(nickname); if(SECFailure == ret) { infof(data,"SSL certificate issuer check failed\n"); |