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 typedef struct krb5_get_init_creds_ctx
{
39 krb5_addresses
*addrs
;
41 krb5_preauthtype
*pre_auth_types
;
50 /* password and keytab_data is freed on completion */
52 krb5_keytab_key_proc_args
*keytab_data
;
54 krb5_pointer
*keyseed
;
55 krb5_s2k_proc keyproc
;
57 krb5_get_init_creds_tristate req_pac
;
59 krb5_pk_init_ctx pk_init_ctx
;
65 EncKDCRepPart enc_part
;
67 krb5_prompter_fct prompter
;
70 } krb5_get_init_creds_ctx
;
72 static krb5_error_code
73 default_s2k_func(krb5_context context
, krb5_enctype type
,
74 krb5_const_pointer keyseed
,
75 krb5_salt salt
, krb5_data
*s2kparms
,
82 password
.data
= rk_UNCONST(keyseed
);
83 password
.length
= strlen(keyseed
);
87 krb5_data_zero(&opaque
);
89 *key
= malloc(sizeof(**key
));
92 ret
= krb5_string_to_key_data_salt_opaque(context
, type
, password
,
102 free_init_creds_ctx(krb5_context context
, krb5_init_creds_context ctx
)
106 if (ctx
->pre_auth_types
)
107 free (ctx
->pre_auth_types
);
108 if (ctx
->in_tkt_service
)
109 free(ctx
->in_tkt_service
);
110 if (ctx
->keytab_data
)
111 free(ctx
->keytab_data
);
112 krb5_data_free(&ctx
->req_buffer
);
113 krb5_free_cred_contents(context
, &ctx
->cred
);
114 free_METHOD_DATA(&ctx
->md
);
115 free_AS_REP(&ctx
->as_rep
);
116 free_EncKDCRepPart(&ctx
->enc_part
);
117 free_KRB_ERROR(&ctx
->error
);
118 free_AS_REQ(&ctx
->as_req
);
119 memset(ctx
, 0, sizeof(*ctx
));
123 get_config_time (krb5_context context
,
130 ret
= krb5_config_get_time (context
, NULL
,
137 ret
= krb5_config_get_time (context
, NULL
,
146 static krb5_error_code
147 init_cred (krb5_context context
,
149 krb5_principal client
,
150 krb5_deltat start_time
,
151 krb5_get_init_creds_opt
*options
)
157 krb5_timeofday (context
, &now
);
159 memset (cred
, 0, sizeof(*cred
));
162 krb5_copy_principal(context
, client
, &cred
->client
);
164 ret
= krb5_get_default_principal (context
,
171 cred
->times
.starttime
= now
+ start_time
;
173 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
)
174 tmp
= options
->tkt_life
;
177 cred
->times
.endtime
= now
+ tmp
;
179 if ((options
->flags
& KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE
) &&
180 options
->renew_life
> 0) {
181 cred
->times
.renew_till
= now
+ options
->renew_life
;
187 krb5_free_cred_contents (context
, cred
);
192 * Print a message (str) to the user about the expiration in `lr'
196 report_expiration (krb5_context context
,
197 krb5_prompter_fct prompter
,
204 asprintf (&p
, "%s%s", str
, ctime(&now
));
205 (*prompter
) (context
, data
, NULL
, p
, 0, NULL
);
210 * Check the context, and in the case there is a expiration warning,
211 * use the prompter to print the warning.
213 * @param context A Kerberos 5 context.
214 * @param options An GIC options structure
215 * @param ctx The krb5_init_creds_context check for expiration.
218 static krb5_error_code
219 process_last_request(krb5_context context
,
220 krb5_get_init_creds_opt
*options
,
221 krb5_init_creds_context ctx
)
223 krb5_const_realm realm
;
225 krb5_boolean reported
= FALSE
;
231 * First check if there is a API consumer.
234 realm
= krb5_principal_get_realm (context
, ctx
->cred
.client
);
235 lr
= &ctx
->enc_part
.last_req
;
237 if (options
&& options
->opt_private
&& options
->opt_private
->lr
.func
) {
238 krb5_last_req_entry
**lre
;
240 lre
= calloc(lr
->len
+ 1, sizeof(**lre
));
242 krb5_set_error_message(context
, ENOMEM
,
243 N_("malloc: out of memory", ""));
246 for (i
= 0; i
< lr
->len
; i
++) {
247 lre
[i
] = calloc(1, sizeof(*lre
[i
]));
250 lre
[i
]->lr_type
= lr
->val
[i
].lr_type
;
251 lre
[i
]->value
= lr
->val
[i
].lr_value
;
254 (*options
->opt_private
->lr
.func
)(context
, lre
,
255 options
->opt_private
->lr
.ctx
);
257 for (i
= 0; i
< lr
->len
; i
++)
263 * Now check if we should prompt the user
266 if (ctx
->prompter
== NULL
)
269 krb5_timeofday (context
, &sec
);
271 t
= sec
+ get_config_time (context
,
276 for (i
= 0; i
< lr
->len
; ++i
) {
277 if (lr
->val
[i
].lr_value
<= t
) {
278 switch (abs(lr
->val
[i
].lr_type
)) {
280 report_expiration(context
, ctx
->prompter
,
282 "Your password will expire at ",
283 lr
->val
[i
].lr_value
);
286 case LR_ACCT_EXPTIME
:
287 report_expiration(context
, ctx
->prompter
,
289 "Your account will expire at ",
290 lr
->val
[i
].lr_value
);
298 && ctx
->enc_part
.key_expiration
299 && *ctx
->enc_part
.key_expiration
<= t
) {
300 report_expiration(context
, ctx
->prompter
,
302 "Your password/account will expire at ",
303 *ctx
->enc_part
.key_expiration
);
308 static krb5_addresses no_addrs
= { 0, NULL
};
310 static krb5_error_code
311 get_init_creds_common(krb5_context context
,
312 krb5_principal client
,
313 krb5_deltat start_time
,
314 krb5_get_init_creds_opt
*options
,
315 krb5_init_creds_context ctx
)
317 krb5_get_init_creds_opt
*default_opt
= NULL
;
319 krb5_enctype
*etypes
;
320 krb5_preauthtype
*pre_auth_types
;
322 memset(ctx
, 0, sizeof(*ctx
));
324 if (options
== NULL
) {
325 const char *realm
= krb5_principal_get_realm(context
, client
);
327 krb5_get_init_creds_opt_alloc (context
, &default_opt
);
328 options
= default_opt
;
329 krb5_get_init_creds_opt_set_default_flags(context
, NULL
, realm
, options
);
332 if (options
->opt_private
) {
333 if (options
->opt_private
->password
) {
334 ret
= krb5_init_creds_set_password(context
, ctx
,
335 options
->opt_private
->password
);
340 ctx
->keyproc
= options
->opt_private
->key_proc
;
341 ctx
->req_pac
= options
->opt_private
->req_pac
;
342 ctx
->pk_init_ctx
= options
->opt_private
->pk_init_ctx
;
343 ctx
->ic_flags
= options
->opt_private
->flags
;
345 ctx
->req_pac
= KRB5_INIT_CREDS_TRISTATE_UNSET
;
347 if (ctx
->keyproc
== NULL
)
348 ctx
->keyproc
= default_s2k_func
;
350 /* Enterprise name implicitly turns on canonicalize */
351 if ((ctx
->ic_flags
& KRB5_INIT_CREDS_CANONICALIZE
) ||
352 krb5_principal_get_type(context
, client
) == KRB5_NT_ENTERPRISE_PRINCIPAL
)
353 ctx
->flags
.canonicalize
= 1;
355 ctx
->pre_auth_types
= NULL
;
358 ctx
->pre_auth_types
= NULL
;
360 ret
= init_cred(context
, &ctx
->cred
, client
, start_time
, options
);
363 krb5_get_init_creds_opt_free(context
, default_opt
);
367 ret
= krb5_init_creds_set_service(context
, ctx
, NULL
);
371 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_FORWARDABLE
)
372 ctx
->flags
.forwardable
= options
->forwardable
;
374 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_PROXIABLE
)
375 ctx
->flags
.proxiable
= options
->proxiable
;
378 ctx
->flags
.postdated
= 1;
379 if (ctx
->cred
.times
.renew_till
)
380 ctx
->flags
.renewable
= 1;
381 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST
) {
382 ctx
->addrs
= options
->address_list
;
383 } else if (options
->opt_private
) {
384 switch (options
->opt_private
->addressless
) {
385 case KRB5_INIT_CREDS_TRISTATE_UNSET
:
386 #if KRB5_ADDRESSLESS_DEFAULT == TRUE
387 ctx
->addrs
= &no_addrs
;
392 case KRB5_INIT_CREDS_TRISTATE_FALSE
:
395 case KRB5_INIT_CREDS_TRISTATE_TRUE
:
396 ctx
->addrs
= &no_addrs
;
400 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST
) {
404 etypes
= malloc((options
->etype_list_length
+ 1)
405 * sizeof(krb5_enctype
));
406 if (etypes
== NULL
) {
408 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
411 memcpy (etypes
, options
->etype_list
,
412 options
->etype_list_length
* sizeof(krb5_enctype
));
413 etypes
[options
->etype_list_length
] = ETYPE_NULL
;
414 ctx
->etypes
= etypes
;
416 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST
) {
417 pre_auth_types
= malloc((options
->preauth_list_length
+ 1)
418 * sizeof(krb5_preauthtype
));
419 if (pre_auth_types
== NULL
) {
421 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
424 memcpy (pre_auth_types
, options
->preauth_list
,
425 options
->preauth_list_length
* sizeof(krb5_preauthtype
));
426 pre_auth_types
[options
->preauth_list_length
] = KRB5_PADATA_NONE
;
427 ctx
->pre_auth_types
= pre_auth_types
;
429 if (options
->flags
& KRB5_GET_INIT_CREDS_OPT_ANONYMOUS
)
430 ctx
->flags
.request_anonymous
= options
->anonymous
;
432 krb5_get_init_creds_opt_free(context
, default_opt
);
436 krb5_get_init_creds_opt_free(context
, default_opt
);
440 static krb5_error_code
441 change_password (krb5_context context
,
442 krb5_principal client
,
443 const char *password
,
446 krb5_prompter_fct prompter
,
448 krb5_get_init_creds_opt
*old_options
)
450 krb5_prompt prompts
[2];
453 char buf1
[BUFSIZ
], buf2
[BUFSIZ
];
454 krb5_data password_data
[2];
456 krb5_data result_code_string
;
457 krb5_data result_string
;
459 krb5_get_init_creds_opt
*options
;
461 memset (&cpw_cred
, 0, sizeof(cpw_cred
));
463 ret
= krb5_get_init_creds_opt_alloc(context
, &options
);
466 krb5_get_init_creds_opt_set_tkt_life (options
, 60);
467 krb5_get_init_creds_opt_set_forwardable (options
, FALSE
);
468 krb5_get_init_creds_opt_set_proxiable (options
, FALSE
);
469 if (old_options
&& old_options
->flags
& KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST
)
470 krb5_get_init_creds_opt_set_preauth_list (options
,
471 old_options
->preauth_list
,
472 old_options
->preauth_list_length
);
474 krb5_data_zero (&result_code_string
);
475 krb5_data_zero (&result_string
);
477 ret
= krb5_get_init_creds_password (context
,
486 krb5_get_init_creds_opt_free(context
, options
);
491 password_data
[0].data
= buf1
;
492 password_data
[0].length
= sizeof(buf1
);
494 prompts
[0].hidden
= 1;
495 prompts
[0].prompt
= "New password: ";
496 prompts
[0].reply
= &password_data
[0];
497 prompts
[0].type
= KRB5_PROMPT_TYPE_NEW_PASSWORD
;
499 password_data
[1].data
= buf2
;
500 password_data
[1].length
= sizeof(buf2
);
502 prompts
[1].hidden
= 1;
503 prompts
[1].prompt
= "Repeat new password: ";
504 prompts
[1].reply
= &password_data
[1];
505 prompts
[1].type
= KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN
;
507 ret
= (*prompter
) (context
, data
, NULL
, "Changing password",
510 memset (buf1
, 0, sizeof(buf1
));
511 memset (buf2
, 0, sizeof(buf2
));
515 if (strcmp (buf1
, buf2
) == 0)
517 memset (buf1
, 0, sizeof(buf1
));
518 memset (buf2
, 0, sizeof(buf2
));
521 ret
= krb5_set_password (context
,
530 asprintf (&p
, "%s: %.*s\n",
531 result_code
? "Error" : "Success",
532 (int)result_string
.length
,
533 result_string
.length
> 0 ? (char*)result_string
.data
: "");
535 /* return the result */
536 (*prompter
) (context
, data
, NULL
, p
, 0, NULL
);
539 if (result_code
== 0) {
540 strlcpy (newpw
, buf1
, newpw_sz
);
544 krb5_set_error_message(context
, ret
,
545 N_("failed changing password", ""));
549 memset (buf1
, 0, sizeof(buf1
));
550 memset (buf2
, 0, sizeof(buf2
));
551 krb5_data_free (&result_string
);
552 krb5_data_free (&result_code_string
);
553 krb5_free_cred_contents (context
, &cpw_cred
);
558 krb5_error_code KRB5_LIB_FUNCTION
559 krb5_keyblock_key_proc (krb5_context context
,
562 krb5_const_pointer keyseed
,
565 return krb5_copy_keyblock (context
, keyseed
, key
);
572 static krb5_error_code
573 init_as_req (krb5_context context
,
575 const krb5_creds
*creds
,
576 const krb5_addresses
*addrs
,
577 const krb5_enctype
*etypes
,
582 memset(a
, 0, sizeof(*a
));
585 a
->msg_type
= krb_as_req
;
586 a
->req_body
.kdc_options
= opts
;
587 a
->req_body
.cname
= malloc(sizeof(*a
->req_body
.cname
));
588 if (a
->req_body
.cname
== NULL
) {
590 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
593 a
->req_body
.sname
= malloc(sizeof(*a
->req_body
.sname
));
594 if (a
->req_body
.sname
== NULL
) {
596 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
600 ret
= _krb5_principal2principalname (a
->req_body
.cname
, creds
->client
);
603 ret
= copy_Realm(&creds
->client
->realm
, &a
->req_body
.realm
);
607 ret
= _krb5_principal2principalname (a
->req_body
.sname
, creds
->server
);
611 if(creds
->times
.starttime
) {
612 a
->req_body
.from
= malloc(sizeof(*a
->req_body
.from
));
613 if (a
->req_body
.from
== NULL
) {
615 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
618 *a
->req_body
.from
= creds
->times
.starttime
;
620 if(creds
->times
.endtime
){
621 ALLOC(a
->req_body
.till
, 1);
622 *a
->req_body
.till
= creds
->times
.endtime
;
624 if(creds
->times
.renew_till
){
625 a
->req_body
.rtime
= malloc(sizeof(*a
->req_body
.rtime
));
626 if (a
->req_body
.rtime
== NULL
) {
628 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
631 *a
->req_body
.rtime
= creds
->times
.renew_till
;
633 a
->req_body
.nonce
= 0;
634 ret
= krb5_init_etype (context
,
635 &a
->req_body
.etype
.len
,
636 &a
->req_body
.etype
.val
,
642 * This means no addresses
645 if (addrs
&& addrs
->len
== 0) {
646 a
->req_body
.addresses
= NULL
;
648 a
->req_body
.addresses
= malloc(sizeof(*a
->req_body
.addresses
));
649 if (a
->req_body
.addresses
== NULL
) {
651 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
656 ret
= krb5_copy_addresses(context
, addrs
, a
->req_body
.addresses
);
658 ret
= krb5_get_all_client_addrs (context
, a
->req_body
.addresses
);
659 if(ret
== 0 && a
->req_body
.addresses
->len
== 0) {
660 free(a
->req_body
.addresses
);
661 a
->req_body
.addresses
= NULL
;
668 a
->req_body
.enc_authorization_data
= NULL
;
669 a
->req_body
.additional_tickets
= NULL
;
676 memset(a
, 0, sizeof(*a
));
680 struct pa_info_data
{
683 krb5_data
*s2kparams
;
687 free_paid(krb5_context context
, struct pa_info_data
*ppaid
)
689 krb5_free_salt(context
, ppaid
->salt
);
690 if (ppaid
->s2kparams
)
691 krb5_free_data(context
, ppaid
->s2kparams
);
695 static krb5_error_code
696 set_paid(struct pa_info_data
*paid
, krb5_context context
,
698 krb5_salttype salttype
, void *salt_string
, size_t salt_len
,
699 krb5_data
*s2kparams
)
702 paid
->salt
.salttype
= salttype
;
703 paid
->salt
.saltvalue
.data
= malloc(salt_len
+ 1);
704 if (paid
->salt
.saltvalue
.data
== NULL
) {
705 krb5_clear_error_message(context
);
708 memcpy(paid
->salt
.saltvalue
.data
, salt_string
, salt_len
);
709 ((char *)paid
->salt
.saltvalue
.data
)[salt_len
] = '\0';
710 paid
->salt
.saltvalue
.length
= salt_len
;
714 ret
= krb5_copy_data(context
, s2kparams
, &paid
->s2kparams
);
716 krb5_clear_error_message(context
);
717 krb5_free_salt(context
, paid
->salt
);
721 paid
->s2kparams
= NULL
;
726 static struct pa_info_data
*
727 pa_etype_info2(krb5_context context
,
728 const krb5_principal client
,
730 struct pa_info_data
*paid
,
731 heim_octet_string
*data
)
738 memset(&e
, 0, sizeof(e
));
739 ret
= decode_ETYPE_INFO2(data
->data
, data
->length
, &e
, &sz
);
744 for (j
= 0; j
< asreq
->req_body
.etype
.len
; j
++) {
745 for (i
= 0; i
< e
.len
; i
++) {
746 if (asreq
->req_body
.etype
.val
[j
] == e
.val
[i
].etype
) {
748 if (e
.val
[i
].salt
== NULL
)
749 ret
= krb5_get_pw_salt(context
, client
, &salt
);
751 salt
.saltvalue
.data
= *e
.val
[i
].salt
;
752 salt
.saltvalue
.length
= strlen(*e
.val
[i
].salt
);
756 ret
= set_paid(paid
, context
, e
.val
[i
].etype
,
759 salt
.saltvalue
.length
,
761 if (e
.val
[i
].salt
== NULL
)
762 krb5_free_salt(context
, salt
);
764 free_ETYPE_INFO2(&e
);
771 free_ETYPE_INFO2(&e
);
775 static struct pa_info_data
*
776 pa_etype_info(krb5_context context
,
777 const krb5_principal client
,
779 struct pa_info_data
*paid
,
780 heim_octet_string
*data
)
787 memset(&e
, 0, sizeof(e
));
788 ret
= decode_ETYPE_INFO(data
->data
, data
->length
, &e
, &sz
);
793 for (j
= 0; j
< asreq
->req_body
.etype
.len
; j
++) {
794 for (i
= 0; i
< e
.len
; i
++) {
795 if (asreq
->req_body
.etype
.val
[j
] == e
.val
[i
].etype
) {
797 salt
.salttype
= KRB5_PW_SALT
;
798 if (e
.val
[i
].salt
== NULL
)
799 ret
= krb5_get_pw_salt(context
, client
, &salt
);
801 salt
.saltvalue
= *e
.val
[i
].salt
;
804 if (e
.val
[i
].salttype
)
805 salt
.salttype
= *e
.val
[i
].salttype
;
807 ret
= set_paid(paid
, context
, e
.val
[i
].etype
,
810 salt
.saltvalue
.length
,
812 if (e
.val
[i
].salt
== NULL
)
813 krb5_free_salt(context
, salt
);
827 static struct pa_info_data
*
828 pa_pw_or_afs3_salt(krb5_context context
,
829 const krb5_principal client
,
831 struct pa_info_data
*paid
,
832 heim_octet_string
*data
)
835 if (paid
->etype
== ENCTYPE_NULL
)
837 ret
= set_paid(paid
, context
,
850 krb5_preauthtype type
;
851 struct pa_info_data
*(*salt_info
)(krb5_context
,
852 const krb5_principal
,
854 struct pa_info_data
*,
855 heim_octet_string
*);
858 static struct pa_info pa_prefs
[] = {
859 { KRB5_PADATA_ETYPE_INFO2
, pa_etype_info2
},
860 { KRB5_PADATA_ETYPE_INFO
, pa_etype_info
},
861 { KRB5_PADATA_PW_SALT
, pa_pw_or_afs3_salt
},
862 { KRB5_PADATA_AFS3_SALT
, pa_pw_or_afs3_salt
}
866 find_pa_data(const METHOD_DATA
*md
, int type
)
871 for (i
= 0; i
< md
->len
; i
++)
872 if (md
->val
[i
].padata_type
== type
)
877 static struct pa_info_data
*
878 process_pa_info(krb5_context context
,
879 const krb5_principal client
,
881 struct pa_info_data
*paid
,
884 struct pa_info_data
*p
= NULL
;
887 for (i
= 0; p
== NULL
&& i
< sizeof(pa_prefs
)/sizeof(pa_prefs
[0]); i
++) {
888 PA_DATA
*pa
= find_pa_data(md
, pa_prefs
[i
].type
);
891 paid
->salt
.salttype
= pa_prefs
[i
].type
;
892 p
= (*pa_prefs
[i
].salt_info
)(context
, client
, asreq
,
893 paid
, &pa
->padata_value
);
898 static krb5_error_code
899 make_pa_enc_timestamp(krb5_context context
, METHOD_DATA
*md
,
900 krb5_enctype etype
, krb5_keyblock
*key
)
906 EncryptedData encdata
;
912 krb5_us_timeofday (context
, &p
.patimestamp
, &usec
);
916 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC
, buf
, buf_size
, &p
, &len
, ret
);
920 krb5_abortx(context
, "internal error in ASN.1 encoder");
922 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
927 ret
= krb5_encrypt_EncryptedData(context
,
929 KRB5_KU_PA_ENC_TIMESTAMP
,
935 krb5_crypto_destroy(context
, crypto
);
939 ASN1_MALLOC_ENCODE(EncryptedData
, buf
, buf_size
, &encdata
, &len
, ret
);
940 free_EncryptedData(&encdata
);
944 krb5_abortx(context
, "internal error in ASN.1 encoder");
946 ret
= krb5_padata_add(context
, md
, KRB5_PADATA_ENC_TIMESTAMP
, buf
, len
);
952 static krb5_error_code
953 add_enc_ts_padata(krb5_context context
,
955 krb5_principal client
,
956 krb5_s2k_proc keyproc
,
957 krb5_const_pointer keyseed
,
958 krb5_enctype
*enctypes
,
961 krb5_data
*s2kparams
)
969 /* default to standard salt */
970 ret
= krb5_get_pw_salt (context
, client
, &salt2
);
976 enctypes
= context
->etypes
;
978 for (ep
= enctypes
; *ep
!= ETYPE_NULL
; ep
++)
982 for (i
= 0; i
< netypes
; ++i
) {
985 ret
= (*keyproc
)(context
, enctypes
[i
], keyseed
,
986 *salt
, s2kparams
, &key
);
989 ret
= make_pa_enc_timestamp (context
, md
, enctypes
[i
], key
);
990 krb5_free_keyblock (context
, key
);
995 krb5_free_salt(context
, salt2
);
999 static krb5_error_code
1000 pa_data_to_md_ts_enc(krb5_context context
,
1002 const krb5_principal client
,
1003 krb5_get_init_creds_ctx
*ctx
,
1004 struct pa_info_data
*ppaid
,
1007 if (ctx
->keyproc
== NULL
|| ctx
->keyseed
== NULL
)
1011 add_enc_ts_padata(context
, md
, client
,
1012 ctx
->keyproc
, ctx
->keyseed
,
1014 &ppaid
->salt
, ppaid
->s2kparams
);
1018 /* make a v5 salted pa-data */
1019 add_enc_ts_padata(context
, md
, client
,
1020 ctx
->keyproc
, ctx
->keyseed
,
1021 a
->req_body
.etype
.val
, a
->req_body
.etype
.len
,
1024 /* make a v4 salted pa-data */
1025 salt
.salttype
= KRB5_PW_SALT
;
1026 krb5_data_zero(&salt
.saltvalue
);
1027 add_enc_ts_padata(context
, md
, client
,
1028 ctx
->keyproc
, ctx
->keyseed
,
1029 a
->req_body
.etype
.val
, a
->req_body
.etype
.len
,
1035 static krb5_error_code
1036 pa_data_to_key_plain(krb5_context context
,
1037 const krb5_principal client
,
1038 krb5_get_init_creds_ctx
*ctx
,
1040 krb5_data
*s2kparams
,
1042 krb5_keyblock
**key
)
1044 krb5_error_code ret
;
1046 ret
= (*ctx
->keyproc
)(context
, etype
, ctx
->keyseed
,
1047 salt
, s2kparams
, key
);
1052 static krb5_error_code
1053 pa_data_to_md_pkinit(krb5_context context
,
1055 const krb5_principal client
,
1056 krb5_get_init_creds_ctx
*ctx
,
1059 if (ctx
->pk_init_ctx
== NULL
)
1062 return _krb5_pk_mk_padata(context
,
1068 krb5_set_error_message(context
, EINVAL
,
1069 N_("no support for PKINIT compiled in", ""));
1074 static krb5_error_code
1075 pa_data_add_pac_request(krb5_context context
,
1076 krb5_get_init_creds_ctx
*ctx
,
1080 krb5_error_code ret
;
1084 switch (ctx
->req_pac
) {
1085 case KRB5_INIT_CREDS_TRISTATE_UNSET
:
1086 return 0; /* don't bother */
1087 case KRB5_INIT_CREDS_TRISTATE_TRUE
:
1088 req
.include_pac
= 1;
1090 case KRB5_INIT_CREDS_TRISTATE_FALSE
:
1091 req
.include_pac
= 0;
1094 ASN1_MALLOC_ENCODE(PA_PAC_REQUEST
, buf
, length
,
1099 krb5_abortx(context
, "internal error in ASN.1 encoder");
1101 ret
= krb5_padata_add(context
, md
, KRB5_PADATA_PA_PAC_REQUEST
, buf
, len
);
1109 * Assumes caller always will free `out_md', even on error.
1112 static krb5_error_code
1113 process_pa_data_to_md(krb5_context context
,
1114 const krb5_creds
*creds
,
1116 krb5_get_init_creds_ctx
*ctx
,
1118 METHOD_DATA
**out_md
,
1119 krb5_prompter_fct prompter
,
1120 void *prompter_data
)
1122 krb5_error_code ret
;
1125 if (*out_md
== NULL
) {
1126 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1130 (*out_md
)->val
= NULL
;
1133 * Make sure we don't sent both ENC-TS and PK-INIT pa data, no
1134 * need to expose our password protecting our PKCS12 key.
1137 if (ctx
->pk_init_ctx
) {
1139 ret
= pa_data_to_md_pkinit(context
, a
, creds
->client
, ctx
, *out_md
);
1143 } else if (in_md
->len
!= 0) {
1144 struct pa_info_data paid
, *ppaid
;
1146 memset(&paid
, 0, sizeof(paid
));
1148 paid
.etype
= ENCTYPE_NULL
;
1149 ppaid
= process_pa_info(context
, creds
->client
, a
, &paid
, in_md
);
1151 pa_data_to_md_ts_enc(context
, a
, creds
->client
, ctx
, ppaid
, *out_md
);
1153 free_paid(context
, ppaid
);
1156 pa_data_add_pac_request(context
, ctx
, *out_md
);
1158 if ((*out_md
)->len
== 0) {
1166 static krb5_error_code
1167 process_pa_data_to_key(krb5_context context
,
1168 krb5_get_init_creds_ctx
*ctx
,
1172 const krb5_krbhst_info
*hi
,
1173 krb5_keyblock
**key
)
1175 struct pa_info_data paid
, *ppaid
= NULL
;
1176 krb5_error_code ret
;
1180 memset(&paid
, 0, sizeof(paid
));
1182 etype
= rep
->enc_part
.etype
;
1186 ppaid
= process_pa_info(context
, creds
->client
, a
, &paid
,
1189 if (ppaid
== NULL
) {
1190 ret
= krb5_get_pw_salt (context
, creds
->client
, &paid
.salt
);
1194 paid
.s2kparams
= NULL
;
1200 pa
= krb5_find_padata(rep
->padata
->val
,
1202 KRB5_PADATA_PK_AS_REP
,
1206 pa
= krb5_find_padata(rep
->padata
->val
,
1208 KRB5_PADATA_PK_AS_REP_19
,
1212 if (pa
&& ctx
->pk_init_ctx
) {
1214 ret
= _krb5_pk_rd_pa_reply(context
,
1225 krb5_set_error_message(context
, ret
, N_("no support for PKINIT compiled in", ""));
1227 } else if (ctx
->keyseed
)
1228 ret
= pa_data_to_key_plain(context
, creds
->client
, ctx
,
1229 paid
.salt
, paid
.s2kparams
, etype
, key
);
1232 krb5_set_error_message(context
, ret
, N_("No usable pa data type", ""));
1235 free_paid(context
, &paid
);
1240 * Start a new context to get a new initial credential.
1242 * @param context A Kerberos 5 context.
1243 * @param client The Kerberos principal to get the credential for, if
1244 * NULL is given, the default principal is used as determined by
1245 * krb5_get_default_principal().
1247 * @param prompter_data
1248 * @param start_time the time the ticket should start to be valid or 0 for now.
1249 * @param options a options structure, can be NULL for default options.
1250 * @param rctx A new allocated free with krb5_init_creds_free().
1252 * @return 0 for success or an Kerberos 5 error code, see krb5_get_error_message().
1254 * @ingroup krb5_credential
1257 krb5_error_code KRB5_LIB_FUNCTION
1258 krb5_init_creds_init(krb5_context context
,
1259 krb5_principal client
,
1260 krb5_prompter_fct prompter
,
1261 void *prompter_data
,
1262 krb5_deltat start_time
,
1263 krb5_get_init_creds_opt
*options
,
1264 krb5_init_creds_context
*rctx
)
1266 krb5_init_creds_context ctx
;
1267 krb5_error_code ret
;
1271 ctx
= calloc(1, sizeof(*ctx
));
1273 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1277 ret
= get_init_creds_common(context
, client
, start_time
, options
, ctx
);
1283 /* Set a new nonce. */
1284 krb5_generate_random_block (&ctx
->nonce
, sizeof(ctx
->nonce
));
1285 ctx
->nonce
&= 0x7fffffff;
1286 /* XXX these just needs to be the same when using Windows PK-INIT */
1287 ctx
->pk_nonce
= ctx
->nonce
;
1289 ctx
->prompter
= prompter
;
1290 ctx
->prompter_data
= prompter_data
;
1298 * Sets the service that the is requested. This call is only neede for
1299 * special initial tickets, by default the a krbtgt is fetched in the default realm.
1301 * @param context a Kerberos 5 context.
1302 * @param ctx a krb5_init_creds_context context.
1303 * @param service the service given as a string, for example
1304 * "kadmind/admin". If NULL, the default krbtgt in the clients
1307 * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1308 * @ingroup krb5_credential
1311 krb5_error_code KRB5_LIB_FUNCTION
1312 krb5_init_creds_set_service(krb5_context context
,
1313 krb5_init_creds_context ctx
,
1314 const char *service
)
1316 krb5_const_realm client_realm
;
1317 krb5_principal principal
;
1318 krb5_error_code ret
;
1320 client_realm
= krb5_principal_get_realm (context
, ctx
->cred
.client
);
1323 ret
= krb5_parse_name (context
, service
, &principal
);
1326 krb5_principal_set_realm (context
, principal
, client_realm
);
1328 ret
= krb5_make_principal(context
, &principal
,
1329 client_realm
, KRB5_TGS_NAME
, client_realm
,
1334 krb5_free_principal(context
, ctx
->cred
.server
);
1335 ctx
->cred
.server
= principal
;
1341 * Sets the password that will use for the request.
1343 * @param context a Kerberos 5 context.
1344 * @param ctx ctx krb5_init_creds_context context.
1345 * @param password the password to use.
1347 * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1348 * @ingroup krb5_credential
1351 krb5_error_code KRB5_LIB_FUNCTION
1352 krb5_init_creds_set_password(krb5_context context
,
1353 krb5_init_creds_context ctx
,
1354 const char *password
)
1357 memset(ctx
->password
, 0, strlen(ctx
->password
));
1359 ctx
->password
= strdup(password
);
1360 if (ctx
->password
== NULL
) {
1361 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1364 ctx
->keyseed
= (void *) ctx
->password
;
1366 ctx
->keyseed
= NULL
;
1367 ctx
->password
= NULL
;
1373 static krb5_error_code
1374 keytab_key_proc(krb5_context context
, krb5_enctype enctype
,
1375 krb5_const_pointer keyseed
,
1376 krb5_salt salt
, krb5_data
*s2kparms
,
1377 krb5_keyblock
**key
)
1379 krb5_keytab_key_proc_args
*args
= rk_UNCONST(keyseed
);
1380 krb5_keytab keytab
= args
->keytab
;
1381 krb5_principal principal
= args
->principal
;
1382 krb5_error_code ret
;
1383 krb5_keytab real_keytab
;
1384 krb5_keytab_entry entry
;
1387 krb5_kt_default(context
, &real_keytab
);
1389 real_keytab
= keytab
;
1391 ret
= krb5_kt_get_entry (context
, real_keytab
, principal
,
1392 0, enctype
, &entry
);
1395 krb5_kt_close (context
, real_keytab
);
1400 ret
= krb5_copy_keyblock (context
, &entry
.keyblock
, key
);
1401 krb5_kt_free_entry(context
, &entry
);
1407 * Set the keytab to use for authentication.
1409 * @param context a Kerberos 5 context.
1410 * @param ctx ctx krb5_init_creds_context context.
1411 * @param keytab the keytab to read the key from.
1413 * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
1414 * @ingroup krb5_credential
1417 krb5_error_code KRB5_LIB_FUNCTION
1418 krb5_init_creds_set_keytab(krb5_context context
,
1419 krb5_init_creds_context ctx
,
1422 krb5_keytab_key_proc_args
*a
;
1423 krb5_keytab_entry entry
;
1424 krb5_kt_cursor cursor
;
1425 krb5_enctype
*etypes
= NULL
;
1426 krb5_error_code ret
;
1430 a
= malloc(sizeof(*a
));
1432 krb5_set_error_message(context
, ENOMEM
,
1433 N_("malloc: out of memory", ""));
1437 a
->principal
= ctx
->cred
.client
;
1440 ctx
->keytab_data
= a
;
1441 ctx
->keyseed
= (void *)a
;
1442 ctx
->keyproc
= keytab_key_proc
;
1445 * We need to the KDC what enctypes we support for this keytab,
1446 * esp if the keytab is really a password based entry, then the
1447 * KDC might have more enctypes in the database then what we have
1451 ret
= krb5_kt_start_seq_get(context
, keytab
, &cursor
);
1455 while(krb5_kt_next_entry(context
, keytab
, &entry
, &cursor
) == 0){
1458 if (!krb5_principal_compare(context
, entry
.principal
, ctx
->cred
.client
))
1461 /* check if we ahve this kvno already */
1462 if (entry
.vno
> kvno
) {
1463 /* remove old list of etype */
1468 } else if (entry
.vno
!= kvno
)
1471 /* check if enctype is supported */
1472 if (krb5_enctype_valid(context
, entry
.keyblock
.keytype
) != 0)
1475 /* add enctype to supported list */
1476 ptr
= realloc(etypes
, sizeof(etypes
[0]) * (netypes
+ 1));
1481 etypes
[netypes
] = entry
.keyblock
.keytype
;
1482 etypes
[netypes
+ 1] = 0;
1485 krb5_kt_free_entry(context
, &entry
);
1487 krb5_kt_end_seq_get(context
, keytab
, &cursor
);
1492 ctx
->etypes
= etypes
;
1499 static krb5_error_code
1500 keyblock_key_proc(krb5_context context
, krb5_enctype enctype
,
1501 krb5_const_pointer keyseed
,
1502 krb5_salt salt
, krb5_data
*s2kparms
,
1503 krb5_keyblock
**key
)
1505 return krb5_copy_keyblock (context
, keyseed
, key
);
1508 krb5_error_code KRB5_LIB_FUNCTION
1509 krb5_init_creds_set_keyblock(krb5_context context
,
1510 krb5_init_creds_context ctx
,
1511 krb5_keyblock
*keyblock
)
1513 ctx
->keyseed
= (void *)keyblock
;
1514 ctx
->keyproc
= keyblock_key_proc
;
1520 * The core loop if krb5_get_init_creds() function family. Create the
1521 * packets and have the caller send them off to the KDC.
1523 * If the caller want all work been done for them, use
1524 * krb5_init_creds_get() instead.
1526 * @param context a Kerberos 5 context.
1527 * @param ctx ctx krb5_init_creds_context context.
1528 * @param in input data from KDC, first round it should be reset by krb5_data_zer().
1529 * @param out reply to KDC.
1530 * @param hostinfo KDC address info, first round it can be NULL.
1531 * @param flags status of the round, if 1 is set, continue one more round.
1533 * @return 0 for success, or an Kerberos 5 error code, see
1534 * krb5_get_error_message().
1536 * @ingroup krb5_credential
1539 krb5_error_code KRB5_LIB_FUNCTION
1540 krb5_init_creds_step(krb5_context context
,
1541 krb5_init_creds_context ctx
,
1544 krb5_krbhst_info
*hostinfo
,
1545 unsigned int *flags
)
1547 krb5_error_code ret
;
1551 krb5_data_zero(out
);
1553 if (ctx
->as_req
.req_body
.cname
== NULL
) {
1554 ret
= init_as_req(context
, ctx
->flags
, &ctx
->cred
,
1555 ctx
->addrs
, ctx
->etypes
, &ctx
->as_req
);
1557 free_init_creds_ctx(context
, ctx
);
1562 #define MAX_PA_COUNTER 10
1563 if (ctx
->pa_counter
> MAX_PA_COUNTER
) {
1564 krb5_set_error_message(context
, KRB5_GET_IN_TKT_LOOP
,
1565 N_("Looping %d times while getting "
1566 "initial credentials", ""),
1568 return KRB5_GET_IN_TKT_LOOP
;
1572 /* Lets process the input packet */
1573 if (in
&& in
->length
) {
1576 memset(&rep
, 0, sizeof(rep
));
1578 ret
= decode_AS_REP(in
->data
, in
->length
, &rep
.kdc_rep
, &size
);
1580 krb5_keyblock
*key
= NULL
;
1581 unsigned eflags
= EXTRACT_TICKET_AS_REQ
;
1583 if (ctx
->flags
.canonicalize
) {
1584 eflags
|= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
;
1585 eflags
|= EXTRACT_TICKET_MATCH_REALM
;
1587 if (ctx
->ic_flags
& KRB5_INIT_CREDS_NO_C_CANON_CHECK
)
1588 eflags
|= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH
;
1590 ret
= process_pa_data_to_key(context
, ctx
, &ctx
->cred
,
1591 &ctx
->as_req
, &rep
.kdc_rep
, hostinfo
, &key
);
1593 free_AS_REP(&rep
.kdc_rep
);
1597 ret
= _krb5_extract_ticket(context
,
1602 KRB5_KU_AS_REP_ENC_PART
,
1608 krb5_free_keyblock(context
, key
);
1613 ret
= copy_EncKDCRepPart(&rep
.enc_part
, &ctx
->enc_part
);
1615 free_AS_REP(&rep
.kdc_rep
);
1616 free_EncASRepPart(&rep
.enc_part
);
1621 /* let's try to parse it as a KRB-ERROR */
1623 free_KRB_ERROR(&ctx
->error
);
1625 ret
= krb5_rd_error(context
, in
, &ctx
->error
);
1626 if(ret
&& in
->length
&& ((char*)in
->data
)[0] == 4)
1627 ret
= KRB5KRB_AP_ERR_V4_REPLY
;
1631 ret
= krb5_error_from_rd_error(context
, &ctx
->error
, &ctx
->cred
);
1634 * If no preauth was set and KDC requires it, give it one
1638 if (ret
== KRB5KDC_ERR_PREAUTH_REQUIRED
) {
1640 free_METHOD_DATA(&ctx
->md
);
1641 memset(&ctx
->md
, 0, sizeof(ctx
->md
));
1643 if (ctx
->error
.e_data
) {
1644 ret
= decode_METHOD_DATA(ctx
->error
.e_data
->data
,
1645 ctx
->error
.e_data
->length
,
1649 krb5_set_error_message(context
, ret
,
1650 N_("Failed to decode METHOD-DATA", ""));
1652 krb5_set_error_message(context
, ret
,
1653 N_("Preauth required but no preauth "
1654 "options send by KDC", ""));
1656 } else if (ret
== KRB5KRB_AP_ERR_SKEW
&& context
->kdc_sec_offset
== 0) {
1658 * Try adapt to timeskrew when we are using pre-auth, and
1659 * if there was a time skew, try again.
1661 krb5_set_real_time(context
, ctx
->error
.stime
, -1);
1662 if (context
->kdc_sec_offset
)
1664 } else if (ret
== KRB5_KDC_ERR_WRONG_REALM
&& ctx
->flags
.canonicalize
) {
1665 /* client referal to a new realm */
1666 if (ctx
->error
.crealm
== NULL
) {
1667 krb5_set_error_message(context
, ret
,
1668 N_("Got a client referral, not but no realm", ""));
1671 ret
= krb5_principal_set_realm(context
,
1673 *ctx
->error
.crealm
);
1680 if (ctx
->as_req
.padata
) {
1681 free_METHOD_DATA(ctx
->as_req
.padata
);
1682 free(ctx
->as_req
.padata
);
1683 ctx
->as_req
.padata
= NULL
;
1686 /* Set a new nonce. */
1687 ctx
->as_req
.req_body
.nonce
= ctx
->nonce
;
1689 /* fill_in_md_data */
1690 ret
= process_pa_data_to_md(context
, &ctx
->cred
, &ctx
->as_req
, ctx
,
1691 &ctx
->md
, &ctx
->as_req
.padata
,
1692 ctx
->prompter
, ctx
->prompter_data
);
1696 krb5_data_free(&ctx
->req_buffer
);
1698 ASN1_MALLOC_ENCODE(AS_REQ
,
1699 ctx
->req_buffer
.data
, ctx
->req_buffer
.length
,
1700 &ctx
->as_req
, &len
, ret
);
1703 if(len
!= ctx
->req_buffer
.length
)
1704 krb5_abortx(context
, "internal error in ASN.1 encoder");
1706 out
->data
= ctx
->req_buffer
.data
;
1707 out
->length
= ctx
->req_buffer
.length
;
1717 * Extract the newly acquired credentials from krb5_init_creds_context
1720 * @param context A Kerberos 5 context.
1722 * @param cred credentials, free with krb5_free_cred_contents().
1724 * @return 0 for sucess or An Kerberos error code, see krb5_get_error_message().
1727 krb5_error_code KRB5_LIB_FUNCTION
1728 krb5_init_creds_get_creds(krb5_context context
,
1729 krb5_init_creds_context ctx
,
1732 return krb5_copy_creds_contents(context
, &ctx
->cred
, cred
);
1736 * Get the last error from the transaction.
1738 * @return Returns 0 or an error code
1740 * @ingroup krb5_credential
1743 krb5_error_code KRB5_LIB_FUNCTION
1744 krb5_init_creds_get_error(krb5_context context
,
1745 krb5_init_creds_context ctx
,
1748 krb5_error_code ret
;
1750 ret
= copy_KRB_ERROR(&ctx
->error
, error
);
1752 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1758 * Free the krb5_init_creds_context allocated by krb5_init_creds_init().
1760 * @param context A Kerberos 5 context.
1761 * @param ctx The krb5_init_creds_context to free.
1763 * @ingroup krb5_credential
1766 void KRB5_LIB_FUNCTION
1767 krb5_init_creds_free(krb5_context context
,
1768 krb5_init_creds_context ctx
)
1770 free_init_creds_ctx(context
, ctx
);
1775 * Get new credentials as setup by the krb5_init_creds_context.
1777 * @param context A Kerberos 5 context.
1778 * @param ctx The krb5_init_creds_context to process.
1780 * @ingroup krb5_credential
1783 krb5_error_code KRB5_LIB_FUNCTION
1784 krb5_init_creds_get(krb5_context context
, krb5_init_creds_context ctx
)
1786 krb5_sendto_ctx stctx
= NULL
;
1787 krb5_krbhst_info
*hostinfo
= NULL
;
1788 krb5_error_code ret
;
1790 unsigned int flags
= 0;
1792 krb5_data_zero(&in
);
1793 krb5_data_zero(&out
);
1795 ret
= krb5_sendto_ctx_alloc(context
, &stctx
);
1798 krb5_sendto_ctx_set_func(stctx
, _krb5_kdc_retry
, NULL
);
1802 ret
= krb5_init_creds_step(context
, ctx
, &in
, &out
, hostinfo
, &flags
);
1803 krb5_data_free(&in
);
1807 if ((flags
& 1) == 0)
1810 ret
= krb5_sendto_context (context
, stctx
, &out
,
1811 ctx
->cred
.client
->realm
, &in
);
1819 krb5_sendto_ctx_free(context
, stctx
);
1825 * Get new credentials using password.
1827 * @ingroup krb5_credential
1831 krb5_error_code KRB5_LIB_FUNCTION
1832 krb5_get_init_creds_password(krb5_context context
,
1834 krb5_principal client
,
1835 const char *password
,
1836 krb5_prompter_fct prompter
,
1838 krb5_deltat start_time
,
1839 const char *in_tkt_service
,
1840 krb5_get_init_creds_opt
*options
)
1842 krb5_init_creds_context ctx
;
1844 krb5_error_code ret
;
1848 ret
= krb5_init_creds_init(context
, client
, prompter
, data
, start_time
, options
, &ctx
);
1852 ret
= krb5_init_creds_set_service(context
, ctx
, in_tkt_service
);
1856 if (prompter
!= NULL
&& ctx
->password
== NULL
&& password
== NULL
) {
1858 krb5_data password_data
;
1861 krb5_unparse_name (context
, client
, &p
);
1862 asprintf (&q
, "%s's Password: ", p
);
1865 password_data
.data
= buf
;
1866 password_data
.length
= sizeof(buf
);
1868 prompt
.reply
= &password_data
;
1869 prompt
.type
= KRB5_PROMPT_TYPE_PASSWORD
;
1871 ret
= (*prompter
) (context
, data
, NULL
, NULL
, 1, &prompt
);
1874 memset (buf
, 0, sizeof(buf
));
1875 ret
= KRB5_LIBOS_PWDINTR
;
1876 krb5_clear_error_message (context
);
1879 password
= password_data
.data
;
1883 ret
= krb5_init_creds_set_password(context
, ctx
, password
);
1888 ret
= krb5_init_creds_get(context
, ctx
);
1891 process_last_request(context
, options
, ctx
);
1894 if (ret
== KRB5KDC_ERR_KEY_EXPIRED
&& chpw
== 0) {
1897 /* try to avoid recursion */
1898 if (in_tkt_service
!= NULL
&& strcmp(in_tkt_service
, "kadmin/changepw") == 0)
1901 /* don't try to change password where then where none */
1902 if (prompter
== NULL
)
1905 ret
= change_password (context
,
1916 krb5_init_creds_free(context
, ctx
);
1922 krb5_init_creds_get_creds(context
, ctx
, creds
);
1925 krb5_init_creds_free(context
, ctx
);
1927 memset(buf
, 0, sizeof(buf
));
1932 * Get new credentials using keyblock.
1934 * @ingroup krb5_credential
1937 krb5_error_code KRB5_LIB_FUNCTION
1938 krb5_get_init_creds_keyblock(krb5_context context
,
1940 krb5_principal client
,
1941 krb5_keyblock
*keyblock
,
1942 krb5_deltat start_time
,
1943 const char *in_tkt_service
,
1944 krb5_get_init_creds_opt
*options
)
1946 krb5_init_creds_context ctx
;
1947 krb5_error_code ret
;
1949 memset(creds
, 0, sizeof(*creds
));
1951 ret
= krb5_init_creds_init(context
, client
, NULL
, NULL
, start_time
, options
, &ctx
);
1955 ret
= krb5_init_creds_set_service(context
, ctx
, in_tkt_service
);
1959 ret
= krb5_init_creds_set_keyblock(context
, ctx
, keyblock
);
1963 ret
= krb5_init_creds_get(context
, ctx
);
1966 process_last_request(context
, options
, ctx
);
1970 krb5_init_creds_get_creds(context
, ctx
, creds
);
1973 krb5_init_creds_free(context
, ctx
);
1979 * Get new credentials using keytab.
1981 * @ingroup krb5_credential
1984 krb5_error_code KRB5_LIB_FUNCTION
1985 krb5_get_init_creds_keytab(krb5_context context
,
1987 krb5_principal client
,
1989 krb5_deltat start_time
,
1990 const char *in_tkt_service
,
1991 krb5_get_init_creds_opt
*options
)
1993 krb5_init_creds_context ctx
;
1994 krb5_error_code ret
;
1996 memset(creds
, 0, sizeof(*creds
));
1998 ret
= krb5_init_creds_init(context
, client
, NULL
, NULL
, start_time
, options
, &ctx
);
2002 ret
= krb5_init_creds_set_service(context
, ctx
, in_tkt_service
);
2006 ret
= krb5_init_creds_set_keytab(context
, ctx
, keytab
);
2010 ret
= krb5_init_creds_get(context
, ctx
);
2012 process_last_request(context
, options
, ctx
);
2016 krb5_init_creds_get_creds(context
, ctx
, creds
);
2019 krb5_init_creds_free(context
, ctx
);