curl -E: allow to escape ':' in cert nickname

This commit is contained in:
Jared Jennings 2013-04-05 16:01:31 +02:00 committed by Kamil Dudka
parent 35874298e4
commit 865d4138a0
2 changed files with 102 additions and 24 deletions

View File

@ -21,6 +21,7 @@ This release includes the following changes:
o usercertinmem.c: add example showing user cert in memory
o url: Added smtp and pop3 hostnames to the protocol detection list
o imap/pop3/smtp: Added support for enabling the SASL initial response [8]
o curl -E: allow to use ':' in certificate nicknames [10]
o
This release includes the following bugfixes:
@ -67,4 +68,4 @@ References to bug reports and discussions on issues:
[7] = http://curl.haxx.se/bug/view.cgi?id=1218
[8] = http://curl.haxx.se/mail/lib-2012-03/0114.html
[9] = http://curl.haxx.se/mail/lib-2013-05/0000.html
[10]
[10] = http://curl.haxx.se/bug/view.cgi?id=1196

View File

@ -286,6 +286,99 @@ static const struct feat feats[] = {
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
};
/* https://sourceforge.net/p/curl/bugs/1196/ */
static void parse_cert_parameter(const char *cert_parameter,
char **certname,
char **passphrase)
{
size_t param_length = strlen(cert_parameter);
size_t parsed_chars = 0;
size_t span;
const char *param_place = NULL;
char *certname_place = NULL;
/* most trivial assumption: cert_parameter is empty */
if(param_length == 0) {
*certname = NULL;
*passphrase = NULL;
return;
}
/* next less trivial: cert_parameter contains no colon nor backslash; this
* means no passphrase was given and no characters escaped */
if(!strpbrk(cert_parameter, ":\\")) {
*certname = strdup(cert_parameter);
*passphrase = NULL;
return;
}
/* deal with escaped chars; find unescaped colon if it exists */
*certname = (char *) malloc(param_length + 1);
*passphrase = NULL;
param_place = cert_parameter;
certname_place = *certname;
param_place = cert_parameter;
while(*param_place) {
span = strcspn(param_place, ":\\");
strncpy(certname_place, param_place, span);
param_place += span;
certname_place += span;
*certname_place = '\0';
/* we just ate all the non-special chars. now we're on either a special
* char or the end of the string. */
switch(*param_place) {
case '\0':
break;
case '\\':
param_place++;
switch(*param_place) {
case '\0':
*certname_place++ = '\\';
break;
case '\\':
*certname_place++ = '\\';
param_place++;
break;
case ':':
*certname_place++ = ':';
param_place++;
break;
default:
*certname_place++ = '\\';
*certname_place++ = *param_place;
param_place++;
break;
}
break;
case ':':
/* Since we live in a world of weirdness and confusion, the win32
dudes can use : when using drive letters and thus c:\file:password
needs to work. In order not to break compatibility, we still use : as
separator, but we try to detect when it is used for a file name! On
windows. */
#ifdef WIN32
if(param_place &&
(param_place == &cert_parameter[1]) &&
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
(ISALPHA(cert_parameter[0])) ) {
/* colon in the second column, followed by a backslash, and the
first character is an alphabetic letter:
this is a drive letter colon */
*certname_place++ = ':';
param_place++;
break;
}
#endif
/* escaped colons and Windows drive letter colons were handled
* above; if we're still here, this is a separating colon */
param_place++;
if(strlen(param_place) > 0) {
*passphrase = strdup(param_place);
}
return;
break;
}
}
}
ParameterError getparameter(char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
bool *usedarg, /* set to TRUE if the arg
@ -1207,30 +1300,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
default: /* certificate file */
{
char *ptr = strchr(nextarg, ':');
/* Since we live in a world of weirdness and confusion, the win32
dudes can use : when using drive letters and thus
c:\file:password needs to work. In order not to break
compatibility, we still use : as separator, but we try to detect
when it is used for a file name! On windows. */
#ifdef WIN32
if(ptr &&
(ptr == &nextarg[1]) &&
(nextarg[2] == '\\' || nextarg[2] == '/') &&
(ISALPHA(nextarg[0])) )
/* colon in the second column, followed by a backslash, and the
first character is an alphabetic letter:
this is a drive letter colon */
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
#endif
if(ptr) {
/* we have a password too */
*ptr = '\0';
ptr++;
GetStr(&config->key_passwd, ptr);
char *certname, *passphrase;
parse_cert_parameter(nextarg, &certname, &passphrase);
if(certname) {
GetStr(&config->cert, certname);
}
if(passphrase) {
GetStr(&config->key_passwd, passphrase);
}
GetStr(&config->cert, nextarg);
cleanarg(nextarg);
}
}