s4:heimdal: import lorikeet-heimdal-201003262338 (commit f4e0dc17709829235f057e0e100d...
[Samba/gebeck_regimport.git] / source4 / heimdal / lib / gssapi / mech / gss_import_name.c
blob6ae2302abd90e1b4bef46094316cc7a9f8cd52b0
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"
31 static OM_uint32
32 _gss_import_export_name(OM_uint32 *minor_status,
33 const gss_buffer_t input_name_buffer,
34 gss_name_t *output_name)
36 OM_uint32 major_status;
37 unsigned char *p = input_name_buffer->value;
38 size_t len = input_name_buffer->length;
39 size_t t;
40 gss_OID_desc mech_oid;
41 gssapi_mech_interface m;
42 struct _gss_name *name;
43 gss_name_t new_canonical_name;
45 *minor_status = 0;
46 *output_name = 0;
49 * Make sure that TOK_ID is {4, 1}.
51 if (len < 2)
52 return (GSS_S_BAD_NAME);
53 if (p[0] != 4 || p[1] != 1)
54 return (GSS_S_BAD_NAME);
55 p += 2;
56 len -= 2;
59 * Get the mech length and the name length and sanity
60 * check the size of of the buffer.
62 if (len < 2)
63 return (GSS_S_BAD_NAME);
64 t = (p[0] << 8) + p[1];
65 p += 2;
66 len -= 2;
69 * Check the DER encoded OID to make sure it agrees with the
70 * length we just decoded.
72 if (p[0] != 6) /* 6=OID */
73 return (GSS_S_BAD_NAME);
74 p++;
75 len--;
76 t--;
77 if (p[0] & 0x80) {
78 int digits = p[0];
79 p++;
80 len--;
81 t--;
82 mech_oid.length = 0;
83 while (digits--) {
84 mech_oid.length = (mech_oid.length << 8) | p[0];
85 p++;
86 len--;
87 t--;
89 } else {
90 mech_oid.length = p[0];
91 p++;
92 len--;
93 t--;
95 if (mech_oid.length != t)
96 return (GSS_S_BAD_NAME);
98 mech_oid.elements = p;
100 if (len < t + 4)
101 return (GSS_S_BAD_NAME);
102 p += t;
103 len -= t;
105 t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
106 p += 4;
107 len -= 4;
109 if (len != t)
110 return (GSS_S_BAD_NAME);
112 m = __gss_get_mechanism(&mech_oid);
113 if (!m)
114 return (GSS_S_BAD_MECH);
117 * Ask the mechanism to import the name.
119 major_status = m->gm_import_name(minor_status,
120 input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name);
121 if (major_status != GSS_S_COMPLETE) {
122 _gss_mg_error(m, major_status, *minor_status);
123 return major_status;
127 * Now we make a new name and mark it as an MN.
129 name = _gss_make_name(m, new_canonical_name);
130 if (!name) {
131 m->gm_release_name(minor_status, &new_canonical_name);
132 return (GSS_S_FAILURE);
135 *output_name = (gss_name_t) name;
137 *minor_status = 0;
138 return (GSS_S_COMPLETE);
142 * Import a name internal or mechanism name
144 * Type of name and their format:
145 * - GSS_C_NO_OID
146 * - GSS_C_NT_USER_NAME
147 * - GSS_C_NT_HOSTBASED_SERVICE
148 * - GSS_C_NT_EXPORT_NAME
149 * - GSS_C_NT_ANONYMOUS
150 * - GSS_KRB5_NT_PRINCIPAL_NAME
152 * For more information about @ref internalVSmechname.
154 * @param minor_status minor status code
155 * @param input_name_buffer import name buffer
156 * @param input_name_type type of the import name buffer
157 * @param output_name the resulting type, release with
158 * gss_release_name(), independent of input_name
160 * @returns a gss_error code, see gss_display_status() about printing
161 * the error code.
163 * @ingroup gssapi
166 OM_uint32 GSSAPI_LIB_FUNCTION
167 gss_import_name(OM_uint32 *minor_status,
168 const gss_buffer_t input_name_buffer,
169 const gss_OID input_name_type,
170 gss_name_t *output_name)
172 struct _gss_mechanism_name *mn;
173 gss_OID name_type = input_name_type;
174 OM_uint32 major_status, ms;
175 struct _gss_name *name;
176 struct _gss_mech_switch *m;
177 gss_name_t rname;
179 *output_name = GSS_C_NO_NAME;
181 if (input_name_buffer->length == 0) {
182 *minor_status = 0;
183 return (GSS_S_BAD_NAME);
186 _gss_load_mech();
189 * Use GSS_NT_USER_NAME as default name type.
191 if (name_type == GSS_C_NO_OID)
192 name_type = GSS_C_NT_USER_NAME;
195 * If this is an exported name, we need to parse it to find
196 * the mechanism and then import it as an MN. See RFC 2743
197 * section 3.2 for a description of the format.
199 if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
200 return _gss_import_export_name(minor_status,
201 input_name_buffer, output_name);
205 *minor_status = 0;
206 name = calloc(1, sizeof(struct _gss_name));
207 if (!name) {
208 *minor_status = ENOMEM;
209 return (GSS_S_FAILURE);
212 SLIST_INIT(&name->gn_mn);
214 major_status = _gss_copy_oid(minor_status,
215 name_type, &name->gn_type);
216 if (major_status) {
217 free(name);
218 return (GSS_S_FAILURE);
221 major_status = _gss_copy_buffer(minor_status,
222 input_name_buffer, &name->gn_value);
223 if (major_status)
224 goto out;
227 * Walk over the mechs and import the name into a mech name
228 * for those supported this nametype.
231 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
232 int present = 0;
234 major_status = gss_test_oid_set_member(minor_status,
235 name_type, m->gm_name_types, &present);
237 if (major_status || present == 0)
238 continue;
240 mn = malloc(sizeof(struct _gss_mechanism_name));
241 if (!mn) {
242 *minor_status = ENOMEM;
243 major_status = GSS_S_FAILURE;
244 goto out;
247 major_status = (*m->gm_mech.gm_import_name)(minor_status,
248 &name->gn_value,
249 (name->gn_type.elements
250 ? &name->gn_type : GSS_C_NO_OID),
251 &mn->gmn_name);
252 if (major_status != GSS_S_COMPLETE) {
253 _gss_mg_error(&m->gm_mech, major_status, *minor_status);
254 free(mn);
255 goto out;
258 mn->gmn_mech = &m->gm_mech;
259 mn->gmn_mech_oid = &m->gm_mech_oid;
260 SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
264 * If we can't find a mn for the name, bail out already here.
267 mn = SLIST_FIRST(&name->gn_mn);
268 if (!mn) {
269 *minor_status = 0;
270 major_status = GSS_S_NAME_NOT_MN;
271 goto out;
274 *output_name = (gss_name_t) name;
275 return (GSS_S_COMPLETE);
277 out:
278 rname = (gss_name_t)name;
279 gss_release_name(&ms, &rname);
280 return major_status;