r19604: This is a massive commit, and I appologise in advance for it's size.
[Samba.git] / source / heimdal / lib / gssapi / mech / gss_import_name.c
blob9684301ba48375face7cac98d194c3afdbe6a005
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: gss_import_name.c,v 1.3 2006/06/29 21:23:13 lha Exp $");
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);
124 * Now we make a new name and mark it as an MN.
126 name = _gss_make_name(m, new_canonical_name);
127 if (!name) {
128 m->gm_release_name(minor_status, &new_canonical_name);
129 return (GSS_S_FAILURE);
132 *output_name = (gss_name_t) name;
134 *minor_status = 0;
135 return (GSS_S_COMPLETE);
138 OM_uint32
139 gss_import_name(OM_uint32 *minor_status,
140 const gss_buffer_t input_name_buffer,
141 const gss_OID input_name_type,
142 gss_name_t *output_name)
144 gss_OID name_type = input_name_type;
145 OM_uint32 major_status;
146 struct _gss_name *name;
148 if (input_name_buffer->length == 0) {
149 *minor_status = 0;
150 *output_name = 0;
151 return (GSS_S_BAD_NAME);
155 * Use GSS_NT_USER_NAME as default name type.
157 if (name_type == GSS_C_NO_OID)
158 name_type = GSS_C_NT_USER_NAME;
161 * If this is an exported name, we need to parse it to find
162 * the mechanism and then import it as an MN. See RFC 2743
163 * section 3.2 for a description of the format.
165 if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
166 return _gss_import_export_name(minor_status,
167 input_name_buffer, output_name);
171 * Only allow certain name types. This is pretty bogus - we
172 * should figure out the list of supported name types using
173 * gss_inquire_names_for_mech.
175 if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME)
176 && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)
177 && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME)
178 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X)
179 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)
180 && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)
181 && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) {
182 *minor_status = 0;
183 *output_name = 0;
184 return (GSS_S_BAD_NAMETYPE);
187 *minor_status = 0;
188 name = malloc(sizeof(struct _gss_name));
189 if (!name) {
190 *minor_status = ENOMEM;
191 return (GSS_S_FAILURE);
193 memset(name, 0, sizeof(struct _gss_name));
195 major_status = _gss_copy_oid(minor_status,
196 name_type, &name->gn_type);
197 if (major_status) {
198 free(name);
199 return (GSS_S_FAILURE);
202 major_status = _gss_copy_buffer(minor_status,
203 input_name_buffer, &name->gn_value);
204 if (major_status) {
205 gss_name_t rname = (gss_name_t)name;
206 gss_release_name(minor_status, &rname);
207 return (GSS_S_FAILURE);
210 SLIST_INIT(&name->gn_mn);
212 *output_name = (gss_name_t) name;
213 return (GSS_S_COMPLETE);