Rewrite parse_name
Remove need for multiple arrays, parse the X509 name one RDN at a time. Thanks to Andy for careful review. Reviewed-by: Andy Polyakov <appro@openssl.org>
This commit is contained in:
parent
2fa45e6ee7
commit
db4c08f019
168
apps/apps.c
168
apps/apps.c
@ -1822,134 +1822,84 @@ int parse_yesno(const char *str, int def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
|
* name is expected to be in the format /type0=value0/type1=value1/type2=...
|
||||||
* where characters may be escaped by \
|
* where characters may be escaped by \
|
||||||
*/
|
*/
|
||||||
X509_NAME *parse_name(char *subject, long chtype, int multirdn)
|
X509_NAME *parse_name(const char *cp, long chtype, int canmulti)
|
||||||
{
|
{
|
||||||
size_t buflen = strlen(subject) + 1; /* to copy the types and values
|
int nextismulti = 0;
|
||||||
* into. due to escaping, the copy
|
char *work;
|
||||||
* can only become shorter */
|
X509_NAME *n;
|
||||||
char *buf = OPENSSL_malloc(buflen);
|
|
||||||
size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
|
|
||||||
char **ne_types = OPENSSL_malloc(max_ne * sizeof(char *));
|
|
||||||
char **ne_values = OPENSSL_malloc(max_ne * sizeof(char *));
|
|
||||||
int *mval = OPENSSL_malloc(max_ne * sizeof(int));
|
|
||||||
|
|
||||||
char *sp = subject, *bp = buf;
|
if (*cp++ != '/')
|
||||||
int i, ne_num = 0;
|
return NULL;
|
||||||
|
|
||||||
X509_NAME *n = NULL;
|
n = X509_NAME_new();
|
||||||
int nid;
|
if (n == NULL)
|
||||||
|
return NULL;
|
||||||
|
work = strdup(cp);
|
||||||
|
if (work == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (!buf || !ne_types || !ne_values || !mval) {
|
while (*cp) {
|
||||||
BIO_printf(bio_err, "malloc error\n");
|
char *bp = work;
|
||||||
goto error;
|
char *typestr = bp;
|
||||||
}
|
unsigned char *valstr;
|
||||||
|
int nid;
|
||||||
|
int ismulti = nextismulti;
|
||||||
|
nextismulti = 0;
|
||||||
|
|
||||||
if (*subject != '/') {
|
/* Collect the type */
|
||||||
BIO_printf(bio_err, "Subject does not start with '/'.\n");
|
while (*cp && *cp != '=')
|
||||||
goto error;
|
*bp++ = *cp++;
|
||||||
}
|
if (*cp == '\0') {
|
||||||
sp++; /* skip leading / */
|
|
||||||
|
|
||||||
/* no multivalued RDN by default */
|
|
||||||
mval[ne_num] = 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 error;
|
|
||||||
}
|
|
||||||
} else if (*sp == '=') {
|
|
||||||
sp++;
|
|
||||||
*bp++ = '\0';
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
*bp++ = *sp++;
|
|
||||||
}
|
|
||||||
if (!*sp) {
|
|
||||||
BIO_printf(bio_err,
|
BIO_printf(bio_err,
|
||||||
"end of string encountered while processing type of subject name element #%d\n",
|
"%s: Hit end of string before finding the equals.\n",
|
||||||
ne_num);
|
opt_getprog());
|
||||||
goto error;
|
goto err;
|
||||||
}
|
|
||||||
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 error;
|
|
||||||
}
|
|
||||||
} else if (*sp == '/') {
|
|
||||||
sp++;
|
|
||||||
/* no multivalued RDN by default */
|
|
||||||
mval[ne_num + 1] = 0;
|
|
||||||
break;
|
|
||||||
} else if (*sp == '+' && multirdn) {
|
|
||||||
/*
|
|
||||||
* a not escaped + signals a mutlivalued RDN
|
|
||||||
*/
|
|
||||||
sp++;
|
|
||||||
mval[ne_num + 1] = -1;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
*bp++ = *sp++;
|
|
||||||
}
|
}
|
||||||
*bp++ = '\0';
|
*bp++ = '\0';
|
||||||
ne_num++;
|
++cp;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(n = X509_NAME_new()))
|
/* Collect the value. */
|
||||||
goto error;
|
valstr = (unsigned char *)bp;
|
||||||
|
for (; *cp && *cp != '/'; *bp++ = *cp++) {
|
||||||
|
if (canmulti && *cp == '+') {
|
||||||
|
nextismulti = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*cp == '\\' && *++cp == '\0') {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"%s: escape character at end of string\n",
|
||||||
|
opt_getprog());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*bp++ = '\0';
|
||||||
|
|
||||||
for (i = 0; i < ne_num; i++) {
|
/* If not at EOS (must be + or /), move forward. */
|
||||||
if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) {
|
if (*cp)
|
||||||
BIO_printf(bio_err,
|
++cp;
|
||||||
"Subject Attribute %s has no known NID, skipped\n",
|
|
||||||
ne_types[i]);
|
/* Parse */
|
||||||
|
nid = OBJ_txt2nid(typestr);
|
||||||
|
if (nid == NID_undef) {
|
||||||
|
BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n",
|
||||||
|
opt_getprog(), typestr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
|
||||||
if (!*ne_values[i]) {
|
valstr, strlen((char *)valstr),
|
||||||
BIO_printf(bio_err,
|
-1, ismulti ? -1 : 0))
|
||||||
"No value provided for Subject Attribute %s, skipped\n",
|
goto err;
|
||||||
ne_types[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!X509_NAME_add_entry_by_NID
|
|
||||||
(n, nid, chtype, (unsigned char *)ne_values[i], -1, -1, mval[i]))
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENSSL_free(ne_values);
|
free(work);
|
||||||
OPENSSL_free(ne_types);
|
|
||||||
OPENSSL_free(buf);
|
|
||||||
OPENSSL_free(mval);
|
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
error:
|
err:
|
||||||
X509_NAME_free(n);
|
X509_NAME_free(n);
|
||||||
if (ne_values)
|
free(work);
|
||||||
OPENSSL_free(ne_values);
|
|
||||||
if (ne_types)
|
|
||||||
OPENSSL_free(ne_types);
|
|
||||||
if (mval)
|
|
||||||
OPENSSL_free(mval);
|
|
||||||
if (buf)
|
|
||||||
OPENSSL_free(buf);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +486,7 @@ void free_index(CA_DB *db);
|
|||||||
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
|
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
|
||||||
int parse_yesno(const char *str, int def);
|
int parse_yesno(const char *str, int def);
|
||||||
|
|
||||||
X509_NAME *parse_name(char *str, long chtype, int multirdn);
|
X509_NAME *parse_name(const char *str, long chtype, int multirdn);
|
||||||
int args_verify(char ***pargs, int *pargc,
|
int args_verify(char ***pargs, int *pargc,
|
||||||
int *badarg, X509_VERIFY_PARAM **pm);
|
int *badarg, X509_VERIFY_PARAM **pm);
|
||||||
void policies_print(X509_STORE_CTX *ctx);
|
void policies_print(X509_STORE_CTX *ctx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user