Commit c0455cbb authored by Lutz Jänicke's avatar Lutz Jänicke
Browse files

Fix escaping when using the -subj option of "openssl req", document

'hidden' -nameopt support. (Robert Joop <joop@fokus.gmd.de>)
parent 17e2c77a
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -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;
+94 −35
Original line number Original line Diff line number Diff line
@@ -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)
	{
	{
	X509_NAME *n = NULL;
	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 *));


	int i, nid, ne_num=0;
	char *sp = subject, *bp = buf;

	int i, ne_num = 0;
	char *ne_name = NULL;
	char *ne_value = NULL;

	char *tmp = NULL;
	char *p[2];


	char *str_list[256];
	X509_NAME *n = NULL;
       
	int nid;
	p[0] = ",/";
	p[1] = "=";

	n = X509_NAME_new();


	tmp = strtok(subject, p[0]);
	if (!buf || !ne_types || !ne_values)
	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;
}
}




+9 −4
Original line number Original line Diff line number Diff line
@@ -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)
+96 −35
Original line number Original line Diff line number Diff line
@@ -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)
	{
	{
	X509_NAME *n = NULL;
	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);
	int i, nid, ne_num=0;
	size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */

	char **ne_types = malloc (max_ne * sizeof (char *));
	char *ne_name = NULL;
	char **ne_values = malloc (max_ne * sizeof (char *));
	char *ne_value = NULL;

	char *tmp = NULL;
	char *p[2];


	char *str_list[256];
	char *sp = subject, *bp = buf;
	int i, ne_num = 0;


	p[0] = ",/";
	X509_NAME *n = NULL;
        p[1] = "=";
	int nid;

	n = X509_NAME_new();


	tmp = strtok(subject, p[0]);
	if (!buf || !ne_types || !ne_values)
	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;
}
}




+3 −1
Original line number Original line Diff line number Diff line
@@ -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>


Loading