nss: avoid CURLE_OUT_OF_MEMORY given a file name without any slash
Bug: https://bugzilla.redhat.com/623663
This commit is contained in:
@@ -26,7 +26,7 @@ This release includes the following bugfixes:
|
|||||||
o Curl_nss_connect: avoid PATH_MAX
|
o Curl_nss_connect: avoid PATH_MAX
|
||||||
o Curl_do: avoid using stale conn pointer
|
o Curl_do: avoid using stale conn pointer
|
||||||
o tftpd test server: avoid buffer overflow report from glibc
|
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:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
|
@@ -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
|
private certificate concatenated! See \fI--cert\fP and \fI--key\fP to specify
|
||||||
them independently.
|
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
|
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
|
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
|
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.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--cert-type <type>"
|
.IP "--cert-type <type>"
|
||||||
|
@@ -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
|
the file name of your certificate. The default format is "PEM" and can be
|
||||||
changed with \fICURLOPT_SSLCERTTYPE\fP.
|
changed with \fICURLOPT_SSLCERTTYPE\fP.
|
||||||
|
|
||||||
With NSS this is the nickname of the certificate you wish to authenticate
|
With NSS this can also be the nickname of the certificate you wish to
|
||||||
with.
|
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
|
.IP CURLOPT_SSLCERTTYPE
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
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
|
the format of your certificate. Supported formats are "PEM" and "DER". (Added
|
||||||
|
65
lib/nss.c
65
lib/nss.c
@@ -277,22 +277,35 @@ static int is_file(const char *filename)
|
|||||||
return 0;
|
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;
|
const char *str = data->set.str[cert_kind];
|
||||||
*nickname_alloc = FALSE;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we'll use the PEM reader to read the certificate from file */
|
||||||
|
*is_nickname = FALSE;
|
||||||
|
|
||||||
if(is_file(str)) {
|
|
||||||
char *n = strrchr(str, '/');
|
|
||||||
if(n) {
|
|
||||||
*nickname_alloc = TRUE;
|
|
||||||
n++; /* skip last slash */
|
n++; /* skip last slash */
|
||||||
nickname = aprintf("PEM Token #%d:%s", 1, n);
|
return aprintf("PEM Token #%d:%s", 1, n);
|
||||||
}
|
|
||||||
return nickname;
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nss_load_cert(struct ssl_connect_data *ssl,
|
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]) {
|
if(data->set.str[STRING_CERT]) {
|
||||||
bool nickname_alloc = FALSE;
|
bool is_nickname;
|
||||||
char *nickname = fmt_nickname(data->set.str[STRING_CERT], &nickname_alloc);
|
char *nickname = fmt_nickname(data, STRING_CERT, &is_nickname);
|
||||||
if(!nickname)
|
if(!nickname)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if(!cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
|
if(!is_nickname && !cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
|
||||||
data->set.str[STRING_KEY])) {
|
data->set.str[STRING_KEY])) {
|
||||||
/* failf() is already done in cert_stuff() */
|
/* failf() is already done in cert_stuff() */
|
||||||
if(nickname_alloc)
|
|
||||||
free(nickname);
|
free(nickname);
|
||||||
return CURLE_SSL_CERTPROBLEM;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this "takes over" the pointer to the allocated name or makes a
|
/* store the nickname for SelectClientCert() called during handshake */
|
||||||
dup of it */
|
connssl->client_nickname = nickname;
|
||||||
connssl->client_nickname = nickname_alloc?nickname:strdup(nickname);
|
|
||||||
if(!connssl->client_nickname)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
connssl->client_nickname = NULL;
|
connssl->client_nickname = NULL;
|
||||||
@@ -1376,17 +1384,16 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
|||||||
display_conn_info(conn, connssl->handle);
|
display_conn_info(conn, connssl->handle);
|
||||||
|
|
||||||
if (data->set.str[STRING_SSL_ISSUERCERT]) {
|
if (data->set.str[STRING_SSL_ISSUERCERT]) {
|
||||||
SECStatus ret;
|
SECStatus ret = SECFailure;
|
||||||
bool nickname_alloc = FALSE;
|
bool is_nickname;
|
||||||
char *nickname = fmt_nickname(data->set.str[STRING_SSL_ISSUERCERT],
|
char *nickname = fmt_nickname(data, STRING_SSL_ISSUERCERT, &is_nickname);
|
||||||
&nickname_alloc);
|
|
||||||
|
|
||||||
if(!nickname)
|
if(!nickname)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
if(is_nickname)
|
||||||
|
/* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
|
||||||
ret = check_issuer_cert(connssl->handle, nickname);
|
ret = check_issuer_cert(connssl->handle, nickname);
|
||||||
|
|
||||||
if(nickname_alloc)
|
|
||||||
free(nickname);
|
free(nickname);
|
||||||
|
|
||||||
if(SECFailure == ret) {
|
if(SECFailure == ret) {
|
||||||
|
Reference in New Issue
Block a user