gss_import_name.c revision 178828
1169695Skan/*-
2169695Skan * Copyright (c) 2005 Doug Rabson
3169695Skan * All rights reserved.
4169695Skan *
5169695Skan * Redistribution and use in source and binary forms, with or without
6169695Skan * modification, are permitted provided that the following conditions
7169695Skan * are met:
8169695Skan * 1. Redistributions of source code must retain the above copyright
9169695Skan *    notice, this list of conditions and the following disclaimer.
10169695Skan * 2. Redistributions in binary form must reproduce the above copyright
11169695Skan *    notice, this list of conditions and the following disclaimer in the
12169695Skan *    documentation and/or other materials provided with the distribution.
13169695Skan *
14169695Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17169695Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24169695Skan * SUCH DAMAGE.
25169695Skan *
26169695Skan *	$FreeBSD: head/lib/libgssapi/gss_import_name.c 178828 2008-05-07 13:53:12Z dfr $
27169695Skan */
28169695Skan
29169695Skan#include <gssapi/gssapi.h>
30169695Skan#include <stdlib.h>
31169695Skan#include <string.h>
32169695Skan#include <errno.h>
33169695Skan
34169695Skan#include "mech_switch.h"
35169695Skan#include "utils.h"
36169695Skan#include "name.h"
37169695Skan
38169695Skanstatic OM_uint32
39169695Skan_gss_import_export_name(OM_uint32 *minor_status,
40169695Skan    const gss_buffer_t input_name_buffer,
41169695Skan    gss_name_t *output_name)
42169695Skan{
43169695Skan	OM_uint32 major_status;
44169695Skan	unsigned char *p = input_name_buffer->value;
45169695Skan	size_t len = input_name_buffer->length;
46169695Skan	size_t t;
47169695Skan	gss_OID_desc mech_oid;
48169695Skan	struct _gss_mech_switch *m;
49169695Skan	struct _gss_name *name;
50169695Skan	gss_name_t new_canonical_name;
51169695Skan
52169695Skan	*minor_status = 0;
53169695Skan	*output_name = 0;
54169695Skan
55169695Skan	/*
56169695Skan	 * Make sure that TOK_ID is {4, 1}.
57169695Skan	 */
58169695Skan	if (len < 2)
59169695Skan		return (GSS_S_BAD_NAME);
60169695Skan	if (p[0] != 4 || p[1] != 1)
61282152Spfg		return (GSS_S_BAD_NAME);
62169695Skan	p += 2;
63169695Skan	len -= 2;
64169695Skan
65282152Spfg	/*
66169695Skan	 * Get the mech length and the name length and sanity
67169695Skan	 * check the size of of the buffer.
68169695Skan	 */
69169695Skan	if (len < 2)
70169695Skan		return (GSS_S_BAD_NAME);
71169695Skan	t = (p[0] << 8) + p[1];
72169695Skan	p += 2;
73169695Skan	len -= 2;
74169695Skan
75169695Skan	/*
76169695Skan	 * Check the DER encoded OID to make sure it agrees with the
77169695Skan	 * length we just decoded.
78169695Skan	 */
79169695Skan	if (p[0] != 6)		/* 6=OID */
80169695Skan		return (GSS_S_BAD_NAME);
81169695Skan	p++;
82169695Skan	len--;
83169695Skan	t--;
84169695Skan	if (p[0] & 0x80) {
85169695Skan		int digits = p[0];
86169695Skan		p++;
87169695Skan		len--;
88169695Skan		t--;
89169695Skan		mech_oid.length = 0;
90169695Skan		while (digits--) {
91169695Skan			mech_oid.length = (mech_oid.length << 8) | p[0];
92169695Skan			p++;
93169695Skan			len--;
94169695Skan			t--;
95169695Skan		}
96169695Skan	} else {
97169695Skan		mech_oid.length = p[0];
98169695Skan		p++;
99169695Skan		len--;
100169695Skan		t--;
101169695Skan	}
102169695Skan	if (mech_oid.length != t)
103169695Skan		return (GSS_S_BAD_NAME);
104169695Skan
105169695Skan	mech_oid.elements = p;
106169695Skan
107169695Skan	if (len < t + 4)
108169695Skan		return (GSS_S_BAD_NAME);
109169695Skan	p += t;
110169695Skan	len -= t;
111169695Skan
112169695Skan	t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
113169695Skan	p += 4;
114169695Skan	len -= 4;
115169695Skan
116169695Skan	if (len != t)
117169695Skan		return (GSS_S_BAD_NAME);
118169695Skan
119169695Skan	m = _gss_find_mech_switch(&mech_oid);
120169695Skan	if (!m)
121169695Skan		return (GSS_S_BAD_MECH);
122169695Skan
123169695Skan	/*
124169695Skan	 * Ask the mechanism to import the name.
125169695Skan	 */
126169695Skan	major_status = m->gm_import_name(minor_status,
127169695Skan	    input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name);
128169695Skan	if (major_status != GSS_S_COMPLETE) {
129169695Skan		_gss_mg_error(m, major_status, *minor_status);
130169695Skan		return (major_status);
131169695Skan	}
132282152Spfg
133169695Skan	/*
134169695Skan	 * Now we make a new name and mark it as an MN.
135169695Skan	 */
136169695Skan	name = _gss_make_name(m, new_canonical_name);
137169695Skan	if (!name) {
138169695Skan		m->gm_release_name(minor_status, &new_canonical_name);
139169695Skan		return (GSS_S_FAILURE);
140169695Skan	}
141169695Skan
142169695Skan	*output_name = (gss_name_t) name;
143169695Skan
144169695Skan	*minor_status = 0;
145169695Skan	return (GSS_S_COMPLETE);
146169695Skan}
147169695Skan
148169695SkanOM_uint32
149169695Skangss_import_name(OM_uint32 *minor_status,
150169695Skan    const gss_buffer_t input_name_buffer,
151169695Skan    const gss_OID input_name_type,
152169695Skan    gss_name_t *output_name)
153169695Skan{
154169695Skan	gss_OID			name_type = input_name_type;
155169695Skan	OM_uint32		major_status;
156169695Skan	struct _gss_name	*name;
157282201Spfg
158169695Skan	*output_name = GSS_C_NO_NAME;
159169695Skan
160169695Skan	if (input_name_buffer->length == 0) {
161169695Skan		*minor_status = 0;
162169695Skan		return (GSS_S_BAD_NAME);
163169695Skan	}
164169695Skan
165169695Skan	/*
166169695Skan	 * Use GSS_NT_USER_NAME as default name type.
167169695Skan	 */
168169695Skan	if (name_type == GSS_C_NO_OID)
169169695Skan		name_type = GSS_C_NT_USER_NAME;
170169695Skan
171169695Skan	/*
172169695Skan	 * If this is an exported name, we need to parse it to find
173169695Skan	 * the mechanism and then import it as an MN. See RFC 2743
174169695Skan	 * section 3.2 for a description of the format.
175169695Skan	 */
176169695Skan	if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
177169695Skan		return _gss_import_export_name(minor_status,
178169695Skan		    input_name_buffer, output_name);
179169695Skan	}
180169695Skan
181169695Skan	/*
182169695Skan	 * Only allow certain name types. This is pretty bogus - we
183169695Skan	 * should figure out the list of supported name types using
184169695Skan	 * gss_inquire_names_for_mech.
185169695Skan	 */
186169695Skan	if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME)
187169695Skan	    && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)
188169695Skan	    && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME)
189169695Skan	    && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X)
190169695Skan	    && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)
191169695Skan	    && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)
192282152Spfg	    && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) {
193282152Spfg		*minor_status = 0;
194282115Spfg		return (GSS_S_BAD_NAMETYPE);
195282115Spfg	}
196282115Spfg
197282115Spfg	*minor_status = 0;
198282115Spfg	name = malloc(sizeof(struct _gss_name));
199282115Spfg	if (!name) {
200282115Spfg		*minor_status = ENOMEM;
201282115Spfg		return (GSS_S_FAILURE);
202282115Spfg	}
203282115Spfg	memset(name, 0, sizeof(struct _gss_name));
204282115Spfg
205282115Spfg	major_status = _gss_copy_oid(minor_status,
206282115Spfg	    name_type, &name->gn_type);
207282115Spfg	if (major_status) {
208282115Spfg		free(name);
209282115Spfg		return (GSS_S_FAILURE);
210282115Spfg	}
211282115Spfg
212282115Spfg	major_status = _gss_copy_buffer(minor_status,
213169695Skan	    input_name_buffer, &name->gn_value);
214169695Skan	if (major_status) {
215169695Skan		gss_name_t rname = (gss_name_t)name;
216169695Skan		gss_release_name(minor_status, &rname);
217169695Skan		return (GSS_S_FAILURE);
218169695Skan	}
219169695Skan
220169695Skan	SLIST_INIT(&name->gn_mn);
221169695Skan
222169695Skan	*output_name = (gss_name_t) name;
223169695Skan	return (GSS_S_COMPLETE);
224169695Skan}
225169695Skan