fixes from Stefan Metzmacher
[heimdal.git] / lib / gssapi / mech / gss_import_name.c
blob040e2284105b95c2046decf4a204a7defd96097d
1 /*-
2 * Copyright (c) 2005 Doug Rabson
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $FreeBSD: src/lib/libgssapi/gss_import_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
29 #include "mech_locl.h"
30 RCSID("$Id$");
32 static OM_uint32
33 _gss_import_export_name(OM_uint32 *minor_status,
34 const gss_buffer_t input_name_buffer,
35 gss_name_t *output_name)
37 OM_uint32 major_status;
38 unsigned char *p = input_name_buffer->value;
39 size_t len = input_name_buffer->length;
40 size_t t;
41 gss_OID_desc mech_oid;
42 gssapi_mech_interface m;
43 struct _gss_name *name;
44 gss_name_t new_canonical_name;
46 *minor_status = 0;
47 *output_name = 0;
50 * Make sure that TOK_ID is {4, 1}.
52 if (len < 2)
53 return (GSS_S_BAD_NAME);
54 if (p[0] != 4 || p[1] != 1)
55 return (GSS_S_BAD_NAME);
56 p += 2;
57 len -= 2;
60 * Get the mech length and the name length and sanity
61 * check the size of of the buffer.
63 if (len < 2)
64 return (GSS_S_BAD_NAME);
65 t = (p[0] << 8) + p[1];
66 p += 2;
67 len -= 2;
70 * Check the DER encoded OID to make sure it agrees with the
71 * length we just decoded.
73 if (p[0] != 6) /* 6=OID */
74 return (GSS_S_BAD_NAME);
75 p++;
76 len--;
77 t--;
78 if (p[0] & 0x80) {
79 int digits = p[0];
80 p++;
81 len--;
82 t--;
83 mech_oid.length = 0;
84 while (digits--) {
85 mech_oid.length = (mech_oid.length << 8) | p[0];
86 p++;
87 len--;
88 t--;
90 } else {
91 mech_oid.length = p[0];
92 p++;
93 len--;
94 t--;
96 if (mech_oid.length != t)
97 return (GSS_S_BAD_NAME);
99 mech_oid.elements = p;
101 if (len < t + 4)
102 return (GSS_S_BAD_NAME);
103 p += t;
104 len -= t;
106 t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
107 p += 4;
108 len -= 4;
110 if (len != t)
111 return (GSS_S_BAD_NAME);
113 m = __gss_get_mechanism(&mech_oid);
114 if (!m)
115 return (GSS_S_BAD_MECH);
118 * Ask the mechanism to import the name.
120 major_status = m->gm_import_name(minor_status,
121 input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name);
122 if (major_status != GSS_S_COMPLETE) {
123 _gss_mg_error(m, major_status, *minor_status);
124 return major_status;
128 * Now we make a new name and mark it as an MN.
130 name = _gss_make_name(m, new_canonical_name);
131 if (!name) {
132 m->gm_release_name(minor_status, &new_canonical_name);
133 return (GSS_S_FAILURE);
136 *output_name = (gss_name_t) name;
138 *minor_status = 0;
139 return (GSS_S_COMPLETE);
142 OM_uint32 GSSAPI_LIB_FUNCTION
143 gss_import_name(OM_uint32 *minor_status,
144 const gss_buffer_t input_name_buffer,
145 const gss_OID input_name_type,
146 gss_name_t *output_name)
148 gss_OID name_type = input_name_type;
149 OM_uint32 major_status;
150 struct _gss_name *name;
152 *output_name = GSS_C_NO_NAME;
154 if (input_name_buffer->length == 0) {
155 *minor_status = 0;
156 return (GSS_S_BAD_NAME);
160 * Use GSS_NT_USER_NAME as default name type.
162 if (name_type == GSS_C_NO_OID)
163 name_type = GSS_C_NT_USER_NAME;
166 * If this is an exported name, we need to parse it to find
167 * the mechanism and then import it as an MN. See RFC 2743
168 * section 3.2 for a description of the format.
170 if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
171 return _gss_import_export_name(minor_status,
172 input_name_buffer, output_name);
176 * Only allow certain name types. This is pretty bogus - we
177 * should figure out the list of supported name types using
178 * gss_inquire_names_for_mech.
180 if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME)
181 && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)
182 && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME)
183 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X)
184 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)
185 && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)
186 && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) {
187 *minor_status = 0;
188 return (GSS_S_BAD_NAMETYPE);
191 *minor_status = 0;
192 name = malloc(sizeof(struct _gss_name));
193 if (!name) {
194 *minor_status = ENOMEM;
195 return (GSS_S_FAILURE);
197 memset(name, 0, sizeof(struct _gss_name));
199 major_status = _gss_copy_oid(minor_status,
200 name_type, &name->gn_type);
201 if (major_status) {
202 free(name);
203 return (GSS_S_FAILURE);
206 major_status = _gss_copy_buffer(minor_status,
207 input_name_buffer, &name->gn_value);
208 if (major_status) {
209 gss_name_t rname = (gss_name_t)name;
210 gss_release_name(minor_status, &rname);
211 return (GSS_S_FAILURE);
214 SLIST_INIT(&name->gn_mn);
216 *output_name = (gss_name_t) name;
217 return (GSS_S_COMPLETE);