Changeset 745 for trunk/server/source3/libads/kerberos_verify.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/libads/kerberos_verify.c
r480 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 kerberos utility library 4 4 Copyright (C) Andrew Tridgell 2001 5 5 Copyright (C) Remus Koos 2001 6 Copyright (C) Luke Howard 2003 6 Copyright (C) Luke Howard 2003 7 7 Copyright (C) Guenther Deschner 2003, 2005 8 8 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 9 9 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 10 10 Copyright (C) Jeremy Allison 2007 11 11 12 12 This program is free software; you can redistribute it and/or modify 13 13 it under the terms of the GNU General Public License as published by 14 14 the Free Software Foundation; either version 3 of the License, or 15 15 (at your option) any later version. 16 16 17 17 This program is distributed in the hope that it will be useful, 18 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 20 GNU General Public License for more details. 21 21 22 22 You should have received a copy of the GNU General Public License 23 23 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 26 26 #include "includes.h" 27 27 #include "smb_krb5.h" 28 #include "libads/kerberos_proto.h" 29 #include "secrets.h" 30 #include "../librpc/gen_ndr/krb5pac.h" 28 31 29 32 #ifdef HAVE_KRB5 … … 114 117 } 115 118 116 /****************************************************************************** ****117 Try to verify a ticket using the system keytab... the system keytab has kvno -1 entries, so118 it's more like what microsoft does... see comment in utils/net_ads.c in the119 ads_keytab_add_entry function for details.120 ****************************************************************************** *****/119 /****************************************************************************** 120 Try to verify a ticket using the system keytab... the system keytab has 121 kvno -1 entries, so it's more like what microsoft does... see comment in 122 utils/net_ads.c in the ads_keytab_add_entry function for details. 123 ******************************************************************************/ 121 124 122 125 static bool ads_keytab_verify_ticket(krb5_context context, … … 132 135 krb5_kt_cursor kt_cursor; 133 136 krb5_keytab_entry kt_entry; 134 char *valid_princ_formats[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; 137 char *valid_princ_formats[7] = { NULL, NULL, NULL, 138 NULL, NULL, NULL, NULL }; 135 139 char *entry_princ_s = NULL; 136 140 fstring my_name, my_fqdn; … … 138 142 int number_matched_principals = 0; 139 143 krb5_data packet; 144 int err; 140 145 141 146 *pp_tkt = NULL; … … 152 157 name_to_fqdn(my_fqdn, global_myname()); 153 158 154 if (asprintf(&valid_princ_formats[0], "%s$@%s", my_name, lp_realm()) == -1) { 155 goto out; 156 } 157 if (asprintf(&valid_princ_formats[1], "host/%s@%s", my_name, lp_realm()) == -1) { 158 goto out; 159 } 160 if (asprintf(&valid_princ_formats[2], "host/%s@%s", my_fqdn, lp_realm()) == -1) { 161 goto out; 162 } 163 if (asprintf(&valid_princ_formats[3], "host/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) { 164 goto out; 165 } 166 if (asprintf(&valid_princ_formats[4], "cifs/%s@%s", my_name, lp_realm()) == -1) { 167 goto out; 168 } 169 if (asprintf(&valid_princ_formats[5], "cifs/%s@%s", my_fqdn, lp_realm()) == -1) { 170 goto out; 171 } 172 if (asprintf(&valid_princ_formats[6], "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) { 159 err = asprintf(&valid_princ_formats[0], 160 "%s$@%s", my_name, lp_realm()); 161 if (err == -1) { 162 goto out; 163 } 164 err = asprintf(&valid_princ_formats[1], 165 "host/%s@%s", my_name, lp_realm()); 166 if (err == -1) { 167 goto out; 168 } 169 err = asprintf(&valid_princ_formats[2], 170 "host/%s@%s", my_fqdn, lp_realm()); 171 if (err == -1) { 172 goto out; 173 } 174 err = asprintf(&valid_princ_formats[3], 175 "host/%s.%s@%s", my_name, lp_realm(), lp_realm()); 176 if (err == -1) { 177 goto out; 178 } 179 err = asprintf(&valid_princ_formats[4], 180 "cifs/%s@%s", my_name, lp_realm()); 181 if (err == -1) { 182 goto out; 183 } 184 err = asprintf(&valid_princ_formats[5], 185 "cifs/%s@%s", my_fqdn, lp_realm()); 186 if (err == -1) { 187 goto out; 188 } 189 err = asprintf(&valid_princ_formats[6], 190 "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()); 191 if (err == -1) { 173 192 goto out; 174 193 } … … 179 198 ret = smb_krb5_open_keytab(context, NULL, False, &keytab); 180 199 if (ret) { 181 DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_open_keytab failed (%s)\n", error_message(ret))); 200 DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n", 201 error_message(ret))); 182 202 goto out; 183 203 } … … 189 209 ret = krb5_kt_start_seq_get(context, keytab, &kt_cursor); 190 210 if (ret) { 191 DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", error_message(ret))); 211 DEBUG(1, (__location__ ": krb5_kt_start_seq_get failed (%s)\n", 212 error_message(ret))); 192 213 goto out; 193 214 } 194 215 195 while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) { 196 ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &entry_princ_s); 216 while (!auth_ok && 217 (krb5_kt_next_entry(context, keytab, 218 &kt_entry, &kt_cursor) == 0)) { 219 ret = smb_krb5_unparse_name(talloc_tos(), context, 220 kt_entry.principal, 221 &entry_princ_s); 197 222 if (ret) { 198 DEBUG(1, ( "ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",199 error_message(ret)));223 DEBUG(1, (__location__ ": smb_krb5_unparse_name " 224 "failed (%s)\n", error_message(ret))); 200 225 goto out; 201 226 } … … 212 237 *pp_tkt = NULL; 213 238 214 ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, &packet, 215 kt_entry.principal, keytab, 216 NULL, pp_tkt, keyblock); 239 ret = krb5_rd_req_return_keyblock_from_keytab(context, 240 &auth_context, &packet, 241 kt_entry.principal, keytab, 242 NULL, pp_tkt, keyblock); 217 243 218 244 if (ret) { 219 DEBUG(10,("ads_keytab_verify_ticket: " 220 "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n", 221 entry_princ_s, error_message(ret))); 222 223 /* workaround for MIT: 245 DEBUG(10, (__location__ ": krb5_rd_req_return" 246 "_keyblock_from_keytab(%s) " 247 "failed: %s\n", entry_princ_s, 248 error_message(ret))); 249 250 /* workaround for MIT: 224 251 * as krb5_ktfile_get_entry will explicitly 225 252 * close the krb5_keytab as soon as krb5_rd_req … … 228 255 * there is no point in querying more keytab 229 256 * entries - Guenther */ 230 231 if (ret == KRB5KRB_AP_ERR_TKT_NYV || 257 258 if (ret == KRB5KRB_AP_ERR_TKT_NYV || 232 259 ret == KRB5KRB_AP_ERR_TKT_EXPIRED || 233 260 ret == KRB5KRB_AP_ERR_SKEW) { … … 235 262 } 236 263 } else { 237 DEBUG(3,("ads_keytab_verify_ticket: " 238 "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n", 239 entry_princ_s)); 264 DEBUG(3, (__location__ ": krb5_rd_req_return" 265 "_keyblock_from_keytab succeeded " 266 "for principal %s\n", 267 entry_princ_s)); 240 268 auth_ok = True; 241 269 break; … … 254 282 ZERO_STRUCT(kt_cursor); 255 283 256 257 284 out: 285 258 286 for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) { 259 287 SAFE_FREE(valid_princ_formats[i]); 260 288 } 261 289 262 290 if (!auth_ok) { 263 291 if (!number_matched_principals) { 264 DEBUG(3, ("ads_keytab_verify_ticket: no keytab principals matched expected file service name.\n")); 292 DEBUG(3, (__location__ ": no keytab principals " 293 "matched expected file service name.\n")); 265 294 } else { 266 DEBUG(3, ("ads_keytab_verify_ticket: krb5_rd_req failed for all %d matched keytab principals\n", 267 number_matched_principals)); 295 DEBUG(3, (__location__ ": krb5_rd_req failed for " 296 "all %d matched keytab principals\n", 297 number_matched_principals)); 268 298 } 269 299 } … … 274 304 krb5_keytab_entry zero_kt_entry; 275 305 ZERO_STRUCT(zero_kt_entry); 276 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) { 306 if (memcmp(&zero_kt_entry, &kt_entry, 307 sizeof(krb5_keytab_entry))) { 277 308 smb_krb5_kt_free_entry(context, &kt_entry); 278 309 } … … 282 313 krb5_kt_cursor zero_csr; 283 314 ZERO_STRUCT(zero_csr); 284 if ((memcmp(&kt_cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) { 315 if ((memcmp(&kt_cursor, &zero_csr, 316 sizeof(krb5_kt_cursor)) != 0) && keytab) { 285 317 krb5_kt_end_seq_get(context, keytab, &kt_cursor); 286 318 } … … 294 326 } 295 327 296 /***************************************************************************** *****328 /***************************************************************************** 297 329 Try to verify a ticket using the secrets.tdb. 298 ****************************************************************************** *****/330 ******************************************************************************/ 299 331 300 332 static krb5_error_code ads_secrets_verify_ticket(krb5_context context, … … 312 344 /* Let's make some room for 2 password (old and new)*/ 313 345 krb5_data passwords[2]; 314 krb5_enctype enctypes[] = { 315 #if defined(ENCTYPE_ARCFOUR_HMAC) 346 krb5_enctype enctypes[] = { 316 347 ENCTYPE_ARCFOUR_HMAC, 317 #endif 318 ENCTYPE_DES_CBC_CRC, 319 ENCTYPE_DES_CBC_MD5, 348 ENCTYPE_DES_CBC_CRC, 349 ENCTYPE_DES_CBC_MD5, 320 350 ENCTYPE_NULL 321 351 }; … … 335 365 } 336 366 337 password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); 367 password_s = secrets_fetch_machine_password(lp_workgroup(), 368 NULL, NULL); 338 369 if (!password_s) { 339 DEBUG(1,( "ads_secrets_verify_ticket: failed to fetch machine password\n"));370 DEBUG(1,(__location__ ": failed to fetch machine password\n")); 340 371 *perr = KRB5_LIBOS_CANTREADPWD; 341 372 return False; … … 347 378 password_s = secrets_fetch_prev_machine_password(lp_workgroup()); 348 379 if (password_s) { 349 DEBUG(10, ("ads_secrets_verify_ticket: found previous password\n"));380 DEBUG(10, (__location__ ": found previous password\n")); 350 381 passwords[1].data = password_s; 351 382 passwords[1].length = strlen(password_s); … … 357 388 packet.data = (char *)ticket->data; 358 389 359 /* We need to setup a auth context with each possible encoding type in turn. */ 390 /* We need to setup a auth context with each possible encoding type 391 * in turn. */ 360 392 for (j=0; j<2 && passwords[j].length; j++) { 361 393 … … 368 400 } 369 401 370 if (create_kerberos_key_from_string(context, host_princ, &passwords[j], key, enctypes[i], false)) { 402 if (create_kerberos_key_from_string(context, 403 host_princ, &passwords[j], 404 key, enctypes[i], false)) { 371 405 SAFE_FREE(key); 372 406 continue; 373 407 } 374 408 375 krb5_auth_con_setuseruserkey(context, auth_context, key); 376 377 if (!(ret = krb5_rd_req(context, &auth_context, &packet, 378 NULL, 379 NULL, NULL, pp_tkt))) { 380 DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n", 381 (unsigned int)enctypes[i] )); 409 krb5_auth_con_setuseruserkey(context, 410 auth_context, key); 411 412 if (!(ret = krb5_rd_req(context, &auth_context, 413 &packet, NULL, NULL, 414 NULL, pp_tkt))) { 415 DEBUG(10, (__location__ ": enc type [%u] " 416 "decrypted message !\n", 417 (unsigned int)enctypes[i])); 382 418 auth_ok = True; 383 419 cont = false; … … 388 424 389 425 DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10, 390 ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n", 391 (unsigned int)enctypes[i], error_message(ret))); 392 393 /* successfully decrypted but ticket is just not valid at the moment */ 426 (__location__ ": enc type [%u] failed to " 427 "decrypt with error %s\n", 428 (unsigned int)enctypes[i], 429 error_message(ret))); 430 431 /* successfully decrypted but ticket is just not 432 * valid at the moment */ 394 433 if (ret == KRB5KRB_AP_ERR_TKT_NYV || 395 434 ret == KRB5KRB_AP_ERR_TKT_EXPIRED || … … 417 456 } 418 457 419 /***************************************************************************** *****420 Verify an incoming ticket and parse out the principal name and 458 /***************************************************************************** 459 Verify an incoming ticket and parse out the principal name and 421 460 authorization_data if available. 422 ****************************************************************************** *****/461 ******************************************************************************/ 423 462 424 463 NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, … … 427 466 const DATA_BLOB *ticket, 428 467 char **principal, 429 struct PAC_ DATA **pac_data,468 struct PAC_LOGON_INFO **logon_info, 430 469 DATA_BLOB *ap_rep, 431 470 DATA_BLOB *session_key, … … 443 482 time_t authtime; 444 483 krb5_error_code ret = 0; 445 int flags = 0; 484 int flags = 0; 446 485 krb5_principal host_princ = NULL; 447 486 krb5_const_principal client_principal = NULL; … … 455 494 456 495 *principal = NULL; 457 * pac_data= NULL;496 *logon_info = NULL; 458 497 *ap_rep = data_blob_null; 459 498 *session_key = data_blob_null; … … 462 501 ret = krb5_init_context(&context); 463 502 if (ret) { 464 DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret))); 503 DEBUG(1, (__location__ ": krb5_init_context failed (%s)\n", 504 error_message(ret))); 465 505 return NT_STATUS_LOGON_FAILURE; 466 506 } … … 472 512 ret = krb5_set_default_realm(context, realm); 473 513 if (ret) { 474 DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret))); 514 DEBUG(1, (__location__ ": krb5_set_default_realm " 515 "failed (%s)\n", error_message(ret))); 475 516 goto out; 476 517 } … … 482 523 ret = krb5_auth_con_init(context, &auth_context); 483 524 if (ret) { 484 DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret))); 525 DEBUG(1, (__location__ ": krb5_auth_con_init failed (%s)\n", 526 error_message(ret))); 485 527 goto out; 486 528 } … … 500 542 ret = smb_krb5_parse_name(context, host_princ_s, &host_princ); 501 543 if (ret) { 502 DEBUG(1, ("ads_verify_ticket: smb_krb5_parse_name(%s) failed (%s)\n",503 504 goto out; 505 } 506 507 508 if ( use_replay_cache) {509 510 /* Lock a mutex surrounding the replay as there is no 511 locking in the MIT krb5 code surrounding the replay 544 DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) " 545 "failed (%s)\n", host_princ_s, error_message(ret))); 546 goto out; 547 } 548 549 550 if (use_replay_cache) { 551 552 /* Lock a mutex surrounding the replay as there is no 553 locking in the MIT krb5 code surrounding the replay 512 554 cache... */ 513 555 514 mutex = grab_named_mutex(talloc_tos(), "replay cache mutex",515 10);556 mutex = grab_named_mutex(talloc_tos(), 557 "replay cache mutex", 10); 516 558 if (mutex == NULL) { 517 DEBUG(1, ("ads_verify_ticket: unable to protect"518 "replaycache with mutex.\n"));559 DEBUG(1, (__location__ ": unable to protect replay " 560 "cache with mutex.\n")); 519 561 ret = KRB5_CC_IO; 520 562 goto out; 521 563 } 522 564 523 /* JRA. We must set the rcache here. This will prevent 565 /* JRA. We must set the rcache here. This will prevent 524 566 replay attacks. */ 525 526 ret = krb5_get_server_rcache(context, 527 krb5_princ_component(context, host_princ, 0), 528 &rcache); 567 568 ret = krb5_get_server_rcache( 569 context, 570 krb5_princ_component(context, host_princ, 0), 571 &rcache); 529 572 if (ret) { 530 DEBUG(1, ("ads_verify_ticket: krb5_get_server_rcache "531 "failed (%s)\n", error_message(ret)));573 DEBUG(1, (__location__ ": krb5_get_server_rcache " 574 "failed (%s)\n", error_message(ret))); 532 575 goto out; 533 576 } … … 535 578 ret = krb5_auth_con_setrcache(context, auth_context, rcache); 536 579 if (ret) { 537 DEBUG(1, ("ads_verify_ticket: krb5_auth_con_setrcache "538 "failed (%s)\n", error_message(ret)));580 DEBUG(1, (__location__ ": krb5_auth_con_setrcache " 581 "failed (%s)\n", error_message(ret))); 539 582 goto out; 540 583 } … … 575 618 } 576 619 577 if ( use_replay_cache ) {620 if (use_replay_cache) { 578 621 TALLOC_FREE(mutex); 579 622 #if 0 … … 583 626 } 584 627 #endif 585 } 628 } 586 629 587 630 if (!auth_ok) { 588 DEBUG(3, ("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n",589 error_message(ret)));631 DEBUG(3, (__location__ ": krb5_rd_req with auth " 632 "failed (%s)\n", error_message(ret))); 590 633 /* Try map the error return in case it's something like 591 634 * a clock skew error. 592 635 */ 593 636 sret = krb5_to_nt_status(ret); 594 if (NT_STATUS_IS_OK(sret) || NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) { 637 if (NT_STATUS_IS_OK(sret) || 638 NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) { 595 639 sret = NT_STATUS_LOGON_FAILURE; 596 640 } 597 DEBUG(10, ("ads_verify_ticket: returning error %s\n",598 nt_errstr(sret) ));599 goto out; 600 } 601 641 DEBUG(10, (__location__ ": returning error %s\n", 642 nt_errstr(sret) )); 643 goto out; 644 } 645 602 646 authtime = get_authtime_from_tkt(tkt); 603 647 client_principal = get_principal_from_tkt(tkt); … … 605 649 ret = krb5_mk_rep(context, auth_context, &packet); 606 650 if (ret) { 607 DEBUG(3, ("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n",608 error_message(ret)));651 DEBUG(3, (__location__ ": Failed to generate mutual " 652 "authentication reply (%s)\n", error_message(ret))); 609 653 goto out; 610 654 } … … 616 660 } 617 661 618 get_krb5_smb_session_key(context, auth_context, session_key, True); 619 dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length); 662 get_krb5_smb_session_key(mem_ctx, context, 663 auth_context, session_key, true); 664 dump_data_pw("SMB session key (from ticket)\n", 665 session_key->data, session_key->length); 620 666 621 667 #if 0 … … 623 669 #endif 624 670 625 /* continue when no PAC is retrieved or we couldn't decode the PAC 671 /* continue when no PAC is retrieved or we couldn't decode the PAC 626 672 (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set, or 627 673 Kerberos tickets encrypted using a DES key) - Guenther */ … … 629 675 got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt); 630 676 if (!got_auth_data) { 631 DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n")); 677 DEBUG(3, (__location__ ": did not retrieve auth data. " 678 "continuing without PAC\n")); 632 679 } 633 680 634 681 if (got_auth_data) { 635 pac_ret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data); 682 struct PAC_DATA *pac_data; 683 pac_ret = decode_pac_data(mem_ctx, &auth_data, context, 684 keyblock, client_principal, 685 authtime, &pac_data); 686 data_blob_free(&auth_data); 636 687 if (!NT_STATUS_IS_OK(pac_ret)) { 637 DEBUG(3,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(pac_ret))); 638 *pac_data = NULL; 639 } 640 data_blob_free(&auth_data); 688 DEBUG(3, (__location__ ": failed to decode " 689 "PAC_DATA: %s\n", nt_errstr(pac_ret))); 690 } else { 691 uint32_t i; 692 for (i = 0; i < pac_data->num_buffers; i++) { 693 694 if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { 695 continue; 696 } 697 698 *logon_info = pac_data->buffers[i].info->logon_info.info; 699 } 700 701 if (!*logon_info) { 702 DEBUG(1, ("correctly decoded PAC but found " 703 "no logon_info! " 704 "This should not happen\n")); 705 return NT_STATUS_INVALID_USER_BUFFER; 706 } 707 } 641 708 } 642 709 … … 659 726 #endif 660 727 661 if ((ret = smb_krb5_unparse_name(mem_ctx, context, client_principal, principal))) { 662 DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n", 663 error_message(ret))); 728 ret = smb_krb5_unparse_name(mem_ctx, context, 729 client_principal, principal); 730 if (ret) { 731 DEBUG(3, (__location__ ": smb_krb5_unparse_name " 732 "failed (%s)\n", error_message(ret))); 664 733 sret = NT_STATUS_LOGON_FAILURE; 665 734 goto out; … … 668 737 sret = NT_STATUS_OK; 669 738 670 739 out: 671 740 672 741 TALLOC_FREE(mutex);
Note:
See TracChangeset
for help on using the changeset viewer.