2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
35 #include "digest_asn1.h"
37 #ifndef HEIMDAL_SMALLER
39 struct krb5_digest_data
{
44 DigestInitReply initReply
;
45 DigestRequest request
;
46 DigestResponse response
;
49 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
50 krb5_digest_alloc(krb5_context context
, krb5_digest
*digest
)
54 d
= calloc(1, sizeof(*d
));
57 return krb5_enomem(context
);
64 KRB5_LIB_FUNCTION
void KRB5_LIB_CALL
65 krb5_digest_free(krb5_digest digest
)
69 free_DigestInit(&digest
->init
);
70 free_DigestInitReply(&digest
->initReply
);
71 free_DigestRequest(&digest
->request
);
72 free_DigestResponse(&digest
->response
);
73 memset(digest
, 0, sizeof(*digest
));
78 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
79 krb5_digest_set_server_cb(krb5_context context
,
84 if (digest
->init
.channel
) {
85 krb5_set_error_message(context
, EINVAL
,
86 N_("server channel binding already set", ""));
89 digest
->init
.channel
= calloc(1, sizeof(*digest
->init
.channel
));
90 if (digest
->init
.channel
== NULL
)
93 digest
->init
.channel
->cb_type
= strdup(type
);
94 if (digest
->init
.channel
->cb_type
== NULL
)
97 digest
->init
.channel
->cb_binding
= strdup(binding
);
98 if (digest
->init
.channel
->cb_binding
== NULL
)
102 if (digest
->init
.channel
) {
103 free(digest
->init
.channel
->cb_type
);
104 free(digest
->init
.channel
->cb_binding
);
105 free(digest
->init
.channel
);
106 digest
->init
.channel
= NULL
;
108 return krb5_enomem(context
);
111 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
112 krb5_digest_set_type(krb5_context context
,
116 if (digest
->init
.type
) {
117 krb5_set_error_message(context
, EINVAL
, "client type already set");
120 digest
->init
.type
= strdup(type
);
121 if (digest
->init
.type
== NULL
)
122 return krb5_enomem(context
);
126 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
127 krb5_digest_set_hostname(krb5_context context
,
129 const char *hostname
)
131 if (digest
->init
.hostname
) {
132 krb5_set_error_message(context
, EINVAL
, "server hostname already set");
135 digest
->init
.hostname
= malloc(sizeof(*digest
->init
.hostname
));
136 if (digest
->init
.hostname
== NULL
)
137 return krb5_enomem(context
);
138 *digest
->init
.hostname
= strdup(hostname
);
139 if (*digest
->init
.hostname
== NULL
) {
140 free(digest
->init
.hostname
);
141 digest
->init
.hostname
= NULL
;
142 return krb5_enomem(context
);
147 KRB5_LIB_FUNCTION
const char * KRB5_LIB_CALL
148 krb5_digest_get_server_nonce(krb5_context context
,
151 return digest
->initReply
.nonce
;
154 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
155 krb5_digest_set_server_nonce(krb5_context context
,
159 if (digest
->request
.serverNonce
) {
160 krb5_set_error_message(context
, EINVAL
, N_("nonce already set", ""));
163 digest
->request
.serverNonce
= strdup(nonce
);
164 if (digest
->request
.serverNonce
== NULL
)
165 return krb5_enomem(context
);
169 KRB5_LIB_FUNCTION
const char * KRB5_LIB_CALL
170 krb5_digest_get_opaque(krb5_context context
,
173 return digest
->initReply
.opaque
;
176 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
177 krb5_digest_set_opaque(krb5_context context
,
181 if (digest
->request
.opaque
) {
182 krb5_set_error_message(context
, EINVAL
, "opaque already set");
185 digest
->request
.opaque
= strdup(opaque
);
186 if (digest
->request
.opaque
== NULL
)
187 return krb5_enomem(context
);
191 KRB5_LIB_FUNCTION
const char * KRB5_LIB_CALL
192 krb5_digest_get_identifier(krb5_context context
,
195 if (digest
->initReply
.identifier
== NULL
)
197 return *digest
->initReply
.identifier
;
200 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
201 krb5_digest_set_identifier(krb5_context context
,
205 if (digest
->request
.identifier
) {
206 krb5_set_error_message(context
, EINVAL
, N_("identifier already set", ""));
209 digest
->request
.identifier
= calloc(1, sizeof(*digest
->request
.identifier
));
210 if (digest
->request
.identifier
== NULL
)
211 return krb5_enomem(context
);
212 *digest
->request
.identifier
= strdup(id
);
213 if (*digest
->request
.identifier
== NULL
) {
214 free(digest
->request
.identifier
);
215 digest
->request
.identifier
= NULL
;
216 return krb5_enomem(context
);
221 static krb5_error_code
222 digest_request(krb5_context context
,
225 krb5_key_usage usage
,
226 const DigestReqInner
*ireq
,
227 DigestRepInner
*irep
)
232 krb5_data data
, data2
;
234 krb5_crypto crypto
= NULL
;
235 krb5_auth_context ac
= NULL
;
236 krb5_principal principal
= NULL
;
237 krb5_ccache id
= NULL
;
240 krb5_data_zero(&data
);
241 krb5_data_zero(&data2
);
242 memset(&req
, 0, sizeof(req
));
243 memset(&rep
, 0, sizeof(rep
));
245 if (ccache
== NULL
) {
246 ret
= krb5_cc_default(context
, &id
);
253 ret
= krb5_get_default_realm(context
, &r
);
263 ret
= krb5_make_principal(context
, &principal
,
264 r
, KRB5_DIGEST_NAME
, r
, NULL
);
268 ASN1_MALLOC_ENCODE(DigestReqInner
, data
.data
, data
.length
,
271 krb5_set_error_message(context
, ret
,
272 N_("Failed to encode digest inner request", ""));
275 if (size
!= data
.length
)
276 krb5_abortx(context
, "ASN.1 internal encoder error");
278 ret
= krb5_mk_req_exact(context
, &ac
,
279 AP_OPTS_USE_SUBKEY
|AP_OPTS_MUTUAL_REQUIRED
,
280 principal
, NULL
, id
, &req
.apReq
);
287 ret
= krb5_auth_con_getlocalsubkey(context
, ac
, &key
);
292 krb5_set_error_message(context
, ret
,
293 N_("Digest failed to get local subkey", ""));
297 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
298 krb5_free_keyblock (context
, key
);
303 ret
= krb5_encrypt_EncryptedData(context
, crypto
, usage
,
304 data
.data
, data
.length
, 0,
309 krb5_data_free(&data
);
311 ASN1_MALLOC_ENCODE(DigestREQ
, data
.data
, data
.length
,
314 krb5_set_error_message(context
, ret
,
315 N_("Failed to encode DigestREQest", ""));
318 if (size
!= data
.length
)
319 krb5_abortx(context
, "ASN.1 internal encoder error");
321 ret
= krb5_sendto_kdc(context
, &data
, &r
, &data2
);
325 ret
= decode_DigestREP(data2
.data
, data2
.length
, &rep
, NULL
);
327 krb5_set_error_message(context
, ret
,
328 N_("Failed to parse digest response", ""));
333 krb5_ap_rep_enc_part
*repl
;
335 ret
= krb5_rd_rep(context
, ac
, &rep
.apRep
, &repl
);
339 krb5_free_ap_rep_enc_part(context
, repl
);
344 ret
= krb5_auth_con_getremotesubkey(context
, ac
, &key
);
349 krb5_set_error_message(context
, ret
,
350 N_("Digest reply has no remote subkey", ""));
354 krb5_crypto_destroy(context
, crypto
);
355 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
356 krb5_free_keyblock (context
, key
);
361 krb5_data_free(&data
);
362 ret
= krb5_decrypt_EncryptedData(context
, crypto
, usage
,
363 &rep
.innerRep
, &data
);
367 ret
= decode_DigestRepInner(data
.data
, data
.length
, irep
, NULL
);
369 krb5_set_error_message(context
, ret
,
370 N_("Failed to decode digest inner reply", ""));
375 if (ccache
== NULL
&& id
)
376 krb5_cc_close(context
, id
);
377 if (realm
== NULL
&& r
)
380 krb5_crypto_destroy(context
, crypto
);
382 krb5_auth_con_free(context
, ac
);
384 krb5_free_principal(context
, principal
);
386 krb5_data_free(&data
);
387 krb5_data_free(&data2
);
389 free_DigestREQ(&req
);
390 free_DigestREP(&rep
);
395 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
396 krb5_digest_init_request(krb5_context context
,
405 memset(&ireq
, 0, sizeof(ireq
));
406 memset(&irep
, 0, sizeof(irep
));
408 if (digest
->init
.type
== NULL
) {
409 krb5_set_error_message(context
, EINVAL
,
410 N_("Type missing from init req", ""));
414 ireq
.element
= choice_DigestReqInner_init
;
415 ireq
.u
.init
= digest
->init
;
417 ret
= digest_request(context
, realm
, ccache
,
418 KRB5_KU_DIGEST_ENCRYPT
, &ireq
, &irep
);
422 if (irep
.element
== choice_DigestRepInner_error
) {
423 ret
= irep
.u
.error
.code
;
424 krb5_set_error_message(context
, ret
, N_("Digest init error: %s", ""),
425 irep
.u
.error
.reason
);
429 if (irep
.element
!= choice_DigestRepInner_initReply
) {
431 krb5_set_error_message(context
, ret
,
432 N_("digest reply not an initReply", ""));
436 ret
= copy_DigestInitReply(&irep
.u
.initReply
, &digest
->initReply
);
438 krb5_set_error_message(context
, ret
,
439 N_("Failed to copy initReply", ""));
444 free_DigestRepInner(&irep
);
450 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
451 krb5_digest_set_client_nonce(krb5_context context
,
455 if (digest
->request
.clientNonce
) {
456 krb5_set_error_message(context
, EINVAL
,
457 N_("clientNonce already set", ""));
460 digest
->request
.clientNonce
=
461 calloc(1, sizeof(*digest
->request
.clientNonce
));
462 if (digest
->request
.clientNonce
== NULL
)
463 return krb5_enomem(context
);
464 *digest
->request
.clientNonce
= strdup(nonce
);
465 if (*digest
->request
.clientNonce
== NULL
) {
466 free(digest
->request
.clientNonce
);
467 digest
->request
.clientNonce
= NULL
;
468 return krb5_enomem(context
);
473 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
474 krb5_digest_set_digest(krb5_context context
,
478 if (digest
->request
.digest
) {
479 krb5_set_error_message(context
, EINVAL
,
480 N_("digest already set", ""));
483 digest
->request
.digest
= strdup(dgst
);
484 if (digest
->request
.digest
== NULL
)
485 return krb5_enomem(context
);
489 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
490 krb5_digest_set_username(krb5_context context
,
492 const char *username
)
494 if (digest
->request
.username
) {
495 krb5_set_error_message(context
, EINVAL
, "username already set");
498 digest
->request
.username
= strdup(username
);
499 if (digest
->request
.username
== NULL
)
500 return krb5_enomem(context
);
504 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
505 krb5_digest_set_authid(krb5_context context
,
509 if (digest
->request
.authid
) {
510 krb5_set_error_message(context
, EINVAL
, "authid already set");
513 digest
->request
.authid
= malloc(sizeof(*digest
->request
.authid
));
514 if (digest
->request
.authid
== NULL
)
515 return krb5_enomem(context
);
516 *digest
->request
.authid
= strdup(authid
);
517 if (*digest
->request
.authid
== NULL
) {
518 free(digest
->request
.authid
);
519 digest
->request
.authid
= NULL
;
520 return krb5_enomem(context
);
525 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
526 krb5_digest_set_authentication_user(krb5_context context
,
528 krb5_principal authentication_user
)
532 if (digest
->request
.authentication_user
) {
533 krb5_set_error_message(context
, EINVAL
,
534 N_("authentication_user already set", ""));
537 ret
= krb5_copy_principal(context
,
539 &digest
->request
.authentication_user
);
545 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
546 krb5_digest_set_realm(krb5_context context
,
550 if (digest
->request
.realm
) {
551 krb5_set_error_message(context
, EINVAL
, "realm already set");
554 digest
->request
.realm
= malloc(sizeof(*digest
->request
.realm
));
555 if (digest
->request
.realm
== NULL
)
556 return krb5_enomem(context
);
557 *digest
->request
.realm
= strdup(realm
);
558 if (*digest
->request
.realm
== NULL
) {
559 free(digest
->request
.realm
);
560 digest
->request
.realm
= NULL
;
561 return krb5_enomem(context
);
566 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
567 krb5_digest_set_method(krb5_context context
,
571 if (digest
->request
.method
) {
572 krb5_set_error_message(context
, EINVAL
,
573 N_("method already set", ""));
576 digest
->request
.method
= malloc(sizeof(*digest
->request
.method
));
577 if (digest
->request
.method
== NULL
)
578 return krb5_enomem(context
);
579 *digest
->request
.method
= strdup(method
);
580 if (*digest
->request
.method
== NULL
) {
581 free(digest
->request
.method
);
582 digest
->request
.method
= NULL
;
583 return krb5_enomem(context
);
588 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
589 krb5_digest_set_uri(krb5_context context
,
593 if (digest
->request
.uri
) {
594 krb5_set_error_message(context
, EINVAL
, N_("uri already set", ""));
597 digest
->request
.uri
= malloc(sizeof(*digest
->request
.uri
));
598 if (digest
->request
.uri
== NULL
)
599 return krb5_enomem(context
);
600 *digest
->request
.uri
= strdup(uri
);
601 if (*digest
->request
.uri
== NULL
) {
602 free(digest
->request
.uri
);
603 digest
->request
.uri
= NULL
;
604 return krb5_enomem(context
);
609 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
610 krb5_digest_set_nonceCount(krb5_context context
,
612 const char *nonce_count
)
614 if (digest
->request
.nonceCount
) {
615 krb5_set_error_message(context
, EINVAL
,
616 N_("nonceCount already set", ""));
619 digest
->request
.nonceCount
=
620 malloc(sizeof(*digest
->request
.nonceCount
));
621 if (digest
->request
.nonceCount
== NULL
)
622 return krb5_enomem(context
);
623 *digest
->request
.nonceCount
= strdup(nonce_count
);
624 if (*digest
->request
.nonceCount
== NULL
) {
625 free(digest
->request
.nonceCount
);
626 digest
->request
.nonceCount
= NULL
;
627 return krb5_enomem(context
);
632 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
633 krb5_digest_set_qop(krb5_context context
,
637 if (digest
->request
.qop
) {
638 krb5_set_error_message(context
, EINVAL
, "qop already set");
641 digest
->request
.qop
= malloc(sizeof(*digest
->request
.qop
));
642 if (digest
->request
.qop
== NULL
)
643 return krb5_enomem(context
);
644 *digest
->request
.qop
= strdup(qop
);
645 if (*digest
->request
.qop
== NULL
) {
646 free(digest
->request
.qop
);
647 digest
->request
.qop
= NULL
;
648 return krb5_enomem(context
);
653 KRB5_LIB_FUNCTION
int KRB5_LIB_CALL
654 krb5_digest_set_responseData(krb5_context context
,
656 const char *response
)
658 digest
->request
.responseData
= strdup(response
);
659 if (digest
->request
.responseData
== NULL
)
660 return krb5_enomem(context
);
664 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
665 krb5_digest_request(krb5_context context
,
674 memset(&ireq
, 0, sizeof(ireq
));
675 memset(&irep
, 0, sizeof(irep
));
677 ireq
.element
= choice_DigestReqInner_digestRequest
;
678 ireq
.u
.digestRequest
= digest
->request
;
680 if (digest
->request
.type
== NULL
) {
681 if (digest
->init
.type
== NULL
) {
682 krb5_set_error_message(context
, EINVAL
,
683 N_("Type missing from req", ""));
686 ireq
.u
.digestRequest
.type
= digest
->init
.type
;
689 if (ireq
.u
.digestRequest
.digest
== NULL
) {
690 static char md5
[] = "md5";
691 ireq
.u
.digestRequest
.digest
= md5
;
694 ret
= digest_request(context
, realm
, ccache
,
695 KRB5_KU_DIGEST_ENCRYPT
, &ireq
, &irep
);
699 if (irep
.element
== choice_DigestRepInner_error
) {
700 ret
= irep
.u
.error
.code
;
701 krb5_set_error_message(context
, ret
,
702 N_("Digest response error: %s", ""),
703 irep
.u
.error
.reason
);
707 if (irep
.element
!= choice_DigestRepInner_response
) {
708 krb5_set_error_message(context
, EINVAL
,
709 N_("digest reply not an DigestResponse", ""));
714 ret
= copy_DigestResponse(&irep
.u
.response
, &digest
->response
);
716 krb5_set_error_message(context
, ret
,
717 N_("Failed to copy initReply,", ""));
722 free_DigestRepInner(&irep
);
727 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
728 krb5_digest_rep_get_status(krb5_context context
,
731 return digest
->response
.success
? TRUE
: FALSE
;
734 KRB5_LIB_FUNCTION
const char * KRB5_LIB_CALL
735 krb5_digest_get_rsp(krb5_context context
,
738 if (digest
->response
.rsp
== NULL
)
740 return *digest
->response
.rsp
;
743 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
744 krb5_digest_get_tickets(krb5_context context
,
753 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
754 krb5_digest_get_client_binding(krb5_context context
,
759 if (digest
->response
.channel
) {
760 *type
= strdup(digest
->response
.channel
->cb_type
);
761 *binding
= strdup(digest
->response
.channel
->cb_binding
);
762 if (*type
== NULL
|| *binding
== NULL
) {
765 return krb5_enomem(context
);
774 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
775 krb5_digest_get_session_key(krb5_context context
,
781 krb5_data_zero(data
);
782 if (digest
->response
.session_key
== NULL
)
784 ret
= der_copy_octet_string(digest
->response
.session_key
, data
);
786 krb5_clear_error_message(context
);
791 struct krb5_ntlm_data
{
793 NTLMInitReply initReply
;
795 NTLMResponse response
;
798 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
799 krb5_ntlm_alloc(krb5_context context
,
802 *ntlm
= calloc(1, sizeof(**ntlm
));
804 return krb5_enomem(context
);
808 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
809 krb5_ntlm_free(krb5_context context
, krb5_ntlm ntlm
)
811 free_NTLMInit(&ntlm
->init
);
812 free_NTLMInitReply(&ntlm
->initReply
);
813 free_NTLMRequest(&ntlm
->request
);
814 free_NTLMResponse(&ntlm
->response
);
815 memset(ntlm
, 0, sizeof(*ntlm
));
821 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
822 krb5_ntlm_init_request(krb5_context context
,
827 const char *hostname
,
828 const char *domainname
)
834 memset(&ireq
, 0, sizeof(ireq
));
835 memset(&irep
, 0, sizeof(irep
));
837 ntlm
->init
.flags
= flags
;
839 ALLOC(ntlm
->init
.hostname
, 1);
840 *ntlm
->init
.hostname
= strdup(hostname
);
843 ALLOC(ntlm
->init
.domain
, 1);
844 *ntlm
->init
.domain
= strdup(domainname
);
847 ireq
.element
= choice_DigestReqInner_ntlmInit
;
848 ireq
.u
.ntlmInit
= ntlm
->init
;
850 ret
= digest_request(context
, realm
, ccache
,
851 KRB5_KU_DIGEST_ENCRYPT
, &ireq
, &irep
);
855 if (irep
.element
== choice_DigestRepInner_error
) {
856 ret
= irep
.u
.error
.code
;
857 krb5_set_error_message(context
, ret
, N_("Digest init error: %s", ""),
858 irep
.u
.error
.reason
);
862 if (irep
.element
!= choice_DigestRepInner_ntlmInitReply
) {
864 krb5_set_error_message(context
, ret
,
865 N_("ntlm reply not an initReply", ""));
869 ret
= copy_NTLMInitReply(&irep
.u
.ntlmInitReply
, &ntlm
->initReply
);
871 krb5_set_error_message(context
, ret
,
872 N_("Failed to copy initReply", ""));
877 free_DigestRepInner(&irep
);
882 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
883 krb5_ntlm_init_get_flags(krb5_context context
,
887 *flags
= ntlm
->initReply
.flags
;
891 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
892 krb5_ntlm_init_get_challenge(krb5_context context
,
894 krb5_data
*challenge
)
898 ret
= der_copy_octet_string(&ntlm
->initReply
.challenge
, challenge
);
900 krb5_clear_error_message(context
);
905 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
906 krb5_ntlm_init_get_opaque(krb5_context context
,
912 ret
= der_copy_octet_string(&ntlm
->initReply
.opaque
, opaque
);
914 krb5_clear_error_message(context
);
919 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
920 krb5_ntlm_init_get_targetname(krb5_context context
,
924 *name
= strdup(ntlm
->initReply
.targetname
);
926 return krb5_enomem(context
);
930 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
931 krb5_ntlm_init_get_targetinfo(krb5_context context
,
937 if (ntlm
->initReply
.targetinfo
== NULL
) {
938 krb5_data_zero(data
);
942 ret
= krb5_data_copy(data
,
943 ntlm
->initReply
.targetinfo
->data
,
944 ntlm
->initReply
.targetinfo
->length
);
946 krb5_clear_error_message(context
);
953 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
954 krb5_ntlm_request(krb5_context context
,
963 memset(&ireq
, 0, sizeof(ireq
));
964 memset(&irep
, 0, sizeof(irep
));
966 ireq
.element
= choice_DigestReqInner_ntlmRequest
;
967 ireq
.u
.ntlmRequest
= ntlm
->request
;
969 ret
= digest_request(context
, realm
, ccache
,
970 KRB5_KU_DIGEST_ENCRYPT
, &ireq
, &irep
);
974 if (irep
.element
== choice_DigestRepInner_error
) {
975 ret
= irep
.u
.error
.code
;
976 krb5_set_error_message(context
, ret
,
977 N_("NTLM response error: %s", ""),
978 irep
.u
.error
.reason
);
982 if (irep
.element
!= choice_DigestRepInner_ntlmResponse
) {
984 krb5_set_error_message(context
, ret
,
985 N_("NTLM reply not an NTLMResponse", ""));
989 ret
= copy_NTLMResponse(&irep
.u
.ntlmResponse
, &ntlm
->response
);
991 krb5_set_error_message(context
, ret
,
992 N_("Failed to copy NTLMResponse", ""));
997 free_DigestRepInner(&irep
);
1002 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1003 krb5_ntlm_req_set_flags(krb5_context context
,
1007 ntlm
->request
.flags
= flags
;
1011 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1012 krb5_ntlm_req_set_username(krb5_context context
,
1014 const char *username
)
1016 ntlm
->request
.username
= strdup(username
);
1017 if (ntlm
->request
.username
== NULL
)
1018 return krb5_enomem(context
);
1022 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1023 krb5_ntlm_req_set_targetname(krb5_context context
,
1025 const char *targetname
)
1027 ntlm
->request
.targetname
= strdup(targetname
);
1028 if (ntlm
->request
.targetname
== NULL
)
1029 return krb5_enomem(context
);
1033 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1034 krb5_ntlm_req_set_lm(krb5_context context
,
1036 void *hash
, size_t len
)
1038 ntlm
->request
.lm
.data
= malloc(len
);
1039 if (ntlm
->request
.lm
.data
== NULL
&& len
!= 0)
1040 return krb5_enomem(context
);
1041 ntlm
->request
.lm
.length
= len
;
1042 memcpy(ntlm
->request
.lm
.data
, hash
, len
);
1046 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1047 krb5_ntlm_req_set_ntlm(krb5_context context
,
1049 void *hash
, size_t len
)
1051 ntlm
->request
.ntlm
.data
= malloc(len
);
1052 if (ntlm
->request
.ntlm
.data
== NULL
&& len
!= 0)
1053 return krb5_enomem(context
);
1054 ntlm
->request
.ntlm
.length
= len
;
1055 memcpy(ntlm
->request
.ntlm
.data
, hash
, len
);
1059 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1060 krb5_ntlm_req_set_opaque(krb5_context context
,
1064 ntlm
->request
.opaque
.data
= malloc(opaque
->length
);
1065 if (ntlm
->request
.opaque
.data
== NULL
&& opaque
->length
!= 0)
1066 return krb5_enomem(context
);
1067 ntlm
->request
.opaque
.length
= opaque
->length
;
1068 memcpy(ntlm
->request
.opaque
.data
, opaque
->data
, opaque
->length
);
1072 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1073 krb5_ntlm_req_set_session(krb5_context context
,
1075 void *sessionkey
, size_t length
)
1077 ntlm
->request
.sessionkey
= calloc(1, sizeof(*ntlm
->request
.sessionkey
));
1078 if (ntlm
->request
.sessionkey
== NULL
)
1079 return krb5_enomem(context
);
1080 ntlm
->request
.sessionkey
->data
= malloc(length
);
1081 if (ntlm
->request
.sessionkey
->data
== NULL
&& length
!= 0)
1082 return krb5_enomem(context
);
1083 memcpy(ntlm
->request
.sessionkey
->data
, sessionkey
, length
);
1084 ntlm
->request
.sessionkey
->length
= length
;
1088 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1089 krb5_ntlm_rep_get_status(krb5_context context
,
1092 return ntlm
->response
.success
? TRUE
: FALSE
;
1095 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1096 krb5_ntlm_rep_get_sessionkey(krb5_context context
,
1100 if (ntlm
->response
.sessionkey
== NULL
) {
1101 krb5_set_error_message(context
, EINVAL
,
1102 N_("no ntlm session key", ""));
1105 krb5_clear_error_message(context
);
1106 return krb5_data_copy(data
,
1107 ntlm
->response
.sessionkey
->data
,
1108 ntlm
->response
.sessionkey
->length
);
1112 * Get the supported/allowed mechanism for this principal.
1114 * @param context A Keberos context.
1115 * @param realm The realm of the KDC.
1116 * @param ccache The credential cache to use when talking to the KDC.
1117 * @param flags The supported mechanism.
1119 * @return Return an error code or 0.
1121 * @ingroup krb5_digest
1124 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1125 krb5_digest_probe(krb5_context context
,
1130 DigestReqInner ireq
;
1131 DigestRepInner irep
;
1132 krb5_error_code ret
;
1134 memset(&ireq
, 0, sizeof(ireq
));
1135 memset(&irep
, 0, sizeof(irep
));
1137 ireq
.element
= choice_DigestReqInner_supportedMechs
;
1139 ret
= digest_request(context
, realm
, ccache
,
1140 KRB5_KU_DIGEST_ENCRYPT
, &ireq
, &irep
);
1144 if (irep
.element
== choice_DigestRepInner_error
) {
1145 ret
= irep
.u
.error
.code
;
1146 krb5_set_error_message(context
, ret
, "Digest probe error: %s",
1147 irep
.u
.error
.reason
);
1151 if (irep
.element
!= choice_DigestRepInner_supportedMechs
) {
1153 krb5_set_error_message(context
, ret
, "Digest reply not an probe");
1157 *flags
= DigestTypes2int(irep
.u
.supportedMechs
);
1160 free_DigestRepInner(&irep
);
1165 #endif /* HEIMDAL_SMALLER */