Blame lib/x509/virt-san.c

Packit 549fdc
/*
Packit 549fdc
 * Copyright (C) 2015-2016 Nikos Mavrogiannopoulos
Packit 549fdc
 * Copyright (C) 2015-2016 Red Hat, Inc.
Packit 549fdc
 *
Packit 549fdc
 * This file is part of GnuTLS.
Packit 549fdc
 *
Packit 549fdc
 * The GnuTLS is free software; you can redistribute it and/or
Packit 549fdc
 * modify it under the terms of the GNU Lesser General Public License
Packit 549fdc
 * as published by the Free Software Foundation; either version 2.1 of
Packit 549fdc
 * the License, or (at your option) any later version.
Packit 549fdc
 *
Packit 549fdc
 * This library is distributed in the hope that it will be useful, but
Packit 549fdc
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 549fdc
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 549fdc
 * Lesser General Public License for more details.
Packit 549fdc
 *
Packit 549fdc
 * You should have received a copy of the GNU Lesser General Public License
Packit 549fdc
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
Packit 549fdc
 *
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
/* This file contains functions to handle the virtual subject alternative names,
Packit 549fdc
 * based on othernames, such as GNUTLS_SAN_OTHERNAME_XMPP.
Packit 549fdc
 */
Packit 549fdc
Packit 549fdc
#include "gnutls_int.h"
Packit 549fdc
#include "x509_int.h"
Packit 549fdc
#include "x509_ext_int.h"
Packit 549fdc
#include "common.h"
Packit 549fdc
#include "krb5.h"
Packit 549fdc
#include "virt-san.h"
Packit 549fdc
Packit 549fdc
static
Packit 549fdc
int san_othername_to_virtual(const char *oid, size_t size)
Packit 549fdc
{
Packit 549fdc
	if (oid) {
Packit 549fdc
		if ((unsigned) size == (sizeof(XMPP_OID)-1)
Packit 549fdc
		    && memcmp(oid, XMPP_OID, sizeof(XMPP_OID)-1) == 0)
Packit 549fdc
			return GNUTLS_SAN_OTHERNAME_XMPP;
Packit 549fdc
		else if ((unsigned) size == (sizeof(KRB5_PRINCIPAL_OID)-1)
Packit 549fdc
		    && memcmp(oid, KRB5_PRINCIPAL_OID, sizeof(KRB5_PRINCIPAL_OID)-1) == 0)
Packit 549fdc
			return GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL;
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return GNUTLS_SAN_OTHERNAME;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
static
Packit 549fdc
const char * virtual_to_othername_oid(unsigned type)
Packit 549fdc
{
Packit 549fdc
	switch(type) {
Packit 549fdc
		case GNUTLS_SAN_OTHERNAME_XMPP:
Packit 549fdc
			return XMPP_OID;
Packit 549fdc
		case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
Packit 549fdc
			return KRB5_PRINCIPAL_OID;
Packit 549fdc
		default:
Packit 549fdc
			return NULL;
Packit 549fdc
	}
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int _gnutls_alt_name_assign_virt_type(struct name_st *name, unsigned type, gnutls_datum_t *san, const char *othername_oid, unsigned raw)
Packit 549fdc
{
Packit 549fdc
	gnutls_datum_t encoded = {NULL, 0};
Packit 549fdc
	gnutls_datum_t xmpp = {NULL,0};
Packit 549fdc
	int ret;
Packit 549fdc
Packit 549fdc
	if (type < 1000) {
Packit 549fdc
		name->type = type;
Packit 549fdc
		ret = _gnutls_alt_name_process(&name->san, type, san, raw);
Packit 549fdc
		if (ret < 0)
Packit 549fdc
			return gnutls_assert_val(ret);
Packit 549fdc
		gnutls_free(san->data);
Packit 549fdc
		san->data = NULL;
Packit 549fdc
Packit 549fdc
		if (othername_oid) {
Packit 549fdc
			name->othername_oid.data = (uint8_t *) othername_oid;
Packit 549fdc
			name->othername_oid.size = strlen(othername_oid);
Packit 549fdc
		} else {
Packit 549fdc
			name->othername_oid.data = NULL;
Packit 549fdc
			name->othername_oid.size = 0;
Packit 549fdc
		}
Packit 549fdc
	} else { /* virtual types */
Packit 549fdc
		const char *oid = virtual_to_othername_oid(type);
Packit 549fdc
Packit 549fdc
		if (oid == NULL)
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
Packit 549fdc
		switch(type) {
Packit 549fdc
			case GNUTLS_SAN_OTHERNAME_XMPP:
Packit 549fdc
Packit 549fdc
				ret = gnutls_idna_map((char*)san->data, san->size, &xmpp, 0);
Packit 549fdc
				if (ret < 0)
Packit 549fdc
					return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
				ret = _gnutls_x509_encode_string(ASN1_ETYPE_UTF8_STRING,
Packit 549fdc
					xmpp.data, xmpp.size, &encoded);
Packit 549fdc
Packit 549fdc
				gnutls_free(xmpp.data);
Packit 549fdc
				if (ret < 0)
Packit 549fdc
					return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
				name->type = GNUTLS_SAN_OTHERNAME;
Packit 549fdc
				name->san.data = encoded.data;
Packit 549fdc
				name->san.size = encoded.size;
Packit 549fdc
				name->othername_oid.data = (void*)gnutls_strdup(oid);
Packit 549fdc
				name->othername_oid.size = strlen(oid);
Packit 549fdc
				break;
Packit 549fdc
Packit 549fdc
			case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
Packit 549fdc
				ret = _gnutls_krb5_principal_to_der((char*)san->data, &name->san);
Packit 549fdc
				if (ret < 0)
Packit 549fdc
					return gnutls_assert_val(ret);
Packit 549fdc
Packit 549fdc
				name->othername_oid.data = (void*)gnutls_strdup(oid);
Packit 549fdc
				name->othername_oid.size = strlen(oid);
Packit 549fdc
				name->type = GNUTLS_SAN_OTHERNAME;
Packit 549fdc
				break;
Packit 549fdc
Packit 549fdc
			default:
Packit 549fdc
				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit 549fdc
		}
Packit 549fdc
Packit 549fdc
		gnutls_free(san->data);
Packit 549fdc
	}
Packit 549fdc
Packit 549fdc
	return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/**
Packit 549fdc
 * gnutls_x509_othername_to_virtual:
Packit 549fdc
 * @oid: The othername object identifier
Packit 549fdc
 * @othername: The othername data
Packit 549fdc
 * @virt_type: GNUTLS_SAN_OTHERNAME_XXX
Packit 549fdc
 * @virt: allocated printable data
Packit 549fdc
 *
Packit 549fdc
 * This function will parse and convert the othername data to a virtual
Packit 549fdc
 * type supported by gnutls.
Packit 549fdc
 *
Packit 549fdc
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
Packit 549fdc
 *
Packit 549fdc
 * Since: 3.3.8
Packit 549fdc
 **/
Packit 549fdc
int gnutls_x509_othername_to_virtual(const char *oid, 
Packit 549fdc
				     const gnutls_datum_t *othername,
Packit 549fdc
				     unsigned int *virt_type,
Packit 549fdc
				     gnutls_datum_t *virt)
Packit 549fdc
{
Packit 549fdc
	int ret;
Packit 549fdc
	unsigned type;
Packit 549fdc
Packit 549fdc
	type = san_othername_to_virtual(oid, strlen(oid));
Packit 549fdc
	if (type == GNUTLS_SAN_OTHERNAME)
Packit 549fdc
		return gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
Packit 549fdc
Packit 549fdc
	if (virt_type)
Packit 549fdc
		*virt_type = type;
Packit 549fdc
Packit 549fdc
	switch(type) {
Packit 549fdc
		case GNUTLS_SAN_OTHERNAME_XMPP:
Packit 549fdc
			ret = _gnutls_x509_decode_string
Packit 549fdc
				    (ASN1_ETYPE_UTF8_STRING, othername->data,
Packit 549fdc
				     othername->size, virt, 0);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return ret;
Packit 549fdc
			}
Packit 549fdc
			return 0;
Packit 549fdc
		case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
Packit 549fdc
			ret = _gnutls_krb5_der_to_principal(othername, virt);
Packit 549fdc
			if (ret < 0) {
Packit 549fdc
				gnutls_assert();
Packit 549fdc
				return ret;
Packit 549fdc
			}
Packit 549fdc
			return 0;
Packit 549fdc
		default:
Packit 549fdc
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit 549fdc
	}
Packit 549fdc
}