#108 Handle escape characters in a subject (now with test)
Merged 10 months ago by rcritten. Opened 10 months ago by ftweedal.
ftweedal/certmonger pr107bis  into  master

file modified
+2

@@ -772,6 +772,8 @@ 

  	AC_CHECK_HEADER(ldap.h,,AC_MSG_ERROR(ldap.h not found))

  	AC_CHECK_FUNC(ldap_initialize,,AC_CHECK_LIB(ldap,ldap_initialize))

  	AC_CHECK_FUNC(ldap_sasl_interactive_bind_s,,AC_CHECK_LIB(ldap,ldap_sasl_interactive_bind_s))

+ 	AC_CHECK_FUNC(ldap_str2dn,,AC_CHECK_LIB(ldap,ldap_str2dn))

+ 	AC_CHECK_FUNC(ldap_dnfree,,AC_CHECK_LIB(ldap,ldap_dnfree))

  	LDAP_CFLAGS="$CFLAGS"

  	LDAP_LIBS="$LIBS"

  	CFLAGS="$CFLAGSsave"

file modified
+6 -6

@@ -150,7 +150,7 @@ 

  getcert_CFLAGS = $(AM_CFLAGS) $(NSS_CFLAGS) $(UUID_CFLAGS)

  getcert_SOURCES = getcert.c tm.c tm.h

  getcert_LDADD = libcm.a $(GETCERT_LIBS) $(KRB5_LIBS) $(NSS_LIBS) $(UUID_LIBS) \

- 			$(POPT_LIBS) $(LTLIBICONV)

+ 			$(POPT_LIBS) $(LTLIBICONV) $(LDAP_LIBS)

  if WITH_IPA

  bin_PROGRAMS += ipa-getcert

  ipa_getcert_CFLAGS = $(getcert_CFLAGS)

@@ -176,16 +176,16 @@ 

  certmonger_SOURCES = main.c env-system.c tm.c tm.h

  certmonger_LDADD = libcm.a \

  		   $(OPENSSL_LIBS) $(CERTMONGER_LIBS) $(KRB5_LIBS) $(IDN_LIBS) \

- 		   $(GMP_LIBS) $(UUID_LIBS) $(POPT_LIBS) $(LTLIBICONV)

+ 		   $(GMP_LIBS) $(UUID_LIBS) $(POPT_LIBS) $(LTLIBICONV) $(LDAP_LIBS)

  certmonger_session_SOURCES = main.c env-session.c tm.c tm.h

  certmonger_session_LDADD = libcm.a \

  		   $(OPENSSL_LIBS) $(CERTMONGER_LIBS) $(KRB5_LIBS) $(IDN_LIBS) \

- 		   $(GMP_LIBS) $(UUID_LIBS) $(POPT_LIBS) $(LTLIBICONV)

+ 		   $(GMP_LIBS) $(UUID_LIBS) $(POPT_LIBS) $(LTLIBICONV) $(LDAP_LIBS)

  noinst_PROGRAMS = tdbusm-check serial-check nl-check submit-x toklist

  tdbusm_check_SOURCES = tdbusm-check.c tm.c tm.h

- tdbusm_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(POPT_LIBS)

- serial_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(LTLIBICONV)

- nl_check_LDADD = libcm.a $(CERTMONGER_LIBS)

+ tdbusm_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(POPT_LIBS) $(LDAP_LIBS)

+ serial_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(LTLIBICONV) $(LDAP_LIBS)

+ nl_check_LDADD = libcm.a $(CERTMONGER_LIBS) $(LDAP_LIBS)

  submit_x_CFLAGS = $(AM_CFLAGS) $(NSS_CFLAGS) -DCM_SUBMIT_X_MAIN

  submit_x_SOURCES = submit-x.c submit-x.h submit-u.c submit-u.h log.c log.h \

  	tm.c tm.h

file modified
+93 -34

@@ -32,8 +32,11 @@ 

  

  #include <openssl/bn.h>

  #include <openssl/err.h>

+ #include <openssl/objects.h>

  #include <openssl/pem.h>

  

+ #include <ldap.h>

+ 

  #include <talloc.h>

  

  #include "certext.h"

@@ -49,6 +52,7 @@ 

  #include "subproc.h"

  #include "util-m.h"

  #include "util-o.h"

+ #include "util.h"

  

  struct cm_csrgen_state {

  	struct cm_csrgen_state_pvt pvt;

@@ -76,6 +80,89 @@ 

  	return V_ASN1_PRINTABLESTRING;

  }

  

