2 * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include "krb5_locl.h"
44 krb5_init_etype (krb5_context context
,
47 const krb5_enctype
*etypes
)
55 tmp
= (krb5_enctype
*)etypes
;
57 ret
= krb5_get_default_in_tkt_etypes(context
,
63 for (i
= 0; tmp
[i
]; ++i
)
66 *val
= malloc(i
* sizeof(unsigned));
81 static krb5_error_code
82 decrypt_tkt (krb5_context context
,
83 const krb5_keyblock
*key
,
84 krb5_const_pointer decrypt_arg
,
85 krb5_kdc_rep
*dec_rep
)
91 ret
= krb5_decrypt (context
,
92 dec_rep
->part1
.enc_part
.cipher
.data
,
93 dec_rep
->part1
.enc_part
.cipher
.length
,
94 dec_rep
->part1
.enc_part
.etype
,
100 ret
= decode_EncASRepPart(data
.data
,
105 ret
= decode_EncTGSRepPart(data
.data
,
109 krb5_data_free (&data
);
115 _krb5_extract_ticket(krb5_context context
,
119 krb5_const_pointer keyseed
,
120 krb5_addresses
*addrs
,
122 krb5_boolean allow_server_mismatch
,
123 krb5_decrypt_proc decrypt_proc
,
124 krb5_const_pointer decryptarg
)
127 krb5_principal tmp_principal
;
134 err
= principalname2krb5_principal (&tmp_principal
,
139 tmp
= krb5_principal_compare (context
, tmp_principal
, creds
->client
);
140 krb5_free_principal (context
, tmp_principal
);
142 err
= KRB5KRB_AP_ERR_MODIFIED
;
148 unsigned char buf
[1024];
150 encode_Ticket(buf
+ sizeof(buf
) - 1, sizeof(buf
),
151 &rep
->part1
.ticket
, &len
);
152 creds
->ticket
.data
= malloc(len
);
153 memcpy(creds
->ticket
.data
, buf
+ sizeof(buf
) - len
, len
);
154 creds
->ticket
.length
= len
;
155 creds
->second_ticket
.length
= 0;
156 creds
->second_ticket
.data
= NULL
;
161 err
= principalname2krb5_principal (&tmp_principal
,
162 rep
->part1
.ticket
.sname
,
163 rep
->part1
.ticket
.realm
);
166 if(allow_server_mismatch
){
167 krb5_free_principal(context
, creds
->server
);
168 creds
->server
= tmp_principal
;
169 tmp_principal
= NULL
;
171 tmp
= krb5_principal_compare (context
, tmp_principal
, creds
->server
);
172 krb5_free_principal (context
, tmp_principal
);
174 err
= KRB5KRB_AP_ERR_MODIFIED
;
181 if (decrypt_proc
== NULL
)
182 decrypt_proc
= decrypt_tkt
;
184 err
= (*decrypt_proc
)(context
, key
, decryptarg
, rep
);
190 if (nonce
!= rep
->part2
.nonce
) {
191 err
= KRB5KRB_AP_ERR_MODIFIED
;
197 krb5_timeofday (context
, &sec_now
);
198 if (context
->kdc_sec_offset
== 0
199 && krb5_config_get_bool (context
->cf
,
203 context
->kdc_sec_offset
= rep
->part2
.authtime
- sec_now
;
204 krb5_timeofday (context
, &sec_now
);
207 /* check all times */
209 if (rep
->part2
.starttime
) {
210 tmp_time
= *rep
->part2
.starttime
;
212 tmp_time
= rep
->part2
.authtime
;
214 if (creds
->times
.starttime
== 0
215 && abs(tmp_time
- sec_now
) > context
->max_skew
) {
216 err
= KRB5KRB_AP_ERR_MODIFIED
;
220 if (creds
->times
.starttime
!= 0
221 && tmp_time
!= creds
->times
.starttime
) {
222 err
= KRB5KRB_AP_ERR_MODIFIED
;
226 creds
->times
.starttime
= tmp_time
;
228 if (rep
->part2
.renew_till
) {
229 tmp_time
= *rep
->part2
.renew_till
;
233 if (creds
->times
.renew_till
!= 0
234 && tmp_time
> creds
->times
.renew_till
) {
235 err
= KRB5KRB_AP_ERR_MODIFIED
;
239 creds
->times
.renew_till
= tmp_time
;
241 creds
->times
.authtime
= rep
->part2
.authtime
;
243 if (creds
->times
.endtime
!= 0
244 && rep
->part2
.endtime
> creds
->times
.endtime
) {
245 err
= KRB5KRB_AP_ERR_MODIFIED
;
249 creds
->times
.endtime
= rep
->part2
.endtime
;
252 krb5_copy_addresses (context
, rep
->part2
.caddr
, &creds
->addresses
);
254 krb5_copy_addresses (context
, addrs
, &creds
->addresses
);
256 creds
->addresses
.len
= 0;
257 creds
->addresses
.val
= NULL
;
259 creds
->flags
.b
= rep
->part2
.flags
;
261 creds
->authdata
.length
= 0;
262 creds
->authdata
.data
= NULL
;
263 creds
->session
.keyvalue
.length
= 0;
264 creds
->session
.keyvalue
.data
= NULL
;
265 creds
->session
.keytype
= rep
->part2
.key
.keytype
;
266 err
= krb5_data_copy (&creds
->session
.keyvalue
,
267 rep
->part2
.key
.keyvalue
.data
,
268 rep
->part2
.key
.keyvalue
.length
);
271 memset (rep
->part2
.key
.keyvalue
.data
, 0,
272 rep
->part2
.key
.keyvalue
.length
);
277 static krb5_error_code
278 make_pa_enc_timestamp(krb5_context context
, PA_DATA
*pa
,
279 krb5_enctype etype
, krb5_keyblock
*key
)
284 EncryptedData encdata
;
289 krb5_us_timeofday (context
, &sec
, &usec
);
294 ret
= encode_PA_ENC_TS_ENC(buf
+ sizeof(buf
) - 1,
301 ret
= krb5_encrypt_EncryptedData(context
,
302 buf
+ sizeof(buf
) - len
,
311 ret
= encode_EncryptedData(buf
+ sizeof(buf
) - 1,
315 free_EncryptedData(&encdata
);
318 pa
->padata_type
= pa_enc_timestamp
;
319 pa
->padata_value
.length
= 0;
320 krb5_data_copy(&pa
->padata_value
,
321 buf
+ sizeof(buf
) - len
,
326 static krb5_error_code
327 init_as_req (krb5_context context
,
330 const krb5_addresses
*addrs
,
331 const krb5_enctype
*etypes
,
332 const krb5_preauthtype
*ptypes
,
333 krb5_key_proc key_proc
,
334 krb5_const_pointer keyseed
,
343 memset(a
, 0, sizeof(*a
));
346 a
->msg_type
= krb_as_req
;
347 a
->req_body
.kdc_options
= opts
.b
;
348 a
->req_body
.cname
= malloc(sizeof(*a
->req_body
.cname
));
349 if (a
->req_body
.cname
== NULL
) {
353 a
->req_body
.sname
= malloc(sizeof(*a
->req_body
.sname
));
354 if (a
->req_body
.sname
== NULL
) {
358 ret
= krb5_principal2principalname (a
->req_body
.cname
, creds
->client
);
361 ret
= krb5_principal2principalname (a
->req_body
.sname
, creds
->server
);
364 ret
= copy_Realm(&creds
->client
->realm
, &a
->req_body
.realm
);
368 if(creds
->times
.starttime
) {
369 a
->req_body
.from
= malloc(sizeof(*a
->req_body
.from
));
370 if (a
->req_body
.from
== NULL
) {
374 *a
->req_body
.from
= creds
->times
.starttime
;
376 if(creds
->times
.endtime
){
377 ALLOC(a
->req_body
.till
, 1);
378 *a
->req_body
.till
= creds
->times
.endtime
;
380 if(creds
->times
.renew_till
){
381 a
->req_body
.rtime
= malloc(sizeof(*a
->req_body
.rtime
));
382 if (a
->req_body
.rtime
== NULL
) {
386 *a
->req_body
.rtime
= creds
->times
.renew_till
;
388 a
->req_body
.nonce
= nonce
;
389 ret
= krb5_init_etype (context
,
390 &a
->req_body
.etype
.len
,
391 &a
->req_body
.etype
.val
,
396 etype
= a
->req_body
.etype
.val
[0]; /* XXX */
398 a
->req_body
.addresses
= malloc(sizeof(*a
->req_body
.addresses
));
399 if (a
->req_body
.addresses
== NULL
) {
405 ret
= krb5_copy_addresses(context
, addrs
, a
->req_body
.addresses
);
407 ret
= krb5_get_all_client_addrs (a
->req_body
.addresses
);
411 a
->req_body
.enc_authorization_data
= NULL
;
412 a
->req_body
.additional_tickets
= NULL
;
414 /* not sure this is the way to use `ptypes' */
415 if (ptypes
== NULL
|| *ptypes
== KRB5_PADATA_NONE
)
417 else if (*ptypes
== KRB5_PADATA_ENC_TIMESTAMP
) {
418 a
->padata
= malloc(sizeof(*a
->padata
));
419 if (a
->padata
== NULL
) {
425 a
->padata
->val
= calloc(a
->padata
->len
, sizeof(*a
->padata
->val
));
426 if (a
->padata
->val
== NULL
) {
431 /* make a v5 salted pa-data */
434 ret
= krb5_get_salt (creds
->client
, &salt
);
440 krb5_keytype keytype
;
441 ret
= krb5_etype_to_keytype(context
, etype
, &keytype
);
443 krb5_data_free(&salt
);
446 ret
= (*key_proc
)(context
, keytype
, &salt
, keyseed
, &key
);
447 krb5_data_free (&salt
);
451 ret
= make_pa_enc_timestamp(context
, &a
->padata
->val
[0], etype
, key
);
452 krb5_free_keyblock_contents (context
, key
);
456 /* make a v4 salted pa-data */
460 krb5_keytype keytype
;
461 ret
= krb5_etype_to_keytype(context
, etype
, &keytype
);
464 ret
= (*key_proc
)(context
, keytype
, &salt
, keyseed
, &key
);
468 ret
= make_pa_enc_timestamp(context
, &a
->padata
->val
[1], etype
, key
);
469 krb5_free_keyblock_contents (context
, key
);
474 ret
= KRB5_PREAUTH_BAD_TYPE
;
484 krb5_get_in_cred(krb5_context context
,
486 const krb5_addresses
*addrs
,
487 const krb5_enctype
*etypes
,
488 const krb5_preauthtype
*ptypes
,
489 krb5_key_proc key_proc
,
490 krb5_const_pointer keyseed
,
491 krb5_decrypt_proc decrypt_proc
,
492 krb5_const_pointer decryptarg
,
494 krb5_kdc_rep
*ret_as_reply
)
511 krb5_generate_random_block (&nonce
, sizeof(nonce
));
514 ret
= init_as_req (context
,
527 ret
= encode_AS_REQ ((unsigned char*)buf
+ sizeof(buf
) - 1,
535 req
.data
= buf
+ sizeof(buf
) - req
.length
;
537 ret
= krb5_sendto_kdc (context
, &req
, &creds
->client
->realm
, &resp
);
541 memset (&rep
, 0, sizeof(rep
));
542 if((ret
= decode_AS_REP(resp
.data
, resp
.length
, &rep
.part1
, &size
))){
543 /* let's try to parse it as a KRB-ERROR */
547 ret2
= krb5_rd_error(context
, &resp
, &error
);
548 if(ret2
&& resp
.data
&& ((char*)resp
.data
)[0] == 4)
549 ret
= KRB5KRB_AP_ERR_V4_REPLY
;
550 krb5_data_free(&resp
);
552 /* XXX - send krb-error packet to caller */
553 free_KRB_ERROR (&error
);
554 return error
.error_code
;
558 krb5_data_free(&resp
);
561 etype
= rep
.part1
.enc_part
.etype
;
562 if(rep
.part1
.padata
){
564 pa
= krb5_find_padata(rep
.part1
.padata
->val
, rep
.part1
.padata
->len
,
568 krb5_keytype keytype
;
569 ret
= krb5_etype_to_keytype(context
, etype
, &keytype
);
570 ret
= (*key_proc
)(context
, keytype
, &pa
->padata_value
, keyseed
, &key
);
572 /* make a v5 salted pa-data */
573 krb5_keytype keytype
;
576 ret
= krb5_get_salt (creds
->client
, &salt
);
580 ret
= krb5_etype_to_keytype(context
, etype
, &keytype
);
581 ret
= (*key_proc
)(context
, keytype
, &salt
, keyseed
, &key
);
582 krb5_data_free (&salt
);
587 ret
= _krb5_extract_ticket(context
, &rep
, creds
, key
, keyseed
,
588 NULL
, nonce
, FALSE
, decrypt_proc
, decryptarg
);
589 memset (key
->keyvalue
.data
, 0, key
->keyvalue
.length
);
590 krb5_free_keyblock_contents (context
, key
);
593 if (ret
== 0 && ret_as_reply
)
596 krb5_free_kdc_rep (context
, &rep
);
601 krb5_get_in_tkt(krb5_context context
,
603 const krb5_addresses
*addrs
,
604 const krb5_enctype
*etypes
,
605 const krb5_preauthtype
*ptypes
,
606 krb5_key_proc key_proc
,
607 krb5_const_pointer keyseed
,
608 krb5_decrypt_proc decrypt_proc
,
609 krb5_const_pointer decryptarg
,
612 krb5_kdc_rep
*ret_as_reply
)
617 opts
.b
= int2KDCOptions(options
);
619 ret
= krb5_get_in_cred (context
,
632 ret
= krb5_cc_store_cred (context
, ccache
, creds
);
633 krb5_free_creds_contents (context
, creds
);