2 * Copyright (c) 1997 - 2008 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"
36 #ifndef HEIMDAL_SMALLER
38 static krb5_error_code
39 make_pa_enc_timestamp(krb5_context context
, PA_DATA
*pa
,
40 krb5_enctype etype
, krb5_keyblock
*key
)
46 EncryptedData encdata
;
52 krb5_us_timeofday (context
, &p
.patimestamp
, &usec
);
56 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC
, buf
, buf_size
, &p
, &len
, ret
);
60 krb5_abortx(context
, "internal error in ASN.1 encoder");
61 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
66 ret
= krb5_encrypt_EncryptedData(context
,
68 KRB5_KU_PA_ENC_TIMESTAMP
,
74 krb5_crypto_destroy(context
, crypto
);
78 ASN1_MALLOC_ENCODE(EncryptedData
, buf
, buf_size
, &encdata
, &len
, ret
);
79 free_EncryptedData(&encdata
);
83 krb5_abortx(context
, "internal error in ASN.1 encoder");
84 pa
->padata_type
= KRB5_PADATA_ENC_TIMESTAMP
;
85 pa
->padata_value
.length
= len
;
86 pa
->padata_value
.data
= buf
;
90 static krb5_error_code
91 add_padata(krb5_context context
,
93 krb5_principal client
,
94 krb5_key_proc key_proc
,
95 krb5_const_pointer keyseed
,
96 krb5_enctype
*enctypes
,
107 /* default to standard salt */
108 ret
= krb5_get_pw_salt (context
, client
, &salt2
);
114 enctypes
= context
->etypes
;
116 for (ep
= enctypes
; *ep
!= ETYPE_NULL
; ep
++)
119 pa2
= realloc (md
->val
, (md
->len
+ netypes
) * sizeof(*md
->val
));
121 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
126 for (i
= 0; i
< netypes
; ++i
) {
129 ret
= (*key_proc
)(context
, enctypes
[i
], *salt
, keyseed
, &key
);
132 ret
= make_pa_enc_timestamp (context
, &md
->val
[md
->len
],
134 krb5_free_keyblock (context
, key
);
140 krb5_free_salt(context
, salt2
);
144 static krb5_error_code
145 init_as_req (krb5_context context
,
148 const krb5_addresses
*addrs
,
149 const krb5_enctype
*etypes
,
150 const krb5_preauthtype
*ptypes
,
151 const krb5_preauthdata
*preauth
,
152 krb5_key_proc key_proc
,
153 krb5_const_pointer keyseed
,
160 memset(a
, 0, sizeof(*a
));
163 a
->msg_type
= krb_as_req
;
164 a
->req_body
.kdc_options
= opts
;
165 a
->req_body
.cname
= malloc(sizeof(*a
->req_body
.cname
));
166 if (a
->req_body
.cname
== NULL
) {
168 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
171 a
->req_body
.sname
= malloc(sizeof(*a
->req_body
.sname
));
172 if (a
->req_body
.sname
== NULL
) {
174 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
177 ret
= _krb5_principal2principalname (a
->req_body
.cname
, creds
->client
);
180 ret
= _krb5_principal2principalname (a
->req_body
.sname
, creds
->server
);
183 ret
= copy_Realm(&creds
->client
->realm
, &a
->req_body
.realm
);
187 if(creds
->times
.starttime
) {
188 a
->req_body
.from
= malloc(sizeof(*a
->req_body
.from
));
189 if (a
->req_body
.from
== NULL
) {
191 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
194 *a
->req_body
.from
= creds
->times
.starttime
;
196 if(creds
->times
.endtime
){
197 ALLOC(a
->req_body
.till
, 1);
198 *a
->req_body
.till
= creds
->times
.endtime
;
200 if(creds
->times
.renew_till
){
201 a
->req_body
.rtime
= malloc(sizeof(*a
->req_body
.rtime
));
202 if (a
->req_body
.rtime
== NULL
) {
204 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
207 *a
->req_body
.rtime
= creds
->times
.renew_till
;
209 a
->req_body
.nonce
= nonce
;
210 ret
= _krb5_init_etype(context
,
212 &a
->req_body
.etype
.len
,
213 &a
->req_body
.etype
.val
,
219 * This means no addresses
222 if (addrs
&& addrs
->len
== 0) {
223 a
->req_body
.addresses
= NULL
;
225 a
->req_body
.addresses
= malloc(sizeof(*a
->req_body
.addresses
));
226 if (a
->req_body
.addresses
== NULL
) {
228 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
233 ret
= krb5_copy_addresses(context
, addrs
, a
->req_body
.addresses
);
235 ret
= krb5_get_all_client_addrs (context
, a
->req_body
.addresses
);
236 if(ret
== 0 && a
->req_body
.addresses
->len
== 0) {
237 free(a
->req_body
.addresses
);
238 a
->req_body
.addresses
= NULL
;
245 a
->req_body
.enc_authorization_data
= NULL
;
246 a
->req_body
.additional_tickets
= NULL
;
248 if(preauth
!= NULL
) {
251 if(a
->padata
== NULL
) {
253 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
256 a
->padata
->val
= NULL
;
258 for(i
= 0; i
< preauth
->len
; i
++) {
259 if(preauth
->val
[i
].type
== KRB5_PADATA_ENC_TIMESTAMP
){
262 for(j
= 0; j
< preauth
->val
[i
].info
.len
; j
++) {
263 krb5_salt
*sp
= &salt
;
264 if(preauth
->val
[i
].info
.val
[j
].salttype
)
265 salt
.salttype
= *preauth
->val
[i
].info
.val
[j
].salttype
;
267 salt
.salttype
= KRB5_PW_SALT
;
268 if(preauth
->val
[i
].info
.val
[j
].salt
)
269 salt
.saltvalue
= *preauth
->val
[i
].info
.val
[j
].salt
;
271 if(salt
.salttype
== KRB5_PW_SALT
)
274 krb5_data_zero(&salt
.saltvalue
);
275 ret
= add_padata(context
, a
->padata
, creds
->client
,
277 &preauth
->val
[i
].info
.val
[j
].etype
, 1,
285 /* not sure this is the way to use `ptypes' */
286 if (ptypes
== NULL
|| *ptypes
== KRB5_PADATA_NONE
)
288 else if (*ptypes
== KRB5_PADATA_ENC_TIMESTAMP
) {
290 if (a
->padata
== NULL
) {
292 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
296 a
->padata
->val
= NULL
;
298 /* make a v5 salted pa-data */
299 add_padata(context
, a
->padata
, creds
->client
,
300 key_proc
, keyseed
, a
->req_body
.etype
.val
,
301 a
->req_body
.etype
.len
, NULL
);
303 /* make a v4 salted pa-data */
304 salt
.salttype
= KRB5_PW_SALT
;
305 krb5_data_zero(&salt
.saltvalue
);
306 add_padata(context
, a
->padata
, creds
->client
,
307 key_proc
, keyseed
, a
->req_body
.etype
.val
,
308 a
->req_body
.etype
.len
, &salt
);
310 ret
= KRB5_PREAUTH_BAD_TYPE
;
311 krb5_set_error_message (context
, ret
,
312 N_("pre-auth type %d not supported", ""),
323 set_ptypes(krb5_context context
,
325 const krb5_preauthtype
**ptypes
,
326 krb5_preauthdata
**preauth
)
328 static krb5_preauthdata preauth2
;
329 static krb5_preauthtype ptypes2
[] = { KRB5_PADATA_ENC_TIMESTAMP
, KRB5_PADATA_NONE
};
334 decode_METHOD_DATA(error
->e_data
->data
,
335 error
->e_data
->length
,
338 for(i
= 0; i
< md
.len
; i
++){
339 switch(md
.val
[i
].padata_type
){
340 case KRB5_PADATA_ENC_TIMESTAMP
:
343 case KRB5_PADATA_ETYPE_INFO
:
344 *preauth
= &preauth2
;
345 ALLOC_SEQ(*preauth
, 1);
346 (*preauth
)->val
[0].type
= KRB5_PADATA_ENC_TIMESTAMP
;
347 decode_ETYPE_INFO(md
.val
[i
].padata_value
.data
,
348 md
.val
[i
].padata_value
.length
,
349 &(*preauth
)->val
[0].info
,
356 free_METHOD_DATA(&md
);
363 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
364 krb5_get_in_cred(krb5_context context
,
366 const krb5_addresses
*addrs
,
367 const krb5_enctype
*etypes
,
368 const krb5_preauthtype
*ptypes
,
369 const krb5_preauthdata
*preauth
,
370 krb5_key_proc key_proc
,
371 krb5_const_pointer keyseed
,
372 krb5_decrypt_proc decrypt_proc
,
373 krb5_const_pointer decryptarg
,
375 krb5_kdc_rep
*ret_as_reply
)
376 KRB5_DEPRECATED_FUNCTION("Use X instead")
389 krb5_preauthdata
*my_preauth
= NULL
;
393 opts
= int2KDCOptions(options
);
395 krb5_generate_random_block (&nonce
, sizeof(nonce
));
400 ret
= init_as_req (context
,
412 free_ETYPE_INFO(&my_preauth
->val
[0].info
);
413 free (my_preauth
->val
);
419 ASN1_MALLOC_ENCODE(AS_REQ
, req
.data
, req
.length
, &a
, &len
, ret
);
423 if(len
!= req
.length
)
424 krb5_abortx(context
, "internal error in ASN.1 encoder");
426 ret
= krb5_sendto_kdc (context
, &req
, &creds
->client
->realm
, &resp
);
427 krb5_data_free(&req
);
431 memset (&rep
, 0, sizeof(rep
));
432 ret
= decode_AS_REP(resp
.data
, resp
.length
, &rep
.kdc_rep
, &size
);
434 /* let's try to parse it as a KRB-ERROR */
438 ret2
= krb5_rd_error(context
, &resp
, &error
);
439 if(ret2
&& resp
.data
&& ((char*)resp
.data
)[0] == 4)
440 ret
= KRB5KRB_AP_ERR_V4_REPLY
;
441 krb5_data_free(&resp
);
443 ret
= krb5_error_from_rd_error(context
, &error
, creds
);
444 /* if no preauth was set and KDC requires it, give it
446 if (!ptypes
&& !preauth
447 && ret
== KRB5KDC_ERR_PREAUTH_REQUIRED
449 || ret
== KRB5KDC_ERR_BADOPTION
451 && set_ptypes(context
, &error
, &ptypes
, &my_preauth
)) {
453 preauth
= my_preauth
;
454 krb5_free_error_contents(context
, &error
);
455 krb5_clear_error_message(context
);
459 ret_as_reply
->error
= error
;
461 free_KRB_ERROR (&error
);
466 krb5_data_free(&resp
);
470 etype
= rep
.kdc_rep
.enc_part
.etype
;
471 if(rep
.kdc_rep
.padata
){
473 pa
= krb5_find_padata(rep
.kdc_rep
.padata
->val
, rep
.kdc_rep
.padata
->len
,
474 KRB5_PADATA_PW_SALT
, &i
);
477 pa
= krb5_find_padata(rep
.kdc_rep
.padata
->val
,
478 rep
.kdc_rep
.padata
->len
,
479 KRB5_PADATA_AFS3_SALT
, &i
);
483 salt
.salttype
= pa
->padata_type
;
484 salt
.saltvalue
= pa
->padata_value
;
486 ret
= (*key_proc
)(context
, etype
, salt
, keyseed
, &key
);
488 /* make a v5 salted pa-data */
489 ret
= krb5_get_pw_salt (context
, creds
->client
, &salt
);
493 ret
= (*key_proc
)(context
, etype
, salt
, keyseed
, &key
);
494 krb5_free_salt(context
, salt
);
500 unsigned flags
= EXTRACT_TICKET_TIMESYNC
;
501 if (opts
.request_anonymous
)
502 flags
|= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
;
504 ret
= _krb5_extract_ticket(context
,
509 KRB5_KU_AS_REP_ENC_PART
,
516 memset (key
->keyvalue
.data
, 0, key
->keyvalue
.length
);
517 krb5_free_keyblock_contents (context
, key
);
521 if (ret
== 0 && ret_as_reply
)
524 krb5_free_kdc_rep (context
, &rep
);
528 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
529 krb5_get_in_tkt(krb5_context context
,
531 const krb5_addresses
*addrs
,
532 const krb5_enctype
*etypes
,
533 const krb5_preauthtype
*ptypes
,
534 krb5_key_proc key_proc
,
535 krb5_const_pointer keyseed
,
536 krb5_decrypt_proc decrypt_proc
,
537 krb5_const_pointer decryptarg
,
540 krb5_kdc_rep
*ret_as_reply
)
541 KRB5_DEPRECATED_FUNCTION("Use X instead")
545 ret
= krb5_get_in_cred (context
,
560 ret
= krb5_cc_store_cred (context
, ccache
, creds
);
564 #endif /* HEIMDAL_SMALLER */