* Version 3.1.7 (unreleased)
+** certtool: Added option "dn" which allows to directly set the DN
+in a template from an RFC4514 string.
+
+** libgnutls: Added functions to directly set the DN in a certificate
+or request from an RFC4514 string.
+
** libgnutls: Simplified the DTLS sliding window implementation.
** libgnutls: Added the gnutls_sbuf_t structure and accompanying
gnutls_sbuf_init: Added
gnutls_sbuf_flush: Added
gnutls_sbuf_queue: Added
+gnutls_x509_crt_set_dn: Added
+gnutls_x509_crq_set_dn: Added
* Version 3.1.6 (released 2013-01-02)
in order to avoid having people working on the same thing.
Current list:
+* Add gnutls_x509_crt_set_dn() to allow setting a DN using an RFC4514
+ string (as well as the x509_crq_set_dn).
* When importing a PKCS #11 certificate, check for its issuers to generate a
chain (e.g. use the DN to retrieve possible signers).
* Think about supporting the groups in RFC3526 and RFC5114. If other
The last step ensures that the requester is in
possession of the private key.
-@showfuncE{gnutls_x509_crq_set_version,gnutls_x509_crq_set_dn_by_oid,gnutls_x509_crq_set_key_usage,gnutls_x509_crq_set_key_purpose_oid,gnutls_x509_crq_set_basic_constraints}
+@showfuncF{gnutls_x509_crq_set_version,gnutls_x509_crq_set_dn,gnutls_x509_crq_set_dn_by_oid,gnutls_x509_crq_set_key_usage,gnutls_x509_crq_set_key_purpose_oid,gnutls_x509_crq_set_basic_constraints}
The @funcref{gnutls_x509_crq_set_key} and @funcref{gnutls_x509_crq_sign2}
functions associate the request with a private key and sign it. If a
/* X.509 Certificate writing.
*/
+ int gnutls_x509_crt_set_dn (gnutls_x509_crt_t crt, const char *dn, const char** err);
+
int gnutls_x509_crt_set_dn_by_oid (gnutls_x509_crt_t crt,
const char *oid,
unsigned int raw_flag,
const char *oid, int indx,
unsigned int raw_flag, void *buf,
size_t * sizeof_buf);
+ int gnutls_x509_crq_set_dn (gnutls_x509_crq_t crq, const char *dn, const char** err);
int gnutls_x509_crq_set_dn_by_oid (gnutls_x509_crq_t crq,
const char *oid,
unsigned int raw_flag,
gnutls_sbuf_init;
gnutls_sbuf_flush;
gnutls_sbuf_queue;
+ gnutls_x509_crt_set_dn;
+ gnutls_x509_crq_set_dn;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {
rfc2818_hostname.c \
sign.c \
verify.c \
- x509.c \
+ x509.c x509_dn.c \
x509_int.h \
x509_write.c \
verify-high.c \
static const struct oid_to_string _oid2str[] = {
/* PKIX
*/
- {"1.3.6.1.5.5.7.9.1", "dateOfBirth", NULL, ASN1_ETYPE_GENERALIZED_TIME},
{"1.3.6.1.5.5.7.9.2", "placeOfBirth", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"1.3.6.1.5.5.7.9.3", "gender", NULL, ASN1_ETYPE_PRINTABLE_STRING},
{"1.3.6.1.5.5.7.9.4", "countryOfCitizenship", NULL, ASN1_ETYPE_PRINTABLE_STRING},
{"1.3.6.1.5.5.7.9.5", "countryOfResidence", NULL, ASN1_ETYPE_PRINTABLE_STRING},
{"2.5.4.6", "C", NULL, ASN1_ETYPE_PRINTABLE_STRING},
- {"2.5.4.9", "STREET", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
- {"2.5.4.12", "T", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
+ {"2.5.4.9", "street", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
+ {"2.5.4.12", "title", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.10", "O", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.11", "OU", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.3", "CN", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.65", "pseudonym", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.46", "dnQualifier", NULL, ASN1_ETYPE_PRINTABLE_STRING},
{"2.5.4.17", "postalCode", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
- {"2.5.4.41", "Name", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
+ {"2.5.4.41", "name", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"2.5.4.15", "businessCategory", "PKIX1.DirectoryString", ASN1_ETYPE_INVALID},
{"0.9.2342.19200300.100.1.25", "DC", NULL, ASN1_ETYPE_IA5_STRING},
while (_oid2str[i].oid != NULL);
return NULL;
+}
+
+const char* _gnutls_ldap_string_to_oid (const char* str, unsigned str_len)
+{
+ unsigned int i = 0;
+
+ do
+ {
+ if ((_oid2str[i].ldap_desc != NULL) &&
+ (str_len == strlen(_oid2str[i].ldap_desc)) &&
+ (strncasecmp (_oid2str[i].ldap_desc, str, str_len) == 0))
+ return _oid2str[i].oid;
+ i++;
+ }
+ while (_oid2str[i].oid != NULL);
+ return NULL;
}
+
/**
* gnutls_x509_dn_oid_known:
* @oid: holds an Object Identifier in a null terminated string
int _gnutls_x509_dn_to_string (const char *OID, void *value,
int value_size, gnutls_datum_t* out);
+const char* _gnutls_ldap_string_to_oid (const char* str, unsigned str_len);
+
int _gnutls_x509_data2hex (const void * data, size_t data_size,
void * out, size_t * sizeof_out);
--- /dev/null
+/*
+ * Copyright (C) 2013 Nikos Mavrogiannopoulos
+ * Copyright (C) 2005 Andrew Suffield <asuffield@debian.org>
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* This file contains functions to handle X.509 certificate generation.
+ */
+
+#include <gnutls_int.h>
+
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+
+enum { CRQ, CRT };
+
+static
+int dn_attr_crt_set( unsigned crt_type, void* crt, const char *attr, unsigned attr_len,
+ const char *value, unsigned value_len)
+{
+ char _oid[MAX_OID_SIZE];
+ const char *oid;
+ int ret;
+
+ if (value_len == 0 || attr_len == 0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ if (isdigit(attr[0]) != 0)
+ {
+ if (attr_len >= sizeof(_oid))
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ memcpy(_oid, attr, attr_len);
+ _oid[attr_len] = 0;
+
+ oid = _oid;
+
+ if (gnutls_x509_dn_oid_known(oid) == 0)
+ {
+ _gnutls_debug_log("Unknown OID: '%s'\n", oid);
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ }
+ }
+ else
+ {
+ oid = _gnutls_ldap_string_to_oid(attr, attr_len);
+ }
+
+ if (oid == NULL)
+ {
+ _gnutls_debug_log("Unknown DN attribute: '%.*s'\n", attr_len, attr);
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ }
+
+ if (value[0] == '#')
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ if (crt_type == CRT)
+ ret = gnutls_x509_crt_set_dn_by_oid(crt, oid, 0, value, value_len);
+ else if (crt_type == CRQ)
+ ret = gnutls_x509_crq_set_dn_by_oid(crt, oid, 0, value, value_len);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
+}
+
+static int
+crt_set_dn (unsigned crt_type, void* crt, const char *dn, const char** err)
+{
+const char *p = dn;
+const char *name_start;
+const char *name_end;
+const char *value_start;
+const char *value_end;
+unsigned name_len;
+unsigned value_len;
+int ret;
+
+ if (crt == NULL || dn == NULL)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ /* For each element */
+ while (*p != 0 && *p != '\n')
+ {
+ /* Skip leading whitespace */
+ while (isspace(*p))
+ p++;
+
+ if (err)
+ *err = p;
+
+ /* Attribute name */
+ name_start = p;
+ while (*p != '=' && *p != 0)
+ p++;
+ name_end = p;
+
+ /* Whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Equals sign */
+ if (*p != '=')
+ {
+ *err = p;
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ p++;
+
+ /* Whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Attribute value */
+ value_start = p;
+ while (*p != 0 && (*p != ',' || (*p == ',' && *(p-1) == '\\')) && *p != '\n')
+ p++;
+ value_end = p;
+ while (value_end > value_start && isspace(value_end[-1]))
+ value_end--;
+
+ /* Comma, or the end of the string */
+ if (*p)
+ p++;
+
+ name_len = name_end - name_start;
+ value_len = value_end - value_start;
+
+ ret = dn_attr_crt_set(crt_type, crt, name_start, name_len, value_start, value_len);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
+ return 0;
+}
+
+
+/**
+ * gnutls_x509_crt_set_dn:
+ * @crt: a certificate of type #gnutls_x509_crt_t
+ * @dn: a comma separated DN string (RFC4514)
+ * @err: indicates the error position (if any)
+ *
+ * This function will set the DN on the provided certificate.
+ * The input string should be plain ASCII or UTF-8 encoded.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crt_set_dn (gnutls_x509_crt_t crt, const char *dn, const char** err)
+{
+ return crt_set_dn( CRT, crt, dn, err);
+}
+
+/**
+ * gnutls_x509_crq_set_dn:
+ * @crq: a certificate of type #gnutls_x509_crq_t
+ * @dn: a comma separated DN string (RFC4514)
+ * @err: indicates the error position (if any)
+ *
+ * This function will set the DN on the provided certificate.
+ * The input string should be plain ASCII or UTF-8 encoded.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crq_set_dn (gnutls_x509_crq_t crq, const char *dn, const char** err)
+{
+ return crt_set_dn( CRQ, crq, dn, err);
+}
*
* DO NOT EDIT THIS FILE (certtool-args.c)
*
- * It has been AutoGen-ed December 15, 2012 at 11:11:26 AM by AutoGen 5.16
+ * It has been AutoGen-ed January 15, 2013 at 11:30:45 PM by AutoGen 5.16
* From the definitions certtool-args.def
* and the template file options
*
# certificates.
# pkcs9_email = "none@@none.org"
+# An alternative way to set the certificate's distinguished name directly
+# is with the "dn" option. The attribute names allowed are:
+# C (country), street, O (organization), OU (unit), title, CN (common name),
+# L (locality), ST (state), placeOfBirth, gender, countryOfCitizenship,
+# countryOfResidence, serialNumber, telephoneNumber, surName, initials,
+# generationQualifier, givenName, pseudonym, dnQualifier, postalCode, name,
+# businessCategory, DC, UID, jurisdictionOfIncorporationLocalityName,
+# jurisdictionOfIncorporationStateOrProvinceName,
+# jurisdictionOfIncorporationCountryName, XmppAddr, and numeric OIDs.
+
+#dn = "cn=Nik,st=Attiki,C=GR,surName=Mavrogiannopoulos,2.5.4.9=Arkadias"
+
# The serial number of the certificate
serial = 007
*
* DO NOT EDIT THIS FILE (certtool-args.h)
*
- * It has been AutoGen-ed December 15, 2012 at 11:11:26 AM by AutoGen 5.16
+ * It has been AutoGen-ed January 15, 2013 at 11:30:45 PM by AutoGen 5.16
* From the definitions certtool-args.def
* and the template file options
*
char *unit;
char *locality;
char *state;
+ char *dn;
char *cn;
char *uid;
char *challenge_password;
if (val != NULL && val->valType == OPARG_TYPE_STRING)
cfg.state = strdup(val->v.strVal);
+ val = optionGetValue(pov, "dn");
+ if (val != NULL && val->valType == OPARG_TYPE_STRING)
+ cfg.dn = strdup(val->v.strVal);
+
val = optionGetValue(pov, "cn");
if (val != NULL && val->valType == OPARG_TYPE_STRING)
cfg.cn = strdup(val->v.strVal);
}
+void
+get_dn_crt_set (gnutls_x509_crt_t crt)
+{
+ int ret;
+ const char* err;
+
+ if (batch)
+ {
+ if (!cfg.dn)
+ return;
+ ret =
+ gnutls_x509_crt_set_dn (crt, cfg.dn, &err);
+ if (ret < 0)
+ {
+ fprintf (stderr, "set_dn: %s at: %s\n", gnutls_strerror (ret), err);
+ exit (1);
+ }
+ }
+}
+
void
get_uid_crt_set (gnutls_x509_crt_t crt)
{
}
+void
+get_dn_crq_set (gnutls_x509_crq_t crq)
+{
+ int ret;
+ const char* err;
+
+ if (batch)
+ {
+ if (!cfg.dn)
+ return;
+ ret =
+ gnutls_x509_crq_set_dn (crq, cfg.dn, &err);
+ if (ret < 0)
+ {
+ fprintf (stderr, "set_dn: %s at: %s\n", gnutls_strerror (ret), err);
+ exit (1);
+ }
+ }
+}
+
void
get_cn_crq_set (gnutls_x509_crq_t crq)
{
void get_state_crt_set (gnutls_x509_crt_t crt);
void get_locality_crt_set (gnutls_x509_crt_t crt);
void get_cn_crt_set (gnutls_x509_crt_t crt);
+void get_dn_crt_set (gnutls_x509_crt_t crt);
+void get_dn_crq_set (gnutls_x509_crq_t crt);
void get_uid_crt_set (gnutls_x509_crt_t crt);
void get_pkcs9_email_crt_set (gnutls_x509_crt_t crt);
void get_oid_crt_set (gnutls_x509_crt_t crt);
error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
gnutls_strerror (result));
+ get_dn_crt_set (crt);
get_cn_crt_set (crt);
}
else
{
+ get_dn_crt_set (crt);
+
get_country_crt_set (crt);
+ get_state_crt_set (crt);
+ get_locality_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_dc_set (TYPE_CRT, crt);
get_uid_crt_set (crt);
+
get_oid_crt_set (crt);
get_key_purpose_set (crt);
/* Set the DN.
*/
+ get_dn_crq_set (crq);
+
get_country_crq_set (crq);
+ get_state_crq_set (crq);
+ get_locality_crq_set (crq);
get_organization_crq_set (crq);
get_unit_crq_set (crq);
- get_locality_crq_set (crq);
- get_state_crq_set (crq);
get_cn_crq_set (crq);
get_dc_set (TYPE_CRQ, crq);
get_uid_crq_set (crq);