1 /* $NetBSD: init_sec_context.c,v 1.1.1.1 2011/04/13 18:14:47 elric Exp $ */
4 * Copyright (c) 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
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
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
42 _netlogon_encode_dns_string(OM_uint32
*minor_status
,
43 const gss_buffer_t str
,
48 memset(buffer
->value
, 0, buffer
->length
);
50 ret
= ns_name_compress((const char *)str
->value
,
51 (uint8_t *)buffer
->value
, buffer
->length
,
54 *minor_status
= errno
;
61 return GSS_S_COMPLETE
;
65 _netlogon_make_initial_auth_message(OM_uint32
*minor_status
,
67 gss_buffer_t output_token
)
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
;
77 if (ctx
->TargetName
->NetbiosName
.length
) {
78 flags
|= NL_FLAG_NETBIOS_DOMAIN_NAME
;
79 names
[n
] = ctx
->TargetName
->NetbiosName
; /* OEM encoding */
83 if (ctx
->SourceName
->NetbiosName
.length
) {
84 flags
|= NL_FLAG_NETBIOS_COMPUTER_NAME
;
85 names
[n
] = ctx
->SourceName
->NetbiosName
; /* OEM encoding */
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
,
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
,
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
,
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);
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
);
149 return GSS_S_CONTINUE_NEEDED
;
153 _netlogon_read_initial_auth_message(OM_uint32
*minor_status
,
155 const gss_buffer_t input_token
)
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
||
173 return GSS_S_DEFECTIVE_TOKEN
;
175 ctx
->State
= NL_AUTH_ESTABLISHED
;
178 return GSS_S_COMPLETE
;
182 _netlogon_alloc_context(OM_uint32
*minor_status
,
183 gssnetlogon_ctx
*pContext
)
187 ctx
= (gssnetlogon_ctx
)calloc(1, sizeof(*ctx
));
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
);
201 return GSS_S_COMPLETE
;
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
,
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
;
226 output_token
->value
= NULL
;
227 output_token
->length
= 0;
229 /* Validate arguments */
231 return GSS_S_NO_CRED
;
232 else if (target
== NULL
)
233 return GSS_S_BAD_NAME
;
236 if (input_token
->length
!= 0)
237 return GSS_S_DEFECTIVE_TOKEN
;
239 ret
= _netlogon_alloc_context(minor_status
, &ctx
);
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
);
257 ret
= _netlogon_duplicate_name(minor_status
, (gss_name_t
)target
,
258 (gss_name_t
*)&ctx
->TargetName
);
262 memcpy(ctx
->SessionKey
, cred
->SessionKey
, sizeof(cred
->SessionKey
));
264 ret
= _netlogon_make_initial_auth_message(minor_status
, ctx
,
269 HEIMDAL_MUTEX_lock(&ctx
->Mutex
);
270 ret
= _netlogon_read_initial_auth_message(minor_status
, ctx
,
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
;
282 HEIMDAL_MUTEX_unlock(&ctx
->Mutex
);
284 if (ret
!= GSS_S_COMPLETE
&& ret
!= GSS_S_CONTINUE_NEEDED
) {
286 _netlogon_delete_sec_context(&tmp
, context_handle
, NULL
);