Remove building with NOCRYPTO option
[minix.git] / crypto / external / bsd / heimdal / dist / lib / gssapi / netlogon / init_sec_context.c
blob8a08c987484f3bff40fde957845bdb524a90ca40
1 /* $NetBSD: init_sec_context.c,v 1.1.1.1 2011/04/13 18:14:47 elric Exp $ */
3 /*
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
38 #include "netlogon.h"
39 #include <nameser.h>
41 static OM_uint32
42 _netlogon_encode_dns_string(OM_uint32 *minor_status,
43 const gss_buffer_t str,
44 gss_buffer_t buffer)
46 int ret;
48 memset(buffer->value, 0, buffer->length);
50 ret = ns_name_compress((const char *)str->value,
51 (uint8_t *)buffer->value, buffer->length,
52 NULL, NULL);
53 if (ret < 0) {
54 *minor_status = errno;
55 return GSS_S_FAILURE;
58 buffer->length = ret;
60 *minor_status = 0;
61 return GSS_S_COMPLETE;
64 static OM_uint32
65 _netlogon_make_initial_auth_message(OM_uint32 *minor_status,
66 gssnetlogon_ctx ctx,
67 gss_buffer_t output_token)
69 uint32_t flags = 0;
70 #define MAX_NL_NAMES 5
71 gss_buffer_desc names[MAX_NL_NAMES];
72 uint8_t comp_names[3][MAXHOSTNAMELEN * 2];
73 size_t n = 0, i = 0, len;
74 OM_uint32 ret;
75 uint8_t *p;
77 if (ctx->TargetName->NetbiosName.length) {
78 flags |= NL_FLAG_NETBIOS_DOMAIN_NAME;
79 names[n] = ctx->TargetName->NetbiosName; /* OEM encoding */
80 names[n].length++;
81 n++;
83 if (ctx->SourceName->NetbiosName.length) {
84 flags |= NL_FLAG_NETBIOS_COMPUTER_NAME;
85 names[n] = ctx->SourceName->NetbiosName; /* OEM encoding */
86 names[n].length++;
87 n++;
89 if (ctx->TargetName->DnsName.length) {
90 flags |= NL_FLAG_DNS_DOMAIN_NAME;
91 names[n].value = comp_names[i++];
92 names[n].length = MAXHOSTNAMELEN * 2;
93 ret = _netlogon_encode_dns_string(minor_status,
94 &ctx->TargetName->DnsName,
95 &names[n]);
96 if (GSS_ERROR(ret))
97 return ret;
98 n++;
100 if (ctx->SourceName->DnsName.length) {
101 flags |= NL_FLAG_DNS_HOST_NAME;
102 names[n].value = comp_names[i++];
103 names[n].length = MAXHOSTNAMELEN * 2;
104 ret = _netlogon_encode_dns_string(minor_status,
105 &ctx->SourceName->DnsName,
106 &names[n]);
107 if (GSS_ERROR(ret))
108 return ret;
109 n++;
111 if (ctx->SourceName->NetbiosName.length) {
112 flags |= NL_FLAG_UTF8_COMPUTER_NAME;
113 names[n].value = comp_names[i++];
114 names[n].length = MAXHOSTNAMELEN * 2;
115 ret = _netlogon_encode_dns_string(minor_status,
116 &ctx->SourceName->NetbiosName,
117 &names[n]);
118 if (GSS_ERROR(ret))
119 return ret;
120 n++;
123 for (i = 0, len = NL_AUTH_MESSAGE_LENGTH; i < n; i++) {
124 len += names[i].length;
127 output_token->value = malloc(len);
128 if (output_token->value == NULL) {
129 *minor_status = ENOMEM;
130 return GSS_S_FAILURE;
133 p = (uint8_t *)output_token->value;
134 _gss_mg_encode_le_uint32(NL_NEGOTIATE_REQUEST_MESSAGE, p);
135 _gss_mg_encode_le_uint32(flags, p + 4);
136 p += 8;
138 for (i = 0; i < n; i++) {
139 assert(names[i].length != 0);
140 assert(((char *)names[i].value)[names[i].length - 1] == '\0');
141 memcpy(p, names[i].value, names[i].length);
142 p += names[i].length;
145 output_token->length = len;
146 assert(p == (uint8_t *)output_token->value + len);
148 *minor_status = 0;
149 return GSS_S_CONTINUE_NEEDED;
152 static OM_uint32
153 _netlogon_read_initial_auth_message(OM_uint32 *minor_status,
154 gssnetlogon_ctx ctx,
155 const gss_buffer_t input_token)
157 NL_AUTH_MESSAGE msg;
158 const uint8_t *p = (const uint8_t *)input_token->value;
160 if (ctx->State != NL_AUTH_NEGOTIATE) {
161 *minor_status = EINVAL;
162 return GSS_S_FAILURE;
165 if (input_token->length < NL_AUTH_MESSAGE_LENGTH)
166 return GSS_S_DEFECTIVE_TOKEN;
168 _gss_mg_decode_le_uint32(&p[0], &msg.MessageType);
169 _gss_mg_decode_le_uint32(&p[4], &msg.Flags);
171 if (msg.MessageType != NL_NEGOTIATE_RESPONSE_MESSAGE ||
172 msg.Flags != 0)
173 return GSS_S_DEFECTIVE_TOKEN;
175 ctx->State = NL_AUTH_ESTABLISHED;
177 *minor_status = 0;
178 return GSS_S_COMPLETE;
181 static OM_uint32
182 _netlogon_alloc_context(OM_uint32 *minor_status,
183 gssnetlogon_ctx *pContext)
185 gssnetlogon_ctx ctx;
187 ctx = (gssnetlogon_ctx)calloc(1, sizeof(*ctx));
188 if (ctx == NULL) {
189 *minor_status = ENOMEM;
190 return GSS_S_FAILURE;
193 ctx->State = NL_AUTH_NEGOTIATE;
194 ctx->LocallyInitiated = 1;
195 ctx->MessageBlockSize = 1;
197 HEIMDAL_MUTEX_init(&ctx->Mutex);
199 *pContext = ctx;
201 return GSS_S_COMPLETE;
204 OM_uint32
205 _netlogon_init_sec_context(OM_uint32 * minor_status,
206 const gss_cred_id_t initiator_cred_handle,
207 gss_ctx_id_t * context_handle,
208 const gss_name_t target_name,
209 const gss_OID mech_type,
210 OM_uint32 req_flags,
211 OM_uint32 time_req,
212 const gss_channel_bindings_t input_chan_bindings,
213 const gss_buffer_t input_token,
214 gss_OID * actual_mech_type,
215 gss_buffer_t output_token,
216 OM_uint32 * ret_flags,
217 OM_uint32 * time_rec)
219 const gssnetlogon_cred cred = (const gssnetlogon_cred)initiator_cred_handle;
220 gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle;
221 const gssnetlogon_name target = (const gssnetlogon_name)target_name;
222 OM_uint32 ret;
224 *minor_status = 0;
226 output_token->value = NULL;
227 output_token->length = 0;
229 /* Validate arguments */
230 if (cred == NULL)
231 return GSS_S_NO_CRED;
232 else if (target == NULL)
233 return GSS_S_BAD_NAME;
235 if (ctx == NULL) {
236 if (input_token->length != 0)
237 return GSS_S_DEFECTIVE_TOKEN;
239 ret = _netlogon_alloc_context(minor_status, &ctx);
240 if (GSS_ERROR(ret))
241 goto cleanup;
243 HEIMDAL_MUTEX_lock(&ctx->Mutex);
244 *context_handle = (gss_ctx_id_t)ctx;
246 ctx->GssFlags = req_flags & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
247 GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
248 GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE);
249 ctx->SignatureAlgorithm = cred->SignatureAlgorithm;
250 ctx->SealAlgorithm = cred->SealAlgorithm;
252 ret = _netlogon_duplicate_name(minor_status, (gss_name_t)cred->Name,
253 (gss_name_t *)&ctx->SourceName);
254 if (GSS_ERROR(ret))
255 goto cleanup;
257 ret = _netlogon_duplicate_name(minor_status, (gss_name_t)target,
258 (gss_name_t *)&ctx->TargetName);
259 if (GSS_ERROR(ret))
260 goto cleanup;
262 memcpy(ctx->SessionKey, cred->SessionKey, sizeof(cred->SessionKey));
264 ret = _netlogon_make_initial_auth_message(minor_status, ctx,
265 output_token);
266 if (GSS_ERROR(ret))
267 goto cleanup;
268 } else {
269 HEIMDAL_MUTEX_lock(&ctx->Mutex);
270 ret = _netlogon_read_initial_auth_message(minor_status, ctx,
271 input_token);
274 if (ret_flags != NULL)
275 *ret_flags = ctx->GssFlags;
276 if (time_rec != NULL)
277 *time_rec = GSS_C_INDEFINITE;
278 if (actual_mech_type != NULL)
279 *actual_mech_type = GSS_NETLOGON_MECHANISM;
281 cleanup:
282 HEIMDAL_MUTEX_unlock(&ctx->Mutex);
284 if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
285 OM_uint32 tmp;
286 _netlogon_delete_sec_context(&tmp, context_handle, NULL);
289 return ret;