Fix escaping when using the -subj option of "openssl req", document
'hidden' -nameopt support. (Robert Joop <joop@fokus.gmd.de>)
This commit is contained in:
parent
17e2c77a77
commit
c0455cbb18
4
CHANGES
4
CHANGES
@ -40,6 +40,10 @@
|
|||||||
|
|
||||||
Changes between 0.9.6d and 0.9.7 [XX xxx 2002]
|
Changes between 0.9.6d and 0.9.7 [XX xxx 2002]
|
||||||
|
|
||||||
|
*) Fix escaping of non-ASCII characters when using the -subj option
|
||||||
|
of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>)
|
||||||
|
[Lutz Jaenicke]
|
||||||
|
|
||||||
*) Make object definitions compliant to LDAP (RFC2256): SN is the short
|
*) Make object definitions compliant to LDAP (RFC2256): SN is the short
|
||||||
form for "surname", serialNumber has no short form.
|
form for "surname", serialNumber has no short form.
|
||||||
Use "mail" as the short name for "rfc822Mailbox" according to RFC2798;
|
Use "mail" as the short name for "rfc822Mailbox" according to RFC2798;
|
||||||
|
127
apps/ca.c
127
apps/ca.c
@ -3023,63 +3023,122 @@ int make_revoked(X509_REVOKED *rev, char *str)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
|
||||||
|
* where characters may be escaped by \
|
||||||
|
*/
|
||||||
static X509_NAME *do_subject(char *subject)
|
static X509_NAME *do_subject(char *subject)
|
||||||
{
|
{
|
||||||
|
size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
|
||||||
|
char *buf = malloc (buflen);
|
||||||
|
size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
|
||||||
|
char **ne_types = malloc (max_ne * sizeof (char *));
|
||||||
|
char **ne_values = malloc (max_ne * sizeof (char *));
|
||||||
|
|
||||||
|
char *sp = subject, *bp = buf;
|
||||||
|
int i, ne_num = 0;
|
||||||
|
|
||||||
X509_NAME *n = NULL;
|
X509_NAME *n = NULL;
|
||||||
|
int nid;
|
||||||
|
|
||||||
int i, nid, ne_num=0;
|
if (!buf || !ne_types || !ne_values)
|
||||||
|
|
||||||
char *ne_name = NULL;
|
|
||||||
char *ne_value = NULL;
|
|
||||||
|
|
||||||
char *tmp = NULL;
|
|
||||||
char *p[2];
|
|
||||||
|
|
||||||
char *str_list[256];
|
|
||||||
|
|
||||||
p[0] = ",/";
|
|
||||||
p[1] = "=";
|
|
||||||
|
|
||||||
n = X509_NAME_new();
|
|
||||||
|
|
||||||
tmp = strtok(subject, p[0]);
|
|
||||||
while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
|
|
||||||
{
|
{
|
||||||
char *token = tmp;
|
BIO_printf(bio_err, "malloc error\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
|
||||||
while (token[0] == ' ')
|
if (*subject != '/')
|
||||||
token++;
|
{
|
||||||
str_list[ne_num] = token;
|
BIO_printf(bio_err, "Subject does not start with '/'.\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
sp++; /* skip leading / */
|
||||||
|
|
||||||
tmp = strtok(NULL, p[0]);
|
while (*sp)
|
||||||
|
{
|
||||||
|
/* collect type */
|
||||||
|
ne_types[ne_num] = bp;
|
||||||
|
while (*sp)
|
||||||
|
{
|
||||||
|
if (*sp == '\\') /* is there anything to escape in the type...? */
|
||||||
|
if (*++sp)
|
||||||
|
*bp++ = *sp++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "escape character at end of string\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
else if (*sp == '=')
|
||||||
|
{
|
||||||
|
sp++;
|
||||||
|
*bp++ = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*bp++ = *sp++;
|
||||||
|
}
|
||||||
|
if (!*sp)
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
ne_values[ne_num] = bp;
|
||||||
|
while (*sp)
|
||||||
|
{
|
||||||
|
if (*sp == '\\')
|
||||||
|
if (*++sp)
|
||||||
|
*bp++ = *sp++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "escape character at end of string\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
else if (*sp == '/')
|
||||||
|
{
|
||||||
|
sp++;
|
||||||
|
*bp++ = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*bp++ = *sp++;
|
||||||
|
}
|
||||||
|
*bp++ = '\0';
|
||||||
ne_num++;
|
ne_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(n = X509_NAME_new()))
|
||||||
|
goto error0;
|
||||||
|
|
||||||
for (i = 0; i < ne_num; i++)
|
for (i = 0; i < ne_num; i++)
|
||||||
{
|
{
|
||||||
ne_name = strtok(str_list[i], p[1]);
|
if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
|
||||||
ne_value = strtok(NULL, p[1]);
|
|
||||||
|
|
||||||
if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
|
|
||||||
{
|
{
|
||||||
BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
|
BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ne_value == NULL)
|
if (!*ne_values[i])
|
||||||
{
|
{
|
||||||
BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
|
BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
|
if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_values[i], -1,-1,0))
|
||||||
{
|
goto error1;
|
||||||
X509_NAME_free(n);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free (ne_values);
|
||||||
|
free (ne_types);
|
||||||
|
free (buf);
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
|
error1:
|
||||||
|
X509_NAME_free(n);
|
||||||
|
error0:
|
||||||
|
free (ne_values);
|
||||||
|
free (ne_types);
|
||||||
|
free (buf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
13
apps/crl.c
13
apps/crl.c
@ -87,6 +87,7 @@ static char *crl_usage[]={
|
|||||||
" -noout - no CRL output\n",
|
" -noout - no CRL output\n",
|
||||||
" -CAfile name - verify CRL using certificates in file \"name\"\n",
|
" -CAfile name - verify CRL using certificates in file \"name\"\n",
|
||||||
" -CApath dir - verify CRL using certificates in \"dir\"\n",
|
" -CApath dir - verify CRL using certificates in \"dir\"\n",
|
||||||
|
" -nameopt arg - various certificate name options\n",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ int MAIN(int, char **);
|
|||||||
|
|
||||||
int MAIN(int argc, char **argv)
|
int MAIN(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
unsigned long nmflag = 0;
|
||||||
X509_CRL *x=NULL;
|
X509_CRL *x=NULL;
|
||||||
char *CAfile = NULL, *CApath = NULL;
|
char *CAfile = NULL, *CApath = NULL;
|
||||||
int ret=1,i,num,badops=0;
|
int ret=1,i,num,badops=0;
|
||||||
@ -105,7 +107,7 @@ int MAIN(int argc, char **argv)
|
|||||||
char *infile=NULL,*outfile=NULL;
|
char *infile=NULL,*outfile=NULL;
|
||||||
int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0;
|
int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0;
|
||||||
int fingerprint = 0;
|
int fingerprint = 0;
|
||||||
char **pp,buf[256];
|
char **pp;
|
||||||
X509_STORE *store = NULL;
|
X509_STORE *store = NULL;
|
||||||
X509_STORE_CTX ctx;
|
X509_STORE_CTX ctx;
|
||||||
X509_LOOKUP *lookup = NULL;
|
X509_LOOKUP *lookup = NULL;
|
||||||
@ -188,6 +190,11 @@ int MAIN(int argc, char **argv)
|
|||||||
text = 1;
|
text = 1;
|
||||||
else if (strcmp(*argv,"-hash") == 0)
|
else if (strcmp(*argv,"-hash") == 0)
|
||||||
hash= ++num;
|
hash= ++num;
|
||||||
|
else if (strcmp(*argv,"-nameopt") == 0)
|
||||||
|
{
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
if (!set_name_ex(&nmflag, *(++argv))) goto bad;
|
||||||
|
}
|
||||||
else if (strcmp(*argv,"-issuer") == 0)
|
else if (strcmp(*argv,"-issuer") == 0)
|
||||||
issuer= ++num;
|
issuer= ++num;
|
||||||
else if (strcmp(*argv,"-lastupdate") == 0)
|
else if (strcmp(*argv,"-lastupdate") == 0)
|
||||||
@ -271,9 +278,7 @@ bad:
|
|||||||
{
|
{
|
||||||
if (issuer == i)
|
if (issuer == i)
|
||||||
{
|
{
|
||||||
X509_NAME_oneline(X509_CRL_get_issuer(x),
|
print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag);
|
||||||
buf,256);
|
|
||||||
BIO_printf(bio_out,"issuer= %s\n",buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash == i)
|
if (hash == i)
|
||||||
|
131
apps/req.c
131
apps/req.c
@ -505,6 +505,7 @@ bad:
|
|||||||
BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
|
BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
|
||||||
BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n");
|
BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n");
|
||||||
BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n");
|
BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n");
|
||||||
|
BIO_printf(bio_err," -nameopt arg - various certificate name options\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,66 +1211,126 @@ err:
|
|||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
|
||||||
|
* where characters may be escaped by \
|
||||||
|
*/
|
||||||
static int build_subject(X509_REQ *req, char *subject, unsigned long chtype)
|
static int build_subject(X509_REQ *req, char *subject, unsigned long chtype)
|
||||||
{
|
{
|
||||||
|
size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
|
||||||
|
char *buf = malloc (buflen);
|
||||||
|
size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
|
||||||
|
char **ne_types = malloc (max_ne * sizeof (char *));
|
||||||
|
char **ne_values = malloc (max_ne * sizeof (char *));
|
||||||
|
|
||||||
|
char *sp = subject, *bp = buf;
|
||||||
|
int i, ne_num = 0;
|
||||||
|
|
||||||
X509_NAME *n = NULL;
|
X509_NAME *n = NULL;
|
||||||
|
int nid;
|
||||||
|
|
||||||
int i, nid, ne_num=0;
|
if (!buf || !ne_types || !ne_values)
|
||||||
|
|
||||||
char *ne_name = NULL;
|
|
||||||
char *ne_value = NULL;
|
|
||||||
|
|
||||||
char *tmp = NULL;
|
|
||||||
char *p[2];
|
|
||||||
|
|
||||||
char *str_list[256];
|
|
||||||
|
|
||||||
p[0] = ",/";
|
|
||||||
p[1] = "=";
|
|
||||||
|
|
||||||
n = X509_NAME_new();
|
|
||||||
|
|
||||||
tmp = strtok(subject, p[0]);
|
|
||||||
while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
|
|
||||||
{
|
{
|
||||||
char *token = tmp;
|
BIO_printf(bio_err, "malloc error\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
|
||||||
while (token[0] == ' ')
|
if (*subject != '/')
|
||||||
token++;
|
{
|
||||||
str_list[ne_num] = token;
|
BIO_printf(bio_err, "Subject does not start with '/'.\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
sp++; /* skip leading / */
|
||||||
|
|
||||||
tmp = strtok(NULL, p[0]);
|
while (*sp)
|
||||||
|
{
|
||||||
|
/* collect type */
|
||||||
|
ne_types[ne_num] = bp;
|
||||||
|
while (*sp)
|
||||||
|
{
|
||||||
|
if (*sp == '\\') /* is there anything to escape in the type...? */
|
||||||
|
if (*++sp)
|
||||||
|
*bp++ = *sp++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "escape character at end of string\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
else if (*sp == '=')
|
||||||
|
{
|
||||||
|
sp++;
|
||||||
|
*bp++ = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*bp++ = *sp++;
|
||||||
|
}
|
||||||
|
if (!*sp)
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
ne_values[ne_num] = bp;
|
||||||
|
while (*sp)
|
||||||
|
{
|
||||||
|
if (*sp == '\\')
|
||||||
|
if (*++sp)
|
||||||
|
*bp++ = *sp++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "escape character at end of string\n");
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
else if (*sp == '/')
|
||||||
|
{
|
||||||
|
sp++;
|
||||||
|
*bp++ = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*bp++ = *sp++;
|
||||||
|
}
|
||||||
|
*bp++ = '\0';
|
||||||
ne_num++;
|
ne_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(n = X509_NAME_new()))
|
||||||
|
goto error0;
|
||||||
|
|
||||||
for(i = 0; i < ne_num; i++)
|
for(i = 0; i < ne_num; i++)
|
||||||
{
|
{
|
||||||
ne_name = strtok(str_list[i], p[1]);
|
if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
|
||||||
ne_value = strtok(NULL, p[1]);
|
|
||||||
|
|
||||||
if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
|
|
||||||
{
|
{
|
||||||
BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
|
BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ne_value == NULL)
|
if (!*ne_values[i])
|
||||||
{
|
{
|
||||||
BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
|
BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_value, -1,-1,0))
|
if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
|
||||||
{
|
goto error1;
|
||||||
X509_NAME_free(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!X509_REQ_set_subject_name(req, n))
|
if (!X509_REQ_set_subject_name(req, n))
|
||||||
return 0;
|
goto error1;
|
||||||
X509_NAME_free(n);
|
X509_NAME_free(n);
|
||||||
|
free (ne_values);
|
||||||
|
free (ne_types);
|
||||||
|
free (buf);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
error1:
|
||||||
|
X509_NAME_free(n);
|
||||||
|
error0:
|
||||||
|
free (ne_values);
|
||||||
|
free (ne_types);
|
||||||
|
free (buf);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,7 +216,9 @@ a filename containing a certificate to revoke.
|
|||||||
|
|
||||||
=item B<-subj arg>
|
=item B<-subj arg>
|
||||||
|
|
||||||
supersedes subject name given in the request
|
supersedes subject name given in the request.
|
||||||
|
The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
|
||||||
|
characters may be escaped by \ (backslash), no spaces are skipped.
|
||||||
|
|
||||||
=item B<-crlexts section>
|
=item B<-crlexts section>
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ B<openssl> B<req>
|
|||||||
[B<-extensions section>]
|
[B<-extensions section>]
|
||||||
[B<-reqexts section>]
|
[B<-reqexts section>]
|
||||||
[B<-utf8>]
|
[B<-utf8>]
|
||||||
|
[B<-nameopt>]
|
||||||
[B<-batch>]
|
[B<-batch>]
|
||||||
[B<-verbose>]
|
[B<-verbose>]
|
||||||
|
|
||||||
@ -168,6 +169,8 @@ the B<OPENSSL_CONF> environment variable.
|
|||||||
|
|
||||||
sets subject name for new request or supersedes the subject name
|
sets subject name for new request or supersedes the subject name
|
||||||
when processing a request.
|
when processing a request.
|
||||||
|
The arg must be formatted as I</type0=value0/type1=value1/type2=...>,
|
||||||
|
characters may be escaped by \ (backslash), no spaces are skipped.
|
||||||
|
|
||||||
=item B<-x509>
|
=item B<-x509>
|
||||||
|
|
||||||
@ -206,6 +209,13 @@ default they are interpreted as ASCII. This means that the field
|
|||||||
values, whether prompted from a terminal or obtained from a
|
values, whether prompted from a terminal or obtained from a
|
||||||
configuration file, must be valid UTF8 strings.
|
configuration file, must be valid UTF8 strings.
|
||||||
|
|
||||||
|
=item B<-nameopt option>
|
||||||
|
|
||||||
|
option which determines how the subject or issuer names are displayed. The
|
||||||
|
B<option> argument can be a single option or multiple options separated by
|
||||||
|
commas. Alternatively the B<-nameopt> switch may be used more than once to
|
||||||
|
set multiple options. See the L<x509(1)|x509(1)> manual page for details.
|
||||||
|
|
||||||
=item B<-asn1-kludge>
|
=item B<-asn1-kludge>
|
||||||
|
|
||||||
by default the B<req> command outputs certificate requests containing
|
by default the B<req> command outputs certificate requests containing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user