db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/*
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SSSD - certificate handling utils - NSS version
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose The calls defined here should be useable outside of SSSD as well, e.g. in
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose libsss_certmap.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose Copyright (C) Sumit Bose <sbose@redhat.com> 2017
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose This program is free software; you can redistribute it and/or modify
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose it under the terms of the GNU General Public License as published by
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose the Free Software Foundation; either version 3 of the License, or
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (at your option) any later version.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose This program is distributed in the hope that it will be useful,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose GNU General Public License for more details.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose You should have received a copy of the GNU General Public License
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose*/
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "config.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <nss.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <cert.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <base64.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <prerror.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <secport.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <secerr.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <prprf.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <prnetdb.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <talloc.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "util/crypto/sss_crypto.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "util/crypto/nss/nss_util.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "util/cert.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "lib/certmap/sss_certmap.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "lib/certmap/sss_certmap_int.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* The following two functions are copied from NSS's lib/certdb/secname.c
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz * because CERT_AddAVA is not exported. I just renamed it and made it static
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * to avoid issues if the call gets exported some time in future. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void **
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit BoseAddToArray(PLArenaPool *arena, void **array, void *element)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose unsigned count;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose void **ap;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* Count up number of slots already in use in the array */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose count = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ap = array;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ap) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose while (*ap++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose count++;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (array) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose array = (void**) PORT_ArenaGrow(arena, array,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (count + 1) * sizeof(void *),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (count + 2) * sizeof(void *));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (array) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose array[count] = element;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose array[count+1] = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return array;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic SECStatus
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosesss_CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return rdn->avas ? SECSuccess : SECFailure;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic SECItem *
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosecert_get_ext_by_tag(CERTCertificate *cert, SECOidTag tag)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECOidData *oid;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose oid = SECOID_FindOIDByTag(tag);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (i = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (cert->extensions != NULL) && (cert->extensions[i] != NULL);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i++)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (SECITEM_ItemsAreEqual(&cert->extensions[i]->id, &oid->oid))
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return &cert->extensions[i]->value;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int get_extended_key_usage_oids(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTCertificate *cert,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char ***_oids)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PLArenaPool *pool;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem *ext;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem **oids = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **oids_list = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECStatus rv;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *tmp_str;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool = PORT_NewArena(sizeof(double));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ext = cert_get_ext_by_tag(cert, SEC_OID_X509_EXT_KEY_USAGE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ext != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rv = SEC_ASN1DecodeItem(pool, &oids,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ext);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv != SECSuccess) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; (oids != NULL && oids[c] != NULL); c++);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose oids_list = talloc_zero_array(mem_ctx, const char *, c + 1);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (oids_list == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; (oids != NULL && oids[c] != NULL); c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_str = CERT_GetOidString(oids[c]);
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz /* it is expected that NSS OID strings start with "OID." but we
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * prefer the plain dotted-decimal version so the prefix is skipped */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose oids_list[c] = talloc_strdup(oids_list, tmp_str + 4);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if(oids_list[c] == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PORT_FreeArena(pool, PR_TRUE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *_oids = oids_list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(oids_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int get_rdn_str(TALLOC_CTX *mem_ctx, CERTAVA **avas,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **rdn_str)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *tmp_name = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char *tmp_str = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECStatus rv;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTRDN rdn = { 0 };
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTName *name = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PLArenaPool *arena = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (arena == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz /* Multiple AVAs should be avoided because there is no general ordering
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * rule and the RDN strings are not reproducible */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; avas[c] != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rv = sss_CERT_AddAVA(arena, &rdn, avas[c]);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv != SECSuccess) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose name = CERT_CreateName(&rdn, NULL);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (name == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_name = CERT_NameToAscii(name);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERT_DestroyName(name);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (tmp_name == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_str = talloc_strdup(mem_ctx, tmp_name);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PORT_Free(tmp_name);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (tmp_str == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *rdn_str = tmp_str;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(discard_const(tmp_str));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PORT_FreeArena(arena, PR_FALSE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int get_rdn_list(TALLOC_CTX *mem_ctx, CERTRDN **rdns,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char ***rdn_list)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const char **list = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; rdns[c] != NULL; c++);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose list = talloc_zero_array(mem_ctx, const char *, c + 1);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (list == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; rdns[c] != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_rdn_str(list, rdns[c]->avas,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &(list[c]));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *rdn_list = list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Boseenum san_opt nss_name_type_to_san_opt(CERTGeneralNameType type)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose switch (type) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certOtherName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_OTHER_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certRFC822Name:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_RFC822_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certDNSName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_DNS_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certX400Address:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_X400_ADDRESS;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certDirectoryName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_DIRECTORY_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certEDIPartyName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_EDIPART_NAME;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certURI:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_URI;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certIPAddress:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_IP_ADDRESS;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certRegisterID:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_REGISTERED_ID;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose default:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return SAN_INVALID;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* taken from pkinit_crypto_nss.c of MIT Kerberos */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* KerberosString: RFC 4120, 5.2.1. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const SEC_ASN1Template kerberos_string_template[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_GENERAL_STRING,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NULL,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(SECItem),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* Realm: RFC 4120, 5.2.2. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestruct realm {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem name;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const SEC_ASN1Template realm_template[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_GENERAL_STRING,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NULL,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(SECItem),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* PrincipalName: RFC 4120, 5.2.2. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const SEC_ASN1Template sequence_of_kerberos_string_template[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_SEQUENCE_OF,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &kerberos_string_template,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestruct principal_name {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem name_type;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem **name_string;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const SEC_ASN1Template principal_name_template[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_SEQUENCE,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NULL,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(struct principal_name),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose offsetof(struct principal_name, name_type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &SEC_IntegerTemplate,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(SECItem),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose offsetof(struct principal_name, name_string),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sequence_of_kerberos_string_template,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(struct SECItem **),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {0, 0, NULL, 0},
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* KRB5PrincipalName: RFC 4556, 3.2.2. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestruct kerberos_principal_name {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem realm;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct principal_name principal_name;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const SEC_ASN1Template kerberos_principal_name_template[] = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_SEQUENCE,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NULL,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(struct kerberos_principal_name),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose offsetof(struct kerberos_principal_name, realm),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &realm_template,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(struct realm),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose offsetof(struct kerberos_principal_name, principal_name),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &principal_name_template,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose sizeof(struct principal_name),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose },
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {0, 0, NULL, 0}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_string_other_name_to_san_list(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTGeneralName *current,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *tmp_str;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_str = CERT_GetOidString(&(current->name.OthName.oid));
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz /* it is expected that NSS OID strings start with "OID." but we
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * prefer the plain dotted-decimal version so the prefix is skipped */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->other_name_oid = talloc_strdup(i, tmp_str + 4);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->other_name_oid == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->bin_val = talloc_memdup(i, current->name.OthName.name.data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.OthName.name.len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->bin_val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->bin_val_len = current->name.OthName.name.len;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_nt_princ_to_san_list(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PLArenaPool *pool,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTGeneralName *current,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECStatus rv;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem tmp_secitem = { 0 };
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rv = SEC_ASN1DecodeItem(pool, &tmp_secitem,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SEC_ASN1_GET(SEC_UTF8StringTemplate),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &(current->name.OthName.name));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv != SECSuccess) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strndup(i, (char *) tmp_secitem.data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_secitem.len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_short_name(i, i->val, '@', &(i->short_name));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_pkinit_princ_to_san_list(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PLArenaPool *pool,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTGeneralName *current,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECStatus rv;
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik /* To avoid 'Wmissing-braces' warnings with older versions of
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik * gcc kerberos_principal_name cannot be initialized with { 0 }
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik * but must be initialized with memset().
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik */
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik struct kerberos_principal_name kname;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t c;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik memset(&kname, 0, sizeof(kname));
22abbb479e00438ec4ab19735824cc6e79dd9aafLukas Slebodnik
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rv = SEC_ASN1DecodeItem(pool, &kname,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose kerberos_principal_name_template,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &(current->name.OthName.name));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv != SECSuccess) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (kname.principal_name.name_string != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strdup(i, "");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose for (c = 0; kname.principal_name.name_string[c] != NULL; c++) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (c > 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strdup_append(i->val, "/");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strndup_append(i->val,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (char *) kname.principal_name.name_string[c]->data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose kname.principal_name.name_string[c]->len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
a20fb9cbd5f42a6ca895aea1b84347fdfea34b89Sumit Bose i->val = talloc_asprintf_append(i->val, "@%.*s",
a20fb9cbd5f42a6ca895aea1b84347fdfea34b89Sumit Bose kname.realm.len,
a20fb9cbd5f42a6ca895aea1b84347fdfea34b89Sumit Bose (char *) kname.realm.data);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_short_name(i, i->val, '@', &(i->short_name));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_oid_to_san_list(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem oid,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char *tmp_str;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose tmp_str = CERT_GetOidString(&oid);
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz /* it is expected that NSS OID strings start with "OID." but we
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose * prefer the plain dotted-decimal version so the prefix is skipped */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strdup(i, tmp_str + 4);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PR_smprintf_free(tmp_str);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_rdn_list_to_san_list(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTName name,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_rdn_list(i, name.rdns, &(i->rdn_list));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int add_ip_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose uint8_t *data, size_t len,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **item)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PRStatus st;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PRNetAddr addr;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose char addrBuf[80];
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (data == NULL || len == 0 || san_opt == SAN_INVALID) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* taken from secu_PrintIPAddress() */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memset(&addr, 0, sizeof addr);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (len == 4) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose addr.inet.family = PR_AF_INET;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memcpy(&addr.inet.ip, data, len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (len == 16) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose addr.ipv6.family = PR_AF_INET6;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memcpy(addr.ipv6.ip.pr_s6_addr, data, len);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* convert to IPv4. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose addr.inet.family = PR_AF_INET;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (st != PR_SUCCESS) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i = talloc_zero(mem_ctx, struct san_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->san_opt = san_opt;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i->val = talloc_strdup(i, addrBuf);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (i->val == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(i);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *item = i;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic int get_san(TALLOC_CTX *mem_ctx, CERTCertificate *cert,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list **san_list)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem subAltName = { 0 };
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECStatus rv;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTGeneralName *name_list = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTGeneralName *current;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PLArenaPool *pool = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *list = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *item = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *item_s = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *item_p = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct san_list *item_pb = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &subAltName);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv != SECSuccess) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (rv == SECFailure
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose && PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EOK;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (pool == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose name_list = CERT_DecodeAltNameExtension(pool, &subAltName);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (name_list == NULL ) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current = name_list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose do {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose switch (current->type) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certOtherName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_string_other_name_to_san_list(mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SAN_STRING_OTHER_NAME,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current, &item_s);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item_s);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose item_p = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (strcmp(item_s->other_name_oid, NT_PRINCIPAL_OID) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_nt_princ_to_san_list(mem_ctx, pool, SAN_NT, current,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &item_p);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item_p);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else if (strcmp(item_s->other_name_oid, PKINIT_OID) == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_pkinit_princ_to_san_list(mem_ctx, pool, SAN_PKINIT,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current, &item_p);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item_p);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (item_p != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_principal_to_san_list(mem_ctx, SAN_PRINCIPAL,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose item_p->val, &item_pb);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item_pb);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certRFC822Name:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certDNSName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certURI:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_to_san_list(mem_ctx, false,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_name_type_to_san_opt(current->type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.len, &item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (current->type == certRFC822Name
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose || current->type == certDNSName) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_short_name(item, item->val,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (current->type == certRFC822Name
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ? '@' : '.'),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &(item->short_name));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certIPAddress:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_ip_to_san_list(mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_name_type_to_san_opt(current->type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.len, &item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certDirectoryName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_rdn_list_to_san_list(mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_name_type_to_san_opt(current->type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.directoryName, &item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certRegisterID:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_oid_to_san_list(mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_name_type_to_san_opt(current->type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other, &item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certX400Address:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose case certEDIPartyName:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = add_to_san_list(mem_ctx, true,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_name_type_to_san_opt(current->type),
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.data,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current->name.other.len, &item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose DLIST_ADD(list, item);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose break;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose default:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
a20fb9cbd5f42a6ca895aea1b84347fdfea34b89Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose current = CERT_GetNextGeneralName(current);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (current == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } while (current != name_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* Don't free nameList, it's part of the arena. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (pool != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose PORT_FreeArena(pool, PR_FALSE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (subAltName.data != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECITEM_FreeItem(&subAltName, PR_FALSE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == EOK) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *san_list = list;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Boseint sss_cert_get_content(TALLOC_CTX *mem_ctx,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose const uint8_t *der_blob, size_t der_size,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_cert_content **content)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose int ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose struct sss_cert_content *cont = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTCertDBHandle *handle;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERTCertificate *cert = NULL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose SECItem der_item;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NSSInitContext *nss_ctx;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (der_blob == NULL || der_size == 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose nss_ctx = NSS_InitContext("", "", "", "", NULL, NSS_INIT_READONLY
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose | NSS_INIT_NOCERTDB
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose | NSS_INIT_NOMODDB
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose | NSS_INIT_FORCEOPEN
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose | NSS_INIT_NOROOTINIT
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose | NSS_INIT_OPTIMIZESPACE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (nss_ctx == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return EIO;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont = talloc_zero(mem_ctx, struct sss_cert_content);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (cont == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose handle = CERT_GetDefaultCertDB();
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose der_item.len = der_size;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose der_item.data = discard_const(der_blob);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (cert == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EINVAL;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont->issuer_str = talloc_strdup(cont, cert->issuerName);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (cont->issuer_str == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_rdn_list(cont, cert->issuer.rdns, &cont->issuer_rdn_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont->subject_str = talloc_strdup(cont, cert->subjectName);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (cont->subject_str == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_rdn_list(cont, cert->subject.rdns, &cont->subject_rdn_list);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont->key_usage = cert->keyUsage;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_extended_key_usage_oids(cont, cert,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose &(cont->extended_key_usage_oids));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = get_san(cont, cert, &(cont->san_list));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret != 0) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont->cert_der = talloc_memdup(cont, der_blob, der_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (cont->cert_der == NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = ENOMEM;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose goto done;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose cont->cert_der_size = der_size;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose ret = EOK;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosedone:
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose CERT_DestroyCertificate(cert);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose NSS_ShutdownContext(nss_ctx);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (ret == EOK) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *content = cont;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose } else {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose talloc_free(cont);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return ret;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}