Package: gnutls-bin Tags: patch The DN input mechanism used by certtool when creating certificates is braindamaged. Instead of asking for a fully-formed DN, it asks for a handful of attributes, and enforces a particlar order on them. This is useless when you wanted a certificate that has a given attribute more than once, or in a more normal order (who the heck puts O before OU, or C at the start?).
Not exactly complete, because I couldn't remember all the attribute names offhand, but here's a quickly hacked up patch that does it properly. Supports c, ou, o, and cn, which is enough for most things and lets me create my "cn=foo, ou=bar, ou=baz, o=quux" certificates. -- .''`. ** Debian GNU/Linux ** | Andrew Suffield : :' : http://www.debian.org/ | `. `' | `- -><- |
diff -u gnutls11-1.0.16/src/certtool.c gnutls11-1.0.16/src/certtool.c
--- gnutls11-1.0.16/src/certtool.c
+++ gnutls11-1.0.16/src/certtool.c
@@ -248,14 +248,17 @@
/* set the DN.
*/
- get_country_crt_set( crt);
- get_organization_crt_set(crt);
- get_unit_crt_set( crt);
- get_locality_crt_set( crt);
- get_state_crt_set( crt);
- get_cn_crt_set( crt);
- get_uid_crt_set( crt);
- get_oid_crt_set( crt);
+ if (!get_dn_crt_set( crt))
+ {
+ get_unit_crt_set( crt);
+ get_country_crt_set( crt);
+ get_organization_crt_set(crt);
+ get_locality_crt_set( crt);
+ get_state_crt_set( crt);
+ get_cn_crt_set( crt);
+ get_uid_crt_set( crt);
+ get_oid_crt_set( crt);
+ }
if (!batch) fprintf(stderr, "This field should not be used in
new certificates.\n");
--- gnutls11-1.0.16.orig/src/certtool-cfg.c
+++ gnutls11-1.0.16/src/certtool-cfg.c
@@ -29,11 +29,13 @@
#include <cfg+.h>
#include <gnutls/x509.h>
#include <string.h>
+#include <ctype.h>
extern int batch;
typedef struct _cfg_ctx
{
+ char *dn;
char *organization;
char *unit;
char *locality;
@@ -84,6 +86,7 @@
/* Option set */
struct cfg_option options[] = {
+ {NULL, '\0', "dn", CFG_STR, (void *) &cfg.dn, 0},
{NULL, '\0', "organization", CFG_STR, (void *)
&cfg.organization, 0},
{NULL, '\0', "unit", CFG_STR, (void *) &cfg.unit, 0},
{NULL, '\0', "locality", CFG_STR, (void *) &cfg.locality, 0},
@@ -245,6 +248,119 @@
return read_str( "Enter the URI of the CRL distribution point:
");
}
+int attrcmp(const char *attr1, const char *attr2, size_t attr2_len)
+{
+ size_t attr1_len = strlen(attr1);
+ if (attr1_len != attr2_len)
+ return 0;
+ return strncasecmp(attr1, attr2, attr1_len) == 0;
+}
+
+void dn_attr_crt_set( gnutls_x509_crt crt, const char *attr, size_t attr_len,
const char *value, size_t value_len)
+{
+ const char *oid = NULL;
+ int ret;
+
+ if (attrcmp("cn", attr, attr_len))
+ oid = GNUTLS_OID_X520_COMMON_NAME;
+ else if (attrcmp("o", attr, attr_len))
+ oid = GNUTLS_OID_X520_ORGANIZATION_NAME;
+ else if (attrcmp("ou", attr, attr_len))
+ oid = GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME;
+ else if (attrcmp("c", attr, attr_len))
+ oid = GNUTLS_OID_X520_COUNTRY_NAME;
+
+ if (!oid)
+ {
+ fprintf(stderr, "dn_attr_crt_set: unknown attribute '%.*s'\n", attr_len,
attr);
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_set_dn_by_oid(crt, oid, 0, value, value_len);
+ if (ret < 0) {
+ fprintf(stderr, "dn_attr_crt_set: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+}
+
+void dn_crt_set( gnutls_x509_crt crt, const char *dn)
+{
+ const char *p = dn;
+
+ /* For each element */
+ while (*p && *p != '\n')
+ {
+ const char *attribute_name_start;
+ const char *attribute_name_end;
+ const char *attribute_value_start;
+ const char *attribute_value_end;
+ size_t attribute_name_len;
+ size_t attribute_value_len;
+
+ /* Skip leading whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Attribute name */
+ attribute_name_start = p;
+ while (isalpha(*p))
+ p++;
+ attribute_name_end = p;
+
+ /* Whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Equals sign */
+ if (*p != '=')
+ {
+ fprintf(stderr, "dn_crt_set: syntax error\n");
+ exit(1);
+ }
+ p++;
+
+ /* Whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Attribute value */
+ attribute_value_start = p;
+ while (*p && *p != ',' && *p != '\n')
+ p++;
+ attribute_value_end = p;
+ while (attribute_value_end > attribute_value_start &&
isspace(attribute_value_end[-1]))
+ attribute_value_end--;
+
+ /* Comma, or the end of the string */
+ if (*p)
+ p++;
+
+ attribute_name_len = attribute_name_end - attribute_name_start;
+ attribute_value_len = attribute_value_end - attribute_value_start;
+
+ dn_attr_crt_set(crt, attribute_name_start, attribute_name_len,
attribute_value_start, attribute_value_len);
+ }
+}
+
+int get_dn_crt_set( gnutls_x509_crt crt)
+{
+ if (batch) {
+ if (!cfg.dn) return 0;
+ dn_crt_set(crt, cfg.dn);
+ return 1;
+ } else {
+ char input[256];
+
+ fputs( "Enter the full DN of the certificate:", stderr);
+ fgets( input, sizeof(input), stdin);
+
+ if (strlen(input)==1) /* only newline */ return 0;
+
+ dn_crt_set(crt, input);
+ return 1;
+ }
+}
+
void get_country_crt_set( gnutls_x509_crt crt)
{
int ret;
only in patch2:
unchanged:
--- gnutls11-1.0.16.orig/src/certtool-cfg.h
+++ gnutls11-1.0.16/src/certtool-cfg.h
@@ -19,6 +19,7 @@
const char* get_pass(void);
const char* get_challenge_pass(void);
const char* get_crl_dist_point_url(void);
+int get_dn_crt_set( gnutls_x509_crt crt);
void get_country_crt_set( gnutls_x509_crt crt);
void get_organization_crt_set( gnutls_x509_crt crt);
void get_unit_crt_set( gnutls_x509_crt crt);
only in patch2:
unchanged:
signature.asc
Description: Digital signature