+ static X509_NAME *

+ ldap_dn_to_X509_NAME(char *s) {

+ 	LDAPDN dn = NULL;

+ 	LDAPRDN rdn = NULL;

+ 	LDAPAVA *attr = NULL;

+ 	int ret = ldap_str2dn(s, &dn, LDAP_DN_FORMAT_LDAPV3);

+ 	if (ret != LDAP_SUCCESS)

+ 		return NULL;

+ 

+ 	X509_NAME *x509name = X509_NAME_new();

+ 	if (x509name == NULL)

+ 		return NULL;

+ 

+ 	for (int i = 0; dn[i] != NULL; i++) {

+ 		rdn = dn[i];

+ 		int set = 0; // add next AVA in new RDN

+ 		for (int j = 0; rdn[j] != NULL; j++) {

+ 			attr = rdn[j];

+ 

+ 			// process attribute type

+ 			ASN1_OBJECT *obj = OBJ_txt2obj(

+ 				attr->la_attr.bv_val,

+ 				0 /* allow dotted OIDs */);

+ 			if (obj == NULL) {

+ 				// OpenSSL requires upper-cased short names

+ 				// i.e. "CN", "O", etc.

+ 				// Convert to upper and try again.

+ 				char *attr_upper = str_to_upper(attr->la_attr.bv_val);

+ 				if (attr_upper != NULL) {

+ 					obj = OBJ_txt2obj(attr_upper, 0);

+ 					free(attr_upper);

+ 				}

+ 			}

+ 

+ 			if (obj == NULL) {

+ 				cm_log(

+ 					0,

+ 					"Unrecognised attribute type: (%s). Continuing.\n",

+ 					attr->la_attr.bv_val);

+ 			} else {

+ 				ret = X509_NAME_add_entry_by_OBJ(

+ 					x509name,

+ 					obj,

+ 					astring_type(

+ 						attr->la_attr.bv_val,

+ 						attr->la_value.bv_val,

+ 						attr->la_value.bv_len),

+ 					(unsigned char *) attr->la_value.bv_val,

+ 					attr->la_value.bv_len,

+ 					-1, // append to RDN

+ 					set);

+ 				if (ret == 1) {

+ 					set = -1; // add next AVA to previous RDN

+ 				} else {

+ 					cm_log(

+ 						0,

+ 						"Failed to add AVA to CSR: (%s=%s). Continuing.\n",

+ 						attr->la_attr.bv_val,

+ 						attr->la_value.bv_val);

+ 				}

+ 			}

+ 		}

+ 	}

+ 	ldap_dnfree(dn);

+ 	return x509name;

+ }

+ 

+ /* Create a single-AVA X509_NAME, with given string as CN */

+ static X509_NAME *

+ cn_to_X509_NAME(const char *s) {

+ 	X509_NAME *n = X509_NAME_new();

+ 	if (n != NULL) {

+ 		X509_NAME_add_entry_by_txt(

+ 			n,

+ 			"CN",

+ 			astring_type("CN", s, -1),

+ 			(unsigned char *) s,

+ 			-1 /* compute value length internally */,

+ 			-1, 0);

+ 	}

+ 	return n;

+ }

+ 

  static int

  cm_csrgen_o_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry,

  		 void *userdata)

@@ -92,7 +179,7 @@ 

  	NETSCAPE_SPKAC spkac;

  	EVP_PKEY *pkey;

  	BIGNUM *serialbn;

- 	char buf[LINE_MAX], *p, *q, *s, *nickname, *pin, *password, *filename;

+ 	char buf[LINE_MAX], *s, *nickname, *pin, *password, *filename;

  	unsigned char *extensions, *upassword, *bmp, *name, *up, *uq, md[CM_DIGEST_MAX];

  	char *spkidec, *mcb64, *nows;

  	const char *default_cn = CM_DEFAULT_CERT_SUBJECT_CN, *spkihex = NULL;

@@ -193,42 +280,14 @@ 

  			if ((subject == NULL) &&

  			    (entry->cm_template_subject != NULL) &&

  			    (strlen(entry->cm_template_subject) != 0)) {

- 				/* This isn't really correct, but it will

- 				 * probably do for now. */

- 				p = entry->cm_template_subject;

- 				q = p + strcspn(p, ",");

- 				subject = X509_NAME_new();

- 				if (subject != NULL) {

- 					while (*p != '\0') {

- 						if ((s = memchr(p, '=', q - p)) != NULL) {

- 							*s = '\0';

- 							for (i = 0; p[i] != '\0'; i++) {

- 								p[i] = toupper(p[i]);

- 							}

- 							X509_NAME_add_entry_by_txt(subject,

- 										   p, astring_type(p, s + 1, q - s - 1),

- 										   (unsigned char *) (s + 1), q - s - 1,

- 										   -1, 0);

- 							*s = '=';

- 						} else {

- 							X509_NAME_add_entry_by_txt(subject,

- 										   "CN", astring_type("CN", p, q - p),

- 										   (unsigned char *) p, q - p,

- 										   -1, 0);

- 						}

- 						p = q + strspn(q, ",");

- 						q = p + strcspn(p, ",");

- 					}

+ 				subject = ldap_dn_to_X509_NAME(entry->cm_template_subject);

+ 

+ 				if (subject == NULL) {

+ 					subject = cn_to_X509_NAME(entry->cm_template_subject);

  				}

  			}

  			if (subject == NULL) {

- 				subject = X509_NAME_new();

- 				if (subject != NULL) {

- 					X509_NAME_add_entry_by_txt(subject,

- 								   "CN", astring_type("CN", default_cn, -1),

- 								   (const unsigned char *) default_cn,

- 								   -1, -1, 0);

- 				}

+ 				subject = cn_to_X509_NAME(default_cn);

  			}

  			if (subject != NULL) {

  				util_X509_REQ_set_subject_name(req, subject);

file modified
+14

@@ -176,3 +176,17 @@ 

      free(tmp);

      return NULL;

  }

+ 

+ void str_to_upper_inplace(char *s) {

+     if (NULL == s) return;

+     for (; *s != '\0'; s++) {

+         *s = toupper(*s);

+     }

+ }

+ 

+ char *str_to_upper(const char *s) {

+     char *ret = strdup(s);

+     if (ret != NULL)

+         str_to_upper_inplace(ret);

+     return ret;

+ }

file modified
+13

@@ -21,4 +21,17 @@ 

  char *read_config_file(const char *filename);

  char *get_config_entry(char *data, const char *section, const char *key);

  

+ /*

+  * Convert string to upper case in place.

+  * String must be null-terminated.  Locale-unaware.

+  */

+ void str_to_upper_inplace(char *s);

+ 

+ /*

+  * Return upper-cased copy of string.

+  * String must be null-terminated.  Locale-unaware.

+  * Return NULL on error (insufficient memory).

+  */

+ char *str_to_upper(const char *s);

+ 

  #endif

@@ -26,7 +26,7 @@ 

     13:d=3  hl=2 l=  20 cons: SET               

     15:d=4  hl=2 l=  18 cons: SEQUENCE          

     17:d=5  hl=2 l=   3 prim: OBJECT            :commonName

-    22:d=5  hl=2 l=  11 prim: PRINTABLESTRING   :Babs Jensen

+    22:d=5  hl=2 l=  11 prim: PRINTABLESTRING   :Cloud, Inc.

     35:d=2  hl=4 l= 290 cons: SEQUENCE          

     39:d=3  hl=2 l=  13 cons: SEQUENCE          

     41:d=4  hl=2 l=   9 prim: OBJECT            :rsaEncryption

file modified
+1 -1

@@ -299,7 +299,7 @@ 

  ns_certtype=

  

  size=2048

- subject="CN=Babs Jensen"

+ subject="CN=Cloud\, Inc."

  hostname=localhost,localhost.localdomain

  email=root@localhost,root@localhost.localdomain

  principal=root@EXAMPLE.COM,root@FOO.EXAMPLE.COM

file modified
+2 -1

@@ -3,7 +3,8 @@ 

  	    $(POPT_CFLAGS) -I$(top_builddir)/src -I$(top_srcdir)/src

  LDADD = libtools.a $(top_builddir)/src/libcm.a $(top_srcdir)/src/env-system.c \

  	libtools.a $(OPENSSL_LIBS) $(CERTMONGER_LIBS) $(KRB5_LIBS) $(IDN_LIBS) \

- 	$(GMP_LIBS) $(UUID_LIBS) $(RESOLV_LIBS) $(POPT_LIBS) $(LTLIBICONV)

+ 	$(GMP_LIBS) $(UUID_LIBS) $(RESOLV_LIBS) $(POPT_LIBS) $(LTLIBICONV) \

+ 	$(LDAP_LIBS)

  

  noinst_SCRIPTS = cachain.sh