2 * Copyright (c) 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
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
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
40 _netlogon_encode_dns_string(OM_uint32
*minor_status
,
41 const gss_buffer_t str
,
46 memset(buffer
->value
, 0, buffer
->length
);
48 ret
= ns_name_compress((const char *)str
->value
,
49 (uint8_t *)buffer
->value
, buffer
->length
,
52 *minor_status
= errno
;
59 return GSS_S_COMPLETE
;
63 _netlogon_make_initial_auth_message(OM_uint32
*minor_status
,
65 gss_buffer_t output_token
)
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
;
75 if (ctx
->TargetName
->NetbiosName
.length
) {
76 flags
|= NL_FLAG_NETBIOS_DOMAIN_NAME
;
77 names
[n
] = ctx
->TargetName
->NetbiosName
; /* OEM encoding */
81 if (ctx
->SourceName
->NetbiosName
.length
) {
82 flags
|= NL_FLAG_NETBIOS_COMPUTER_NAME
;
83 names
[n
] = ctx
->SourceName
->NetbiosName
; /* OEM encoding */
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
,
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
,
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
,
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);
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
);
147 return GSS_S_CONTINUE_NEEDED
;
151 _netlogon_read_initial_auth_message(OM_uint32
*minor_status
,
153 const gss_buffer_t input_token
)
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
||
171 return GSS_S_DEFECTIVE_TOKEN
;
173 ctx
->State
= NL_AUTH_ESTABLISHED
;
176 return GSS_S_COMPLETE
;
180 _netlogon_alloc_context(OM_uint32
*minor_status
,
181 gssnetlogon_ctx
*pContext
)
185 ctx
= (gssnetlogon_ctx
)calloc(1, sizeof(*ctx
));
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
);
199 return GSS_S_COMPLETE
;
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
,
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
;
224 output_token
->value
= NULL
;
225 output_token
->length
= 0;
227 /* Validate arguments */
229 return GSS_S_NO_CRED
;
230 else if (target
== NULL
)
231 return GSS_S_BAD_NAME
;
234 if (input_token
->length
!= 0)
235 return GSS_S_DEFECTIVE_TOKEN
;
237 ret
= _netlogon_alloc_context(minor_status
, &ctx
);
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
);
255 ret
= _netlogon_duplicate_name(minor_status
, (gss_name_t
)target
,
256 (gss_name_t
*)&ctx
->TargetName
);
260 memcpy(ctx
->SessionKey
, cred
->SessionKey
, sizeof(cred
->SessionKey
));
262 ret
= _netlogon_make_initial_auth_message(minor_status
, ctx
,
267 HEIMDAL_MUTEX_lock(&ctx
->Mutex
);
268 ret
= _netlogon_read_initial_auth_message(minor_status
, ctx
,
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
;
280 HEIMDAL_MUTEX_unlock(&ctx
->Mutex
);
282 if (ret
!= GSS_S_COMPLETE
&& ret
!= GSS_S_CONTINUE_NEEDED
) {
284 _netlogon_delete_sec_context(&tmp
, context_handle
, NULL
);