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	free(name);
145	*minor_status = HNTLM_ERR_MISSING_NAME_SEPARATOR;
146	return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_BAD_NAME,
147				       HNTLM_ERR_MISSING_NAME_SEPARATOR,
148				       "domain requested but missing name");
149    }
150
151    *output_name = _gss_ntlm_create_name(minor_status, user, domain, 0);
152    free(name);
153    if (*output_name == NULL)
154	return GSS_S_FAILURE;
155
156    return GSS_S_COMPLETE;
157}
158
159static OM_uint32
160user_name(OM_uint32 *minor_status,
161	  gss_const_OID mech,
162	  const gss_buffer_t input_name_buffer,
163	  gss_const_OID input_name_type,
164	  gss_name_t *output_name)
165{
166    return parse_name(minor_status, mech, 0, input_name_buffer, input_name_type, output_name);
167}
168
169static OM_uint32
170parse_ntlm_name(OM_uint32 *minor_status,
171		gss_const_OID mech,
172		const gss_buffer_t input_name_buffer,
173		gss_const_OID input_name_type,
174		gss_name_t *output_name)
175{
176    return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name);
177}
178
179static OM_uint32
180export_name(OM_uint32 *minor_status,
181	    gss_const_OID mech,
182	    const gss_buffer_t input_name_buffer,
183	    gss_const_OID input_name_type,
184	    gss_name_t *output_name)
185{
186    return parse_name(minor_status, mech, 1, input_name_buffer, input_name_type, output_name);
187}
188
189static struct _gss_name_type ntlm_names[] = {
190    { GSS_C_NT_ANONYMOUS, anon_name},
191    { GSS_C_NT_HOSTBASED_SERVICE, hostbased_name},
192    { GSS_C_NT_USER_NAME, user_name },
193    { GSS_C_NT_NTLM, parse_ntlm_name },
194    { GSS_C_NT_EXPORT_NAME, export_name },
195    { NULL }
196};
197
198
199OM_uint32 _gss_ntlm_import_name
200           (OM_uint32 * minor_status,
201            const gss_buffer_t input_name_buffer,
202            gss_const_OID input_name_type,
203            gss_name_t * output_name
204           )
205{
206    return _gss_mech_import_name(minor_status, GSS_NTLM_MECHANISM,
207				 ntlm_names, input_name_buffer,
208				 input_name_type, output_name);
209}
210
211OM_uint32 _gss_ntlm_inquire_names_for_mech (
212            OM_uint32 * minor_status,
213            gss_const_OID mechanism,
214            gss_OID_set * name_types
215           )
216{
217    return _gss_mech_inquire_names_for_mech(minor_status, ntlm_names,
218					    name_types);
219}
220