Print this page
11528 Makefile.noget can get gone
11529 Use -Wno-maybe-initialized
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c
+++ new/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c
1 1 /*
2 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */
3 3
4 +/*
5 + * Copyright 2019 Joyent, Inc.
6 + */
7 +
4 8 #include "k5-int.h"
5 9 #include "com_err.h"
6 10 #include <admin.h>
7 11 #include <locale.h>
8 12 #include <syslog.h>
9 13
10 14 /* Solaris Kerberos:
11 15 *
12 16 * Change Password functionality is handled by the libkadm5clnt.so.1 library in
13 17 * Solaris Kerberos. In order to avoid a circular dependency between that lib
14 18 * and the kerberos mech lib, we use the #pragma weak compiler directive.
15 19 * This way, when applications link with the libkadm5clnt.so.1 lib the circular
16 20 * dependancy between the two libs will be resolved.
17 21 */
18 22
19 23 #pragma weak kadm5_get_cpw_host_srv_name
20 24 #pragma weak kadm5_init_with_password
21 25 #pragma weak kadm5_chpass_principal_util
22 26
23 27 extern kadm5_ret_t kadm5_get_cpw_host_srv_name(krb5_context, const char *,
24 28 char **);
25 29 extern kadm5_ret_t kadm5_init_with_password(char *, char *, char *,
26 30 kadm5_config_params *, krb5_ui_4, krb5_ui_4, char **,
27 31 void **);
28 32 extern kadm5_ret_t kadm5_chpass_principal_util(void *, krb5_principal,
29 33 char *, char **, char *, unsigned int);
30 34
31 35 /*
32 36 * Solaris Kerberos:
33 37 * See the function's definition for the description of this interface.
34 38 */
35 39 krb5_error_code __krb5_get_init_creds_password(krb5_context,
36 40 krb5_creds *, krb5_principal, char *, krb5_prompter_fct, void *,
37 41 krb5_deltat, char *, krb5_get_init_creds_opt *, krb5_kdc_rep **);
38 42
39 43 static krb5_error_code
40 44 krb5_get_as_key_password(
41 45 krb5_context context,
42 46 krb5_principal client,
43 47 krb5_enctype etype,
44 48 krb5_prompter_fct prompter,
45 49 void *prompter_data,
46 50 krb5_data *salt,
47 51 krb5_data *params,
48 52 krb5_keyblock *as_key,
49 53 void *gak_data)
50 54 {
51 55 krb5_data *password;
52 56 krb5_error_code ret;
53 57 krb5_data defsalt;
54 58 char *clientstr;
55 59 char promptstr[1024];
56 60 krb5_prompt prompt;
57 61 krb5_prompt_type prompt_type;
58 62
59 63 password = (krb5_data *) gak_data;
60 64
61 65 /* If there's already a key of the correct etype, we're done.
62 66 If the etype is wrong, free the existing key, and make
63 67 a new one.
64 68
65 69 XXX This was the old behavior, and was wrong in hw preauth
66 70 cases. Is this new behavior -- always asking -- correct in all
67 71 cases? */
68 72
69 73 if (as_key->length) {
70 74 if (as_key->enctype != etype) {
71 75 krb5_free_keyblock_contents (context, as_key);
72 76 as_key->length = 0;
73 77 }
74 78 }
75 79
76 80 if (password->data[0] == '\0') {
77 81 if (prompter == NULL)
78 82 prompter = krb5_prompter_posix; /* Solaris Kerberos */
79 83
80 84 if ((ret = krb5_unparse_name(context, client, &clientstr)))
81 85 return(ret);
82 86
83 87 strcpy(promptstr, "Password for ");
84 88 strncat(promptstr, clientstr, sizeof(promptstr)-strlen(promptstr)-1);
85 89 promptstr[sizeof(promptstr)-1] = '\0';
86 90
87 91 free(clientstr);
88 92
89 93 prompt.prompt = promptstr;
90 94 prompt.hidden = 1;
91 95 prompt.reply = password;
92 96 prompt_type = KRB5_PROMPT_TYPE_PASSWORD;
93 97
94 98 /* PROMPTER_INVOCATION */
95 99 krb5int_set_prompt_types(context, &prompt_type);
96 100 if ((ret = (((*prompter)(context, prompter_data, NULL, NULL,
97 101 1, &prompt))))) {
98 102 krb5int_set_prompt_types(context, 0);
99 103 return(ret);
100 104 }
101 105 krb5int_set_prompt_types(context, 0);
102 106 }
103 107
104 108 if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
105 109 if ((ret = krb5_principal2salt(context, client, &defsalt)))
106 110 return(ret);
107 111
108 112 salt = &defsalt;
109 113 } else {
110 114 defsalt.length = 0;
111 115 }
112 116
113 117 ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
114 118 params->data?params:NULL, as_key);
115 119
116 120 if (defsalt.length)
117 121 krb5_xfree(defsalt.data);
118 122
119 123 return(ret);
120 124 }
121 125
122 126 krb5_error_code KRB5_CALLCONV
123 127 krb5_get_init_creds_password(krb5_context context,
124 128 krb5_creds *creds,
125 129 krb5_principal client,
126 130 char *password,
127 131 krb5_prompter_fct prompter,
128 132 void *data,
129 133 krb5_deltat start_time,
130 134 char *in_tkt_service,
131 135 krb5_get_init_creds_opt *options)
132 136 {
133 137 /*
134 138 * Solaris Kerberos:
135 139 * We call our own private function that returns the as_reply back to
136 140 * the caller. This structure contains information, such as
137 141 * key-expiration and last-req fields. Entities such as pam_krb5 can
138 142 * use this information to provide account/password expiration warnings.
139 143 * The original "prompter" interface is not granular enough for PAM,
140 144 * as it will perform all passes w/o coordination with other modules.
141 145 */
142 146 return (__krb5_get_init_creds_password(context, creds, client, password,
143 147 prompter, data, start_time, in_tkt_service, options, NULL));
144 148 }
145 149
146 150 /*
147 151 * Solaris Kerberos:
148 152 * See krb5_get_init_creds_password()'s comments for the justification of this
149 153 * private function. Caller must free ptr_as_reply if non-NULL.
150 154 */
151 155 krb5_error_code KRB5_CALLCONV
152 156 __krb5_get_init_creds_password(
153 157 krb5_context context,
154 158 krb5_creds *creds,
155 159 krb5_principal client,
156 160 char *password,
157 161 krb5_prompter_fct prompter,
158 162 void *data,
159 163 krb5_deltat start_time,
160 164 char *in_tkt_service,
161 165 krb5_get_init_creds_opt *options,
162 166 krb5_kdc_rep **ptr_as_reply)
163 167 {
164 168 krb5_error_code ret, ret2;
165 169 int use_master;
166 170 krb5_kdc_rep *as_reply;
167 171 int tries;
168 172 krb5_creds chpw_creds;
169 173 krb5_data pw0, pw1;
170 174 char banner[1024], pw0array[1024], pw1array[1024];
171 175 krb5_prompt prompt[2];
172 176 krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])];
173 177 krb5_gic_opt_ext *opte = NULL;
174 178 krb5_gic_opt_ext *chpw_opte = NULL;
175 179
176 180 char admin_realm[1024], *cpw_service=NULL, *princ_str=NULL;
177 181 kadm5_config_params params;
178 182 void *server_handle;
179 183 const char *err_msg_1 = NULL;
180 184
181 185 use_master = 0;
182 186 as_reply = NULL;
183 187 memset(&chpw_creds, 0, sizeof(chpw_creds));
184 188
185 189 pw0.data = pw0array;
186 190
187 191 if (password && password[0]) {
188 192 if ((pw0.length = strlen(password)) > sizeof(pw0array)) {
189 193 ret = EINVAL;
190 194 goto cleanup;
191 195 }
192 196 strcpy(pw0.data, password);
193 197 } else {
194 198 pw0.data[0] = '\0';
195 199 pw0.length = sizeof(pw0array);
196 200 }
197 201
198 202 pw1.data = pw1array;
199 203 pw1.data[0] = '\0';
200 204 pw1.length = sizeof(pw1array);
201 205
202 206 ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
203 207 "krb5_get_init_creds_password");
204 208 if (ret)
205 209 goto cleanup;
206 210
207 211 /* first try: get the requested tkt from any kdc */
208 212
209 213 ret = krb5_get_init_creds(context, creds, client, prompter, data,
210 214 start_time, in_tkt_service, opte,
211 215 krb5_get_as_key_password, (void *) &pw0,
212 216 &use_master, &as_reply);
213 217 /* check for success */
214 218
215 219 if (ret == 0)
216 220 goto cleanup;
217 221
218 222 /* If all the kdc's are unavailable, or if the error was due to a
219 223 user interrupt, or preauth errored out, fail */
220 224
221 225 if ((ret == KRB5_KDC_UNREACH) ||
222 226 (ret == KRB5_PREAUTH_FAILED) ||
223 227 (ret == KRB5_LIBOS_PWDINTR) ||
224 228 (ret == KRB5_REALM_CANT_RESOLVE))
225 229 goto cleanup;
226 230
227 231 /* if the reply did not come from the master kdc, try again with
228 232 the master kdc */
229 233
230 234 if (!use_master) {
231 235 use_master = 1;
232 236
233 237 if (as_reply) {
234 238 krb5_free_kdc_rep( context, as_reply);
235 239 as_reply = NULL;
236 240 }
237 241
238 242 err_msg_1 = krb5_get_error_message(context, ret);
239 243
240 244 ret2 = krb5_get_init_creds(context, creds, client, prompter, data,
241 245 start_time, in_tkt_service, opte,
242 246 krb5_get_as_key_password, (void *) &pw0,
243 247 &use_master, &as_reply);
244 248
245 249 if (ret2 == 0) {
246 250 ret = 0;
247 251 goto cleanup;
248 252 }
249 253
250 254 /* if the master is unreachable, return the error from the
251 255 slave we were able to contact or reset the use_master flag */
252 256
253 257 if ((ret2 != KRB5_KDC_UNREACH) &&
254 258 (ret2 != KRB5_REALM_CANT_RESOLVE) &&
255 259 (ret2 != KRB5_REALM_UNKNOWN)) {
256 260 ret = ret2;
257 261 } else {
258 262 use_master = 0;
259 263 /* Solaris - if 2nd try failed, reset 1st err msg */
260 264 if (ret2 && err_msg_1) {
261 265 krb5_set_error_message(context, ret, err_msg_1);
262 266 }
263 267 }
264 268 }
265 269
266 270 /* Solaris Kerberos: 163 resync */
267 271 /* #ifdef USE_LOGIN_LIBRARY */
268 272 if (ret == KRB5KDC_ERR_KEY_EXP)
269 273 goto cleanup; /* Login library will deal appropriately with this error */
270 274 /* #endif */
271 275
272 276 /* at this point, we have an error from the master. if the error
273 277 is not password expired, or if it is but there's no prompter,
274 278 return this error */
275 279
276 280 if ((ret != KRB5KDC_ERR_KEY_EXP) ||
277 281 (prompter == NULL))
278 282 goto cleanup;
279 283
280 284 /* historically the default has been to prompt for password change.
281 285 * if the change password prompt option has not been set, we continue
282 286 * to prompt. Prompting is only disabled if the option has been set
283 287 * and the value has been set to false.
284 288 */
285 289 if (!(options->flags & KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT))
286 290 goto cleanup;
287 291
288 292 /* ok, we have an expired password. Give the user a few chances
289 293 to change it */
290 294
291 295
292 296 /*
293 297 * Solaris Kerberos:
294 298 * Get the correct change password service principal name to use.
295 299 * This is necessary because SEAM based admin servers require
296 300 * a slightly different service principal name than MIT/MS servers.
297 301 */
298 302
299 303 memset((char *) ¶ms, 0, sizeof (params));
300 304
301 305 snprintf(admin_realm, sizeof (admin_realm),
302 306 krb5_princ_realm(context, client)->data);
303 307 params.mask |= KADM5_CONFIG_REALM;
304 308 params.realm = admin_realm;
305 309
306 310 ret=kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service);
307 311
308 312 if (ret != KADM5_OK) {
309 313 syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
310 314 "Kerberos mechanism library: Unable to get change password "
311 315 "service name for realm %s\n"), admin_realm);
312 316 goto cleanup;
313 317 } else {
314 318 ret=0;
315 319 }
316 320
317 321 /* extract the string version of the principal */
318 322 if ((ret = krb5_unparse_name(context, client, &princ_str)))
319 323 goto cleanup;
320 324
321 325 ret = kadm5_init_with_password(princ_str, pw0array, cpw_service,
322 326 ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, NULL,
323 327 &server_handle);
324 328
325 329 if (ret != 0) {
326 330 goto cleanup;
327 331 }
328 332
329 333 prompt[0].prompt = "Enter new password";
330 334 prompt[0].hidden = 1;
331 335 prompt[0].reply = &pw0;
332 336 prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD;
333 337
334 338 prompt[1].prompt = "Enter it again";
335 339 prompt[1].hidden = 1;
336 340 prompt[1].reply = &pw1;
337 341 prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
338 342
339 343 strcpy(banner, "Password expired. You must change it now.");
340 344
341 345 for (tries = 3; tries; tries--) {
342 346 pw0.length = sizeof(pw0array);
343 347 pw1.length = sizeof(pw1array);
344 348
345 349 /* PROMPTER_INVOCATION */
346 350 krb5int_set_prompt_types(context, prompt_types);
347 351 if ((ret = ((*prompter)(context, data, 0, banner,
348 352 sizeof(prompt)/sizeof(prompt[0]), prompt))))
349 353 goto cleanup;
350 354 krb5int_set_prompt_types(context, 0);
351 355
352 356
353 357 if (strcmp(pw0.data, pw1.data) != 0) {
354 358 ret = KRB5_LIBOS_BADPWDMATCH;
355 359 sprintf(banner, "%s. Please try again.", error_message(ret));
356 360 } else if (pw0.length == 0) {
357 361 ret = KRB5_CHPW_PWDNULL;
358 362 sprintf(banner, "%s. Please try again.", error_message(ret));
359 363 } else {
360 364 int result_code;
361 365 krb5_data code_string;
362 366 krb5_data result_string;
363 367
364 368 if ((ret = krb5_change_password(context, &chpw_creds, pw0array,
365 369 &result_code, &code_string,
366 370 &result_string)))
367 371 goto cleanup;
368 372
369 373 /* the change succeeded. go on */
370 374
371 375 if (result_code == 0) {
372 376 krb5_xfree(result_string.data);
373 377 break;
374 378 }
375 379
376 380 /* set this in case the retry loop falls through */
377 381
378 382 ret = KRB5_CHPW_FAIL;
379 383
380 384 if (result_code != KRB5_KPASSWD_SOFTERROR) {
381 385 krb5_xfree(result_string.data);
382 386 goto cleanup;
383 387 }
384 388
385 389 /* the error was soft, so try again */
386 390
387 391 /* 100 is I happen to know that no code_string will be longer
388 392 than 100 chars */
389 393
390 394 if (result_string.length > (sizeof(banner)-100))
391 395 result_string.length = sizeof(banner)-100;
392 396
393 397 sprintf(banner, "%.*s%s%.*s. Please try again.\n",
394 398 (int) code_string.length, code_string.data,
395 399 result_string.length ? ": " : "",
396 400 (int) result_string.length,
397 401 result_string.data ? result_string.data : "");
398 402
399 403 krb5_xfree(code_string.data);
400 404 krb5_xfree(result_string.data);
401 405 }
402 406 }
403 407
404 408 if (ret)
405 409 goto cleanup;
406 410
407 411 /* the password change was successful. Get an initial ticket
408 412 from the master. this is the last try. the return from this
409 413 is final. */
410 414
411 415 ret = krb5_get_init_creds(context, creds, client, prompter, data,
412 416 start_time, in_tkt_service, opte,
413 417 krb5_get_as_key_password, (void *) &pw0,
414 418 &use_master, &as_reply);
415 419
416 420 cleanup:
417 421 if (err_msg_1)
418 422 free((void *)err_msg_1);
419 423
420 424 krb5int_set_prompt_types(context, 0);
421 425 /* if getting the password was successful, then check to see if the
422 426 password is about to expire, and warn if so */
423 427
424 428 if (ret == 0) {
425 429 krb5_timestamp now;
426 430 krb5_last_req_entry **last_req;
427 431 int hours;
428 432
429 433 /* XXX 7 days should be configurable. This is all pretty ad hoc,
430 434 and could probably be improved if I was willing to screw around
431 435 with timezones, etc. */
432 436
433 437 if (prompter &&
434 438 (in_tkt_service && cpw_service &&
435 439 (strcmp(in_tkt_service, cpw_service) != 0)) &&
436 440 ((ret = krb5_timeofday(context, &now)) == 0) &&
437 441 as_reply->enc_part2->key_exp &&
438 442 ((hours = ((as_reply->enc_part2->key_exp-now)/(60*60))) <= 7*24) &&
439 443 (hours >= 0)) {
440 444 if (hours < 1)
441 445 sprintf(banner,
442 446 "Warning: Your password will expire in less than one hour.");
443 447 else if (hours <= 48)
444 448 sprintf(banner, "Warning: Your password will expire in %d hour%s.",
445 449 hours, (hours == 1)?"":"s");
446 450 else
447 451 sprintf(banner, "Warning: Your password will expire in %d days.",
448 452 hours/24);
449 453
450 454 /* ignore an error here */
451 455 /* PROMPTER_INVOCATION */
452 456 (*prompter)(context, data, 0, banner, 0, 0);
453 457 } else if (prompter &&
454 458 (!in_tkt_service ||
455 459 (strcmp(in_tkt_service, "kadmin/changepw") != 0)) &&
456 460 as_reply->enc_part2 && as_reply->enc_part2->last_req) {
457 461 /*
458 462 * Check the last_req fields
459 463 */
460 464
461 465 for (last_req = as_reply->enc_part2->last_req; *last_req; last_req++)
462 466 if ((*last_req)->lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
463 467 (*last_req)->lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
464 468 krb5_deltat delta;
465 469 char ts[256];
466 470
467 471 if ((ret = krb5_timeofday(context, &now)))
468 472 break;
469 473
470 474 if ((ret = krb5_timestamp_to_string((*last_req)->value,
471 475 ts, sizeof(ts))))
472 476 break;
473 477
474 478 delta = (*last_req)->value - now;
475 479
476 480 if (delta < 3600)
477 481 sprintf(banner,
478 482 "Warning: Your password will expire in less than one "
479 483 "hour on %s", ts);
480 484 else if (delta < 86400*2)
481 485 sprintf(banner,
482 486 "Warning: Your password will expire in %d hour%s on %s",
483 487 delta / 3600, delta < 7200 ? "" : "s", ts);
484 488 else
485 489 sprintf(banner,
486 490 "Warning: Your password will expire in %d days on %s",
487 491 delta / 86400, ts);
488 492 /* ignore an error here */
489 493 /* PROMPTER_INVOCATION */
490 494 (*prompter)(context, data, 0, banner, 0, 0);
491 495 }
492 496 }
493 497 }
494 498
495 499 free(cpw_service);
496 500 free(princ_str);
497 501 if (opte && krb5_gic_opt_is_shadowed(opte))
498 502 krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
499 503 memset(pw0array, 0, sizeof(pw0array));
500 504 memset(pw1array, 0, sizeof(pw1array));
501 505 krb5_free_cred_contents(context, &chpw_creds);
502 506 /*
503 507 * Solaris Kerberos:
504 508 * Argument, ptr_as_reply, being returned to caller if success and non-NULL.
505 509 */
506 510 if (as_reply != NULL) {
507 511 if (ptr_as_reply == NULL)
508 512 krb5_free_kdc_rep(context, as_reply);
509 513 else
510 514 *ptr_as_reply = as_reply;
511 515 }
↓ open down ↓ |
498 lines elided |
↑ open up ↑ |
512 516
513 517 return(ret);
514 518 }
515 519 krb5_error_code krb5int_populate_gic_opt (
516 520 krb5_context context, krb5_gic_opt_ext **opte,
517 521 krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes,
518 522 krb5_preauthtype *pre_auth_types, krb5_creds *creds)
519 523 {
520 524 int i;
521 525 krb5_int32 starttime;
522 - krb5_get_init_creds_opt *opt;
526 + krb5_get_init_creds_opt opt;
523 527
524 528
525 - krb5_get_init_creds_opt_init(opt);
529 + krb5_get_init_creds_opt_init(&opt);
526 530 if (addrs)
527 - krb5_get_init_creds_opt_set_address_list(opt, (krb5_address **) addrs);
531 + krb5_get_init_creds_opt_set_address_list(&opt, (krb5_address **) addrs);
528 532 if (ktypes) {
529 533 for (i=0; ktypes[i]; i++);
530 534 if (i)
531 - krb5_get_init_creds_opt_set_etype_list(opt, ktypes, i);
535 + krb5_get_init_creds_opt_set_etype_list(&opt, ktypes, i);
532 536 }
533 537 if (pre_auth_types) {
534 538 for (i=0; pre_auth_types[i]; i++);
535 539 if (i)
536 - krb5_get_init_creds_opt_set_preauth_list(opt, pre_auth_types, i);
540 + krb5_get_init_creds_opt_set_preauth_list(&opt, pre_auth_types, i);
537 541 }
538 542 if (options&KDC_OPT_FORWARDABLE)
539 - krb5_get_init_creds_opt_set_forwardable(opt, 1);
540 - else krb5_get_init_creds_opt_set_forwardable(opt, 0);
543 + krb5_get_init_creds_opt_set_forwardable(&opt, 1);
544 + else krb5_get_init_creds_opt_set_forwardable(&opt, 0);
541 545 if (options&KDC_OPT_PROXIABLE)
542 - krb5_get_init_creds_opt_set_proxiable(opt, 1);
543 - else krb5_get_init_creds_opt_set_proxiable(opt, 0);
546 + krb5_get_init_creds_opt_set_proxiable(&opt, 1);
547 + else krb5_get_init_creds_opt_set_proxiable(&opt, 0);
544 548 if (creds && creds->times.endtime) {
545 549 krb5_timeofday(context, &starttime);
546 550 if (creds->times.starttime) starttime = creds->times.starttime;
547 - krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime);
551 + krb5_get_init_creds_opt_set_tkt_life(&opt, creds->times.endtime - starttime);
548 552 }
549 - return krb5int_gic_opt_to_opte(context, opt, opte, 0,
553 + return krb5int_gic_opt_to_opte(context, &opt, opte, 0,
550 554 "krb5int_populate_gic_opt");
551 555 }
552 556
553 557 /*
554 558 Rewrites get_in_tkt in terms of newer get_init_creds API.
555 559 Attempts to get an initial ticket for creds->client to use server
556 560 creds->server, (realm is taken from creds->client), with options
557 561 options, and using creds->times.starttime, creds->times.endtime,
558 562 creds->times.renew_till as from, till, and rtime.
559 563 creds->times.renew_till is ignored unless the RENEWABLE option is requested.
560 564
561 565 If addrs is non-NULL, it is used for the addresses requested. If it is
562 566 null, the system standard addresses are used.
563 567
564 568 If password is non-NULL, it is converted using the cryptosystem entry
565 569 point for a string conversion routine, seeded with the client's name.
566 570 If password is passed as NULL, the password is read from the terminal,
567 571 and then converted into a key.
568 572
569 573 A succesful call will place the ticket in the credentials cache ccache.
570 574
571 575 returns system errors, encryption errors
572 576 */
573 577 krb5_error_code KRB5_CALLCONV
574 578 krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
575 579 krb5_address *const *addrs, krb5_enctype *ktypes,
576 580 krb5_preauthtype *pre_auth_types,
577 581 const char *password, krb5_ccache ccache,
578 582 krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
579 583 {
580 584 krb5_error_code retval;
581 585 krb5_data pw0;
582 586 char pw0array[1024];
583 587 char * server;
584 588 krb5_principal server_princ, client_princ;
585 589 int use_master = 0;
586 590 krb5_gic_opt_ext *opte = NULL;
587 591
588 592 pw0array[0] = '\0';
589 593 pw0.data = pw0array;
590 594 if (password) {
591 595 pw0.length = strlen(password);
592 596 if (pw0.length > sizeof(pw0array))
593 597 return EINVAL;
594 598 strncpy(pw0.data, password, sizeof(pw0array));
595 599 if (pw0.length == 0)
596 600 pw0.length = sizeof(pw0array);
597 601 } else {
598 602 pw0.length = sizeof(pw0array);
599 603 }
600 604 retval = krb5int_populate_gic_opt(context, &opte,
601 605 options, addrs, ktypes,
602 606 pre_auth_types, creds);
603 607 if (retval)
604 608 return (retval);
605 609 retval = krb5_unparse_name( context, creds->server, &server);
606 610 if (retval) {
607 611 return (retval);
608 612 krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
609 613 }
610 614 server_princ = creds->server;
611 615 client_princ = creds->client;
612 616 retval = krb5_get_init_creds (context,
613 617 creds, creds->client,
614 618 krb5_prompter_posix, NULL,
615 619 0, server, opte,
616 620 krb5_get_as_key_password, &pw0,
617 621 &use_master, ret_as_reply);
618 622 krb5_free_unparsed_name( context, server);
619 623 krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
620 624 if (retval) {
621 625 return (retval);
622 626 }
623 627 if (creds->server)
624 628 krb5_free_principal( context, creds->server);
625 629 if (creds->client)
626 630 krb5_free_principal( context, creds->client);
627 631 creds->client = client_princ;
628 632 creds->server = server_princ;
629 633 /* store it in the ccache! */
630 634 if (ccache)
631 635 if ((retval = krb5_cc_store_cred(context, ccache, creds)))
632 636 return (retval);
633 637 return retval;
634 638 }
635 639
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX