1/*
2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include "ntlm.h"
37
38gss_name_t
39_gss_ntlm_create_name(OM_uint32 *minor_status,
40		      const char *user, const char *domain, int flags)
41{
42    ntlm_name n;
43    n = calloc(1, sizeof(*n));
44    if (n == NULL) {
45	*minor_status = ENOMEM;
46	return NULL;
47    }
48
49    n->user = strdup(user);
50    n->domain = strdup(domain);
51    n->flags = flags;
52
53    if (n->user == NULL || n->domain == NULL) {
54	free(n->user);
55	free(n->domain);
56	free(n);
57	*minor_status = ENOMEM;
58	return NULL;
59    }
60
61    return (gss_name_t)n;
62}
63
64static OM_uint32
65anon_name(OM_uint32 *minor_status,
66	  gss_const_OID mech,
67	  const gss_buffer_t input_name_buffer,
68	  gss_const_OID input_name_type,
69	  gss_name_t *output_name)
70{
71    *output_name = _gss_ntlm_create_name(minor_status, "", "", NTLM_ANON_NAME);
72    if (*output_name == NULL)
73	return GSS_S_FAILURE;
74    return GSS_S_COMPLETE;
75}
76
77static OM_uint32
78hostbased_name(OM_uint32 *minor_status,
79	       gss_const_OID mech,
80	       const gss_buffer_t input_name_buffer,
81	       gss_const_OID input_name_type,
82	       gss_name_t *output_name)
83{
84    char *name, *p;
85
86    name = malloc(input_name_buffer->length + 1);
87    if (name == NULL) {
88	*minor_status = ENOMEM;
89	return GSS_S_FAILURE;
90    }
91    memcpy(name, input_name_buffer->value, input_name_buffer->length);
92    name[input_name_buffer->length] = '\0';
93
94    /* find "domain" part of the name and uppercase it */
95    p = strchr(name, '@');
96    if (p) {
97	p[0] = '\0';
98	p++;
99    } else {
100	p = "";
101    }
102
103    *output_name = _gss_ntlm_create_name(minor_status, name, p, 0);
104    free(name);
105    if (*output_name == NULL)
106	return GSS_S_FAILURE;
107
108    return GSS_S_COMPLETE;
109}
110
111static OM_uint32
112parse_name(OM_uint32 *minor_status,
113	   gss_const_OID mech,
114	   int domain_required,
115	   const gss_buffer_t input_name_buffer,
116	   gss_const_OID input_name_type,
117	   gss_name_t *output_name)
118{
119    char *name, *p, *user, *domain;
120
121    if (memchr(input_name_buffer->value, '@', input_name_buffer->length) != NULL)
122	return hostbased_name(minor_status, mech, input_name_buffer,
123			      input_name_type, output_name);
124
125    name = malloc(input_name_buffer->length + 1);
126    if (name == NULL) {
127	*minor_status = ENOMEM;
128	return GSS_S_FAILURE;
129    }
130    memcpy(name, input_name_buffer->value, input_name_buffer->length);
131    name[input_name_buffer->length] = '\0';
132
133    /* find "domain" part of the name and uppercase it */
134    p = strchr(name, '\\');
135    if (p) {
136	p[0] = '\0';
137	user = p + 1;
138	domain = name;
139	strupr(domain);
140    } else if (!domain_required) {
141	user = name;
142	domain = ""; /* no domain */
143    } else {
144	*minor_status = HNTLM_ERR_MISSING_NAME_SEPARATOR;
145	return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_BAD_NAME,
146				       HNTLM_ERR_MISSING_NAME_SEPARATOR,
147				       "domain requested but missing name");
148    }
149
150    *output_name = _gss_ntlm_create_name(minor_status, user, domain, 0);
151    free(name);
152    if (*output_name == NULL)
153	return GSS_S_FAILURE;
154
155    return GSS_S_COMPLETE;
156}
157
158static OM_uint32
159user_name(OM_uint32 *minor_status,
160	  gss_const_OID mech,
161	  const gss_buffer_t input_name_buffer,
162	  gss_const_OID input_name_type,
163	  gss_name_t *output_name)
164{
165    return parse_name(minor_status, mech, 0, input_name_buffer, input_name_type, output_name);
166}
167
168static OM_uint32
169parse_ntlm_name(OM_uint32 *minor_status,
170		gss_const_OID mech,
171		const gss_buffer_t input_name_buffer,
172		gss_const_OID input_name_type,
173		gss_name_t *output_name)
174{
175    return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name);
176}
177
178static OM_uint32
179export_name(OM_uint32 *minor_status,
180	    gss_const_OID mech,
181	    const gss_buffer_t input_name_buffer,
182	    gss_const_OID input_name_type,
183	    gss_name_t *output_name)
184{
185    return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name);
186}
187
188static struct _gss_name_type ntlm_names[] = {
189    { GSS_C_NT_ANONYMOUS, anon_name},
190    { GSS_C_NT_HOSTBASED_SERVICE, hostbased_name},
191    { GSS_C_NT_USER_NAME, user_name },
192    { GSS_C_NT_NTLM, parse_ntlm_name },
193    { GSS_C_NT_EXPORT_NAME, export_name },
194    { NULL }
195};
196
197
198OM_uint32 _gss_ntlm_import_name
199           (OM_uint32 * minor_status,
200            const gss_buffer_t input_name_buffer,
201            gss_const_OID input_name_type,
202            gss_name_t * output_name
203           )
204{
205    return _gss_mech_import_name(minor_status, GSS_NTLM_MECHANISM,
206				 ntlm_names, input_name_buffer,
207				 input_name_type, output_name);
208}
209
210OM_uint32 _gss_ntlm_inquire_names_for_mech (
211            OM_uint32 * minor_status,
212            gss_const_OID mechanism,
213            gss_OID_set * name_types
214           )
215{
216    return _gss_mech_inquire_names_for_mech(minor_status, ntlm_names,
217					    name_types);
218}
219