1 /* $NetBSD: kdc.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
4 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
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
47 krb5_realm kerberos_realm
;
56 static OM_uint32
kdc_destroy(OM_uint32
*, void *);
59 * Get credential cache that the ntlm code can use to talk to the KDC
60 * using the digest API.
63 static krb5_error_code
64 get_ccache(krb5_context context
, int *destroy
, krb5_ccache
*id
)
66 krb5_principal principal
= NULL
;
68 krb5_keytab kt
= NULL
;
75 cache
= getenv("NTLM_ACCEPTOR_CCACHE");
77 ret
= krb5_cc_resolve(context
, cache
, id
);
84 ret
= krb5_sname_to_principal(context
, NULL
, "host",
85 KRB5_NT_SRV_HST
, &principal
);
89 ret
= krb5_cc_cache_match(context
, principal
, id
);
93 /* did not find in default credcache, lets try default keytab */
94 ret
= krb5_kt_default(context
, &kt
);
98 /* XXX check in keytab */
100 krb5_get_init_creds_opt
*opt
;
103 memset(&cred
, 0, sizeof(cred
));
105 ret
= krb5_cc_new_unique(context
, "MEMORY", NULL
, id
);
109 ret
= krb5_get_init_creds_opt_alloc(context
, &opt
);
112 ret
= krb5_get_init_creds_keytab (context
,
119 krb5_get_init_creds_opt_free(context
, opt
);
122 ret
= krb5_cc_initialize (context
, *id
, cred
.client
);
124 krb5_free_cred_contents (context
, &cred
);
127 ret
= krb5_cc_store_cred (context
, *id
, &cred
);
128 krb5_free_cred_contents (context
, &cred
);
133 krb5_kt_close(context
, kt
);
140 krb5_cc_destroy(context
, *id
);
142 krb5_cc_close(context
, *id
);
147 krb5_kt_close(context
, kt
);
150 krb5_free_principal(context
, principal
);
159 kdc_alloc(OM_uint32
*minor
, void **ctx
)
165 c
= calloc(1, sizeof(*c
));
168 return GSS_S_FAILURE
;
171 ret
= krb5_init_context(&c
->context
);
173 kdc_destroy(&junk
, c
);
175 return GSS_S_FAILURE
;
178 ret
= get_ccache(c
->context
, &c
->destroy
, &c
->id
);
180 kdc_destroy(&junk
, c
);
182 return GSS_S_FAILURE
;
185 ret
= krb5_ntlm_alloc(c
->context
, &c
->ntlm
);
187 kdc_destroy(&junk
, c
);
189 return GSS_S_FAILURE
;
194 return GSS_S_COMPLETE
;
198 kdc_probe(OM_uint32
*minor
, void *ctx
, const char *realm
)
200 struct ntlmkrb5
*c
= ctx
;
204 ret
= krb5_digest_probe(c
->context
, rk_UNCONST(realm
), c
->id
, &flags
);
208 if ((flags
& (1|2|4)) == 0)
219 kdc_destroy(OM_uint32
*minor
, void *ctx
)
221 struct ntlmkrb5
*c
= ctx
;
222 krb5_data_free(&c
->opaque
);
223 krb5_data_free(&c
->sessionkey
);
225 krb5_ntlm_free(c
->context
, c
->ntlm
);
228 krb5_cc_destroy(c
->context
, c
->id
);
230 krb5_cc_close(c
->context
, c
->id
);
233 krb5_free_context(c
->context
);
234 memset(c
, 0, sizeof(*c
));
237 return GSS_S_COMPLETE
;
245 kdc_type2(OM_uint32
*minor_status
,
248 const char *hostname
,
251 struct ntlm_buf
*out
)
253 struct ntlmkrb5
*c
= ctx
;
255 struct ntlm_type2 type2
;
257 struct ntlm_buf data
;
260 memset(&type2
, 0, sizeof(type2
));
263 * Request data for type 2 packet from the KDC.
265 ret
= krb5_ntlm_init_request(c
->context
,
274 return GSS_S_FAILURE
;
281 ret
= krb5_ntlm_init_get_opaque(c
->context
, c
->ntlm
, &c
->opaque
);
284 return GSS_S_FAILURE
;
291 ret
= krb5_ntlm_init_get_flags(c
->context
, c
->ntlm
, &type2
.flags
);
294 return GSS_S_FAILURE
;
296 *ret_flags
= type2
.flags
;
298 ret
= krb5_ntlm_init_get_challange(c
->context
, c
->ntlm
, &challange
);
301 return GSS_S_FAILURE
;
304 if (challange
.length
!= sizeof(type2
.challenge
)) {
305 *minor_status
= EINVAL
;
306 return GSS_S_FAILURE
;
308 memcpy(type2
.challenge
, challange
.data
, sizeof(type2
.challenge
));
309 krb5_data_free(&challange
);
311 ret
= krb5_ntlm_init_get_targetname(c
->context
, c
->ntlm
,
315 return GSS_S_FAILURE
;
318 ret
= krb5_ntlm_init_get_targetinfo(c
->context
, c
->ntlm
, &ti
);
320 free(type2
.targetname
);
322 return GSS_S_FAILURE
;
325 type2
.targetinfo
.data
= ti
.data
;
326 type2
.targetinfo
.length
= ti
.length
;
328 ret
= heim_ntlm_encode_type2(&type2
, &data
);
329 free(type2
.targetname
);
333 return GSS_S_FAILURE
;
336 out
->data
= data
.data
;
337 out
->length
= data
.length
;
339 return GSS_S_COMPLETE
;
347 kdc_type3(OM_uint32
*minor_status
,
349 const struct ntlm_type3
*type3
,
350 struct ntlm_buf
*sessionkey
)
352 struct ntlmkrb5
*c
= ctx
;
355 sessionkey
->data
= NULL
;
356 sessionkey
->length
= 0;
358 ret
= krb5_ntlm_req_set_flags(c
->context
, c
->ntlm
, type3
->flags
);
360 ret
= krb5_ntlm_req_set_username(c
->context
, c
->ntlm
, type3
->username
);
362 ret
= krb5_ntlm_req_set_targetname(c
->context
, c
->ntlm
,
365 ret
= krb5_ntlm_req_set_lm(c
->context
, c
->ntlm
,
366 type3
->lm
.data
, type3
->lm
.length
);
368 ret
= krb5_ntlm_req_set_ntlm(c
->context
, c
->ntlm
,
369 type3
->ntlm
.data
, type3
->ntlm
.length
);
371 ret
= krb5_ntlm_req_set_opaque(c
->context
, c
->ntlm
, &c
->opaque
);
374 if (type3
->sessionkey
.length
) {
375 ret
= krb5_ntlm_req_set_session(c
->context
, c
->ntlm
,
376 type3
->sessionkey
.data
,
377 type3
->sessionkey
.length
);
382 * Verify with the KDC the type3 packet is ok
384 ret
= krb5_ntlm_request(c
->context
,
391 if (krb5_ntlm_rep_get_status(c
->context
, c
->ntlm
) != TRUE
) {
396 if (type3
->sessionkey
.length
) {
397 ret
= krb5_ntlm_rep_get_sessionkey(c
->context
,
403 sessionkey
->data
= c
->sessionkey
.data
;
404 sessionkey
->length
= c
->sessionkey
.length
;
411 return GSS_S_FAILURE
;
419 kdc_free_buffer(struct ntlm_buf
*sessionkey
)
421 if (sessionkey
->data
)
422 free(sessionkey
->data
);
423 sessionkey
->data
= NULL
;
424 sessionkey
->length
= 0;
431 struct ntlm_server_interface ntlmsspi_kdc_digest
= {