First attempt s/\<const gss_.*_t/gss_const_.*_t/g
[heimdal.git] / lib / gssapi / netlogon / init_sec_context.c
blob906f457444946ae84bef0e2514d63312e0b90993
1 /*
2 * Copyright (c) 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
36 #include "netlogon.h"
37 #include <nameser.h>
39 static OM_uint32
40 _netlogon_encode_dns_string(OM_uint32 *minor_status,
41 const gss_buffer_t str,
42 gss_buffer_t buffer)
44 int ret;
46 memset(buffer->value, 0, buffer->length);
48 ret = ns_name_compress((const char *)str->value,
49 (uint8_t *)buffer->value, buffer->length,
50 NULL, NULL);
51 if (ret < 0) {
52 *minor_status = errno;
53 return GSS_S_FAILURE;
56 buffer->length = ret;
58 *minor_status = 0;
59 return GSS_S_COMPLETE;
62 static OM_uint32
63 _netlogon_make_initial_auth_message(OM_uint32 *minor_status,
64 gssnetlogon_ctx ctx,
65 gss_buffer_t output_token)
67 uint32_t flags = 0;
68 #define MAX_NL_NAMES 5
69 gss_buffer_desc names[MAX_NL_NAMES];
70 uint8_t comp_names[3][MAXHOSTNAMELEN * 2];
71 size_t n = 0, i = 0, len;
72 OM_uint32 ret;
73 uint8_t *p;
75 if (ctx->TargetName->NetbiosName.length) {
76 flags |= NL_FLAG_NETBIOS_DOMAIN_NAME;
77 names[n] = ctx->TargetName->NetbiosName; /* OEM encoding */
78 names[n].length++;
79 n++;
81 if (ctx->SourceName->NetbiosName.length) {
82 flags |= NL_FLAG_NETBIOS_COMPUTER_NAME;
83 names[n] = ctx->SourceName->NetbiosName; /* OEM encoding */
84 names[n].length++;
85 n++;
87 if (ctx->TargetName->DnsName.length) {
88 flags |= NL_FLAG_DNS_DOMAIN_NAME;
89 names[n].value = comp_names[i++];
90 names[n].length = MAXHOSTNAMELEN * 2;
91 ret = _netlogon_encode_dns_string(minor_status,
92 &ctx->TargetName->DnsName,
93 &names[n]);
94 if (GSS_ERROR(ret))
95 return ret;
96 n++;
98 if (ctx->SourceName->DnsName.length) {
99 flags |= NL_FLAG_DNS_HOST_NAME;
100 names[n].value = comp_names[i++];
101 names[n].length = MAXHOSTNAMELEN * 2;
102 ret = _netlogon_encode_dns_string(minor_status,
103 &ctx->SourceName->DnsName,
104 &names[n]);
105 if (GSS_ERROR(ret))
106 return ret;
107 n++;
109 if (ctx->SourceName->NetbiosName.length) {
110 flags |= NL_FLAG_UTF8_COMPUTER_NAME;
111 names[n].value = comp_names[i++];
112 names[n].length = MAXHOSTNAMELEN * 2;
113 ret = _netlogon_encode_dns_string(minor_status,
114 &ctx->SourceName->NetbiosName,
115 &names[n]);
116 if (GSS_ERROR(ret))
117 return ret;
118 n++;
121 for (i = 0, len = NL_AUTH_MESSAGE_LENGTH; i < n; i++) {
122 len += names[i].length;
125 output_token->value = malloc(len);
126 if (output_token->value == NULL) {
127 *minor_status = ENOMEM;
128 return GSS_S_FAILURE;
131 p = (uint8_t *)output_token->value;
132 _gss_mg_encode_le_uint32(NL_NEGOTIATE_REQUEST_MESSAGE, p);
133 _gss_mg_encode_le_uint32(flags, p + 4);
134 p += 8;
136 for (i = 0; i < n; i++) {
137 assert(names[i].length != 0);
138 assert(((char *)names[i].value)[names[i].length - 1] == '\0');
139 memcpy(p, names[i].value, names[i].length);
140 p += names[i].length;
143 output_token->length = len;
144 assert(p == (uint8_t *)output_token->value + len);
146 *minor_status = 0;
147 return GSS_S_CONTINUE_NEEDED;
150 static OM_uint32
151 _netlogon_read_initial_auth_message(OM_uint32 *minor_status,
152 gssnetlogon_ctx ctx,
153 const gss_buffer_t input_token)
155 NL_AUTH_MESSAGE msg;
156 const uint8_t *p = (const uint8_t *)input_token->value;
158 if (ctx->State != NL_AUTH_NEGOTIATE) {
159 *minor_status = EINVAL;
160 return GSS_S_FAILURE;
163 if (input_token->length < NL_AUTH_MESSAGE_LENGTH)
164 return GSS_S_DEFECTIVE_TOKEN;
166 _gss_mg_decode_le_uint32(&p[0], &msg.MessageType);
167 _gss_mg_decode_le_uint32(&p[4], &msg.Flags);
169 if (msg.MessageType != NL_NEGOTIATE_RESPONSE_MESSAGE ||
170 msg.Flags != 0)
171 return GSS_S_DEFECTIVE_TOKEN;
173 ctx->State = NL_AUTH_ESTABLISHED;
175 *minor_status = 0;
176 return GSS_S_COMPLETE;
179 static OM_uint32
180 _netlogon_alloc_context(OM_uint32 *minor_status,
181 gssnetlogon_ctx *pContext)
183 gssnetlogon_ctx ctx;
185 ctx = (gssnetlogon_ctx)calloc(1, sizeof(*ctx));
186 if (ctx == NULL) {
187 *minor_status = ENOMEM;
188 return GSS_S_FAILURE;
191 ctx->State = NL_AUTH_NEGOTIATE;
192 ctx->LocallyInitiated = 1;
193 ctx->MessageBlockSize = 1;
195 HEIMDAL_MUTEX_init(&ctx->Mutex);
197 *pContext = ctx;
199 return GSS_S_COMPLETE;
202 OM_uint32
203 _netlogon_init_sec_context(OM_uint32 * minor_status,
204 gss_const_cred_id_t initiator_cred_handle,
205 gss_ctx_id_t * context_handle,
206 gss_const_name_t target_name,
207 const gss_OID mech_type,
208 OM_uint32 req_flags,
209 OM_uint32 time_req,
210 const gss_channel_bindings_t input_chan_bindings,
211 const gss_buffer_t input_token,
212 gss_OID * actual_mech_type,
213 gss_buffer_t output_token,
214 OM_uint32 * ret_flags,
215 OM_uint32 * time_rec)
217 const gssnetlogon_cred cred = (const gssnetlogon_cred)initiator_cred_handle;
218 gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle;
219 const gssnetlogon_name target = (const gssnetlogon_name)target_name;
220 OM_uint32 ret;
222 *minor_status = 0;
224 output_token->value = NULL;
225 output_token->length = 0;
227 /* Validate arguments */
228 if (cred == NULL)
229 return GSS_S_NO_CRED;
230 else if (target == NULL)
231 return GSS_S_BAD_NAME;
233 if (ctx == NULL) {
234 if (input_token->length != 0)
235 return GSS_S_DEFECTIVE_TOKEN;
237 ret = _netlogon_alloc_context(minor_status, &ctx);
238 if (GSS_ERROR(ret))
239 goto cleanup;
241 HEIMDAL_MUTEX_lock(&ctx->Mutex);
242 *context_handle = (gss_ctx_id_t)ctx;
244 ctx->GssFlags = req_flags & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
245 GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
246 GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE);
247 ctx->SignatureAlgorithm = cred->SignatureAlgorithm;
248 ctx->SealAlgorithm = cred->SealAlgorithm;
250 ret = _netlogon_duplicate_name(minor_status, (gss_name_t)cred->Name,
251 (gss_name_t *)&ctx->SourceName);
252 if (GSS_ERROR(ret))
253 goto cleanup;
255 ret = _netlogon_duplicate_name(minor_status, (gss_name_t)target,
256 (gss_name_t *)&ctx->TargetName);
257 if (GSS_ERROR(ret))
258 goto cleanup;
260 memcpy(ctx->SessionKey, cred->SessionKey, sizeof(cred->SessionKey));
262 ret = _netlogon_make_initial_auth_message(minor_status, ctx,
263 output_token);
264 if (GSS_ERROR(ret))
265 goto cleanup;
266 } else {
267 HEIMDAL_MUTEX_lock(&ctx->Mutex);
268 ret = _netlogon_read_initial_auth_message(minor_status, ctx,
269 input_token);
272 if (ret_flags != NULL)
273 *ret_flags = ctx->GssFlags;
274 if (time_rec != NULL)
275 *time_rec = GSS_C_INDEFINITE;
276 if (actual_mech_type != NULL)
277 *actual_mech_type = GSS_NETLOGON_MECHANISM;
279 cleanup:
280 HEIMDAL_MUTEX_unlock(&ctx->Mutex);
282 if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
283 OM_uint32 tmp;
284 _netlogon_delete_sec_context(&tmp, context_handle, NULL);
287 return ret;