1/* 2 Unix SMB/CIFS implementation. 3 kerberos authorization data (PAC) utility library 4 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22 23#ifdef HAVE_KRB5 24 25static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data) 26{ 27 DATA_BLOB pac_contents; 28 ASN1_DATA data; 29 int data_type; 30 31 asn1_load(&data, *auth_data); 32 asn1_start_tag(&data, ASN1_SEQUENCE(0)); 33 asn1_start_tag(&data, ASN1_SEQUENCE(0)); 34 asn1_start_tag(&data, ASN1_CONTEXT(0)); 35 asn1_read_Integer(&data, &data_type); 36 asn1_end_tag(&data); 37 asn1_start_tag(&data, ASN1_CONTEXT(1)); 38 asn1_read_OctetString(&data, &pac_contents); 39 asn1_end_tag(&data); 40 asn1_end_tag(&data); 41 asn1_end_tag(&data); 42 asn1_free(&data); 43 return pac_contents; 44} 45 46static BOOL pac_io_unknown_type_10(const char *desc, UNKNOWN_TYPE_10 *type_10, 47 prs_struct *ps, int depth) 48{ 49 if (NULL == type_10) 50 return False; 51 52 prs_debug(ps, depth, desc, "pac_io_unknown_type_10"); 53 depth++; 54 55 if (!smb_io_time("unknown_time", &type_10->unknown_time, ps, depth)) 56 return False; 57 58 if (!prs_uint16("len", ps, depth, &type_10->len)) 59 return False; 60 61 if (UNMARSHALLING(ps) && type_10->len) { 62 type_10->username = (uint16 *) prs_alloc_mem(ps, type_10->len); 63 if (!type_10->username) { 64 DEBUG(3, ("No memory available\n")); 65 return False; 66 } 67 } 68 69 if (!prs_uint16s(True, "name", ps, depth, type_10->username, 70 (type_10->len / sizeof(uint16)))) 71 return False; 72 73 return True; 74 75} 76 77 78static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr, 79 prs_struct *ps, int depth) 80{ 81 if (NULL == sid_and_attr) 82 return False; 83 84 prs_debug(ps, depth, desc, "pac_io_krb_sids"); 85 depth++; 86 87 if (UNMARSHALLING(ps)) { 88 sid_and_attr->sid = 89 (DOM_SID2 * ) prs_alloc_mem(ps, sizeof(DOM_SID2)); 90 if (!sid_and_attr->sid) { 91 DEBUG(3, ("No memory available\n")); 92 return False; 93 } 94 } 95 96 if(!smb_io_dom_sid2("sid", sid_and_attr->sid, ps, depth)) 97 return False; 98 99 return True; 100} 101 102 103static BOOL pac_io_krb_attrs(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr, 104 prs_struct *ps, int depth) 105{ 106 if (NULL == sid_and_attr) 107 return False; 108 109 prs_debug(ps, depth, desc, "pac_io_krb_attrs"); 110 depth++; 111 112 if (!prs_uint32("sid_ptr", ps, depth, &sid_and_attr->sid_ptr)) 113 return False; 114 if (!prs_uint32("attrs", ps, depth, &sid_and_attr->attrs)) 115 return False; 116 117 return True; 118} 119 120static BOOL pac_io_krb_sid_and_attr_array(const char *desc, 121 KRB_SID_AND_ATTR_ARRAY *array, 122 uint32 num, 123 prs_struct *ps, int depth) 124{ 125 int i; 126 127 if (NULL == array) 128 return False; 129 130 prs_debug(ps, depth, desc, "pac_io_krb_sid_and_attr_array"); 131 depth++; 132 133 134 if (!prs_uint32("count", ps, depth, &array->count)) 135 return False; 136 137 if (UNMARSHALLING(ps)) { 138 array->krb_sid_and_attrs = (KRB_SID_AND_ATTRS *) 139 prs_alloc_mem(ps, sizeof(KRB_SID_AND_ATTRS) * num); 140 if (!array->krb_sid_and_attrs) { 141 DEBUG(3, ("No memory available\n")); 142 return False; 143 } 144 } 145 146 for (i=0; i<num; i++) { 147 if (!pac_io_krb_attrs(desc, 148 &array->krb_sid_and_attrs[i], 149 ps, depth)) 150 return False; 151 152 } 153 for (i=0; i<num; i++) { 154 if (!pac_io_krb_sids(desc, 155 &array->krb_sid_and_attrs[i], 156 ps, depth)) 157 return False; 158 159 } 160 161 return True; 162 163} 164 165static BOOL pac_io_group_membership(const char *desc, 166 GROUP_MEMBERSHIP *membership, 167 prs_struct *ps, int depth) 168{ 169 if (NULL == membership) 170 return False; 171 172 prs_debug(ps, depth, desc, "pac_io_group_membership"); 173 depth++; 174 175 if (!prs_uint32("rid", ps, depth, &membership->rid)) 176 return False; 177 if (!prs_uint32("attrs", ps, depth, &membership->attrs)) 178 return False; 179 180 return True; 181} 182 183 184static BOOL pac_io_group_membership_array(const char *desc, 185 GROUP_MEMBERSHIP_ARRAY *array, 186 uint32 num, 187 prs_struct *ps, int depth) 188{ 189 int i; 190 191 if (NULL == array) 192 return False; 193 194 prs_debug(ps, depth, desc, "pac_io_group_membership_array"); 195 depth++; 196 197 198 if (!prs_uint32("count", ps, depth, &array->count)) 199 return False; 200 201 if (UNMARSHALLING(ps)) { 202 array->group_membership = (GROUP_MEMBERSHIP *) 203 prs_alloc_mem(ps, sizeof(GROUP_MEMBERSHIP) * num); 204 if (!array->group_membership) { 205 DEBUG(3, ("No memory available\n")); 206 return False; 207 } 208 } 209 210 for (i=0; i<num; i++) { 211 if (!pac_io_group_membership(desc, 212 &array->group_membership[i], 213 ps, depth)) 214 return False; 215 216 } 217 218 return True; 219 220} 221 222static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 223 prs_struct *ps, int depth) 224{ 225 uint32 garbage; 226 if (NULL == info) 227 return False; 228 229 prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); 230 depth++; 231 232 if (!prs_uint32("unknown", ps, depth, &garbage)) 233 return False; 234 if (!prs_uint32("unknown", ps, depth, &garbage)) 235 return False; 236 if (!prs_uint32("bufferlen", ps, depth, &garbage)) 237 return False; 238 if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) 239 return False; 240 if (!prs_uint32("pointer", ps, depth, &garbage)) 241 return False; 242 243 if (!smb_io_time("logon_time", &info->logon_time, ps, depth)) 244 return False; 245 if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth)) 246 return False; 247 if (!smb_io_time("kickoff_time", &info->kickoff_time, ps, depth)) 248 return False; 249 if (!smb_io_time("pass_last_set_time", &info->pass_last_set_time, 250 ps, depth)) 251 return False; 252 if (!smb_io_time("pass_can_change_time", &info->pass_can_change_time, 253 ps, depth)) 254 return False; 255 if (!smb_io_time("pass_must_change_time", &info->pass_must_change_time, 256 ps, depth)) 257 return False; 258 259 if (!smb_io_unihdr("hdr_user_name", &info->hdr_user_name, ps, depth)) 260 return False; 261 if (!smb_io_unihdr("hdr_full_name", &info->hdr_full_name, ps, depth)) 262 return False; 263 if (!smb_io_unihdr("hdr_logon_script", &info->hdr_logon_script, 264 ps, depth)) 265 return False; 266 if (!smb_io_unihdr("hdr_profile_path", &info->hdr_profile_path, 267 ps, depth)) 268 return False; 269 if (!smb_io_unihdr("hdr_home_dir", &info->hdr_home_dir, ps, depth)) 270 return False; 271 if (!smb_io_unihdr("hdr_dir_drive", &info->hdr_dir_drive, ps, depth)) 272 return False; 273 274 if (!prs_uint16("logon_count", ps, depth, &info->logon_count)) 275 return False; 276 if (!prs_uint16("reserved12", ps, depth, &info->reserved12)) 277 return False; 278 if (!prs_uint32("user_rid", ps, depth, &info->user_rid)) 279 return False; 280 if (!prs_uint32("group_rid", ps, depth, &info->group_rid)) 281 return False; 282 if (!prs_uint32("group_count", ps, depth, &info->group_count)) 283 return False; 284 /* I haven't seen this contain anything yet, but when it does 285 we will have to make sure we decode the contents in the middle 286 all the unistr2s ... */ 287 if (!prs_uint32("group_mem_ptr", ps, depth, 288 &info->group_membership_ptr)) 289 return False; 290 if (!prs_uint32("user_flags", ps, depth, &info->user_flags)) 291 return False; 292 293 if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0])) 294 return False; 295 if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1])) 296 return False; 297 if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2])) 298 return False; 299 if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3])) 300 return False; 301 302 if (!smb_io_unihdr("hdr_dom_controller", 303 &info->hdr_dom_controller, ps, depth)) 304 return False; 305 if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth)) 306 return False; 307 308 /* this should be followed, but just get ptr for now */ 309 if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid)) 310 return False; 311 312 if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0])) 313 return False; 314 if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1])) 315 return False; 316 317 /* might be acb_info */ 318 if (!prs_uint32("reserved17", ps, depth, &info->reserved17)) 319 return False; 320 321 322 if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0])) 323 return False; 324 if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1])) 325 return False; 326 if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2])) 327 return False; 328 if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3])) 329 return False; 330 if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4])) 331 return False; 332 if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5])) 333 return False; 334 if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6])) 335 return False; 336 337 if (!prs_uint32("sid_count", ps, depth, &info->sid_count)) 338 return False; 339 if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids)) 340 return False; 341 if (!prs_uint32("ptr_res_group_dom_sid", ps, depth, 342 &info->ptr_res_group_dom_sid)) 343 return False; 344 if (!prs_uint32("res_group_count", ps, depth, &info->res_group_count)) 345 return False; 346 if (!prs_uint32("ptr_res_groups", ps, depth, &info->ptr_res_groups)) 347 return False; 348 349 if(!smb_io_unistr2("uni_user_name", &info->uni_user_name, 350 info->hdr_user_name.buffer, ps, depth)) 351 return False; 352 if(!smb_io_unistr2("uni_full_name", &info->uni_full_name, 353 info->hdr_full_name.buffer, ps, depth)) 354 return False; 355 if(!smb_io_unistr2("uni_logon_script", &info->uni_logon_script, 356 info->hdr_logon_script.buffer, ps, depth)) 357 return False; 358 if(!smb_io_unistr2("uni_profile_path", &info->uni_profile_path, 359 info->hdr_profile_path.buffer, ps, depth)) 360 return False; 361 if(!smb_io_unistr2("uni_home_dir", &info->uni_home_dir, 362 info->hdr_home_dir.buffer, ps, depth)) 363 return False; 364 if(!smb_io_unistr2("uni_dir_drive", &info->uni_dir_drive, 365 info->hdr_dir_drive.buffer, ps, depth)) 366 return False; 367 368 if (info->group_membership_ptr) { 369 if (!pac_io_group_membership_array("group membership", 370 &info->groups, 371 info->group_count, 372 ps, depth)) 373 return False; 374 } 375 376 377 if(!smb_io_unistr2("uni_dom_controller", &info->uni_dom_controller, 378 info->hdr_dom_controller.buffer, ps, depth)) 379 return False; 380 if(!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, 381 info->hdr_dom_name.buffer, ps, depth)) 382 return False; 383 384 if(info->ptr_dom_sid) 385 if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth)) 386 return False; 387 388 389 if (info->sid_count && info->ptr_extra_sids) 390 if (!pac_io_krb_sid_and_attr_array("extra_sids", 391 &info->extra_sids, 392 info->sid_count, 393 ps, depth)) 394 return False; 395 396 if (info->ptr_res_group_dom_sid) 397 if (!smb_io_dom_sid2("res_group_dom_sid", 398 &info->res_group_dom_sid, ps, depth)) 399 return False; 400 401 if (info->ptr_res_groups) 402 if (!pac_io_group_membership_array("res group membership", 403 &info->res_groups, 404 info->res_group_count, 405 ps, depth)) 406 return False; 407 408 return True; 409} 410 411 412static BOOL pac_io_pac_signature_data(const char *desc, 413 PAC_SIGNATURE_DATA *data, uint32 length, 414 prs_struct *ps, int depth) 415{ 416 uint32 siglen = length - sizeof(uint32); 417 if (NULL == data) 418 return False; 419 420 prs_debug(ps, depth, desc, "pac_io_pac_signature_data"); 421 depth++; 422 423 if (!prs_uint32("type", ps, depth, &data->type)) 424 return False; 425 if (UNMARSHALLING(ps)) { 426 data->signature = (unsigned char *)prs_alloc_mem(ps, siglen); 427 if (!data->signature) { 428 DEBUG(3, ("No memory available\n")); 429 return False; 430 } 431 } 432 if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen)) 433 return False; 434 435 return True; 436} 437 438static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, 439 prs_struct *ps, int depth) 440{ 441 if (NULL == hdr) 442 return False; 443 444 prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr"); 445 depth++; 446 447 if (!prs_align(ps)) 448 return False; 449 450 if (hdr->offset != prs_offset(ps)) { 451 DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n", 452 hdr->offset, prs_offset(ps))); 453 prs_set_offset(ps, hdr->offset); 454 } 455 456 if (UNMARSHALLING(ps) && hdr->size > 0) { 457 hdr->ctr = (PAC_INFO_CTR *) 458 prs_alloc_mem(ps, sizeof(PAC_INFO_CTR)); 459 if (!hdr->ctr) { 460 DEBUG(3, ("No memory available\n")); 461 return False; 462 } 463 } 464 465 switch(hdr->type) { 466 case PAC_TYPE_LOGON_INFO: 467 DEBUG(5, ("PAC_TYPE_LOGON_INFO\n")); 468 if (UNMARSHALLING(ps)) 469 hdr->ctr->pac.logon_info = (PAC_LOGON_INFO *) 470 prs_alloc_mem(ps, sizeof(PAC_LOGON_INFO)); 471 if (!hdr->ctr->pac.logon_info) { 472 DEBUG(3, ("No memory available\n")); 473 return False; 474 } 475 if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info, 476 ps, depth)) 477 return False; 478 break; 479 480 case PAC_TYPE_SERVER_CHECKSUM: 481 DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n")); 482 if (UNMARSHALLING(ps)) 483 hdr->ctr->pac.srv_cksum = (PAC_SIGNATURE_DATA *) 484 prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA)); 485 if (!hdr->ctr->pac.srv_cksum) { 486 DEBUG(3, ("No memory available\n")); 487 return False; 488 } 489 if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum, 490 hdr->size, ps, depth)) 491 return False; 492 break; 493 494 case PAC_TYPE_PRIVSVR_CHECKSUM: 495 DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n")); 496 if (UNMARSHALLING(ps)) 497 hdr->ctr->pac.privsrv_cksum = (PAC_SIGNATURE_DATA *) 498 prs_alloc_mem(ps, sizeof(PAC_SIGNATURE_DATA)); 499 if (!hdr->ctr->pac.privsrv_cksum) { 500 DEBUG(3, ("No memory available\n")); 501 return False; 502 } 503 if (!pac_io_pac_signature_data(desc, 504 hdr->ctr->pac.privsrv_cksum, 505 hdr->size, ps, depth)) 506 return False; 507 break; 508 509 case PAC_TYPE_UNKNOWN_10: 510 DEBUG(5, ("PAC_TYPE_UNKNOWN_10\n")); 511 if (UNMARSHALLING(ps)) 512 hdr->ctr->pac.type_10 = (UNKNOWN_TYPE_10 *) 513 prs_alloc_mem(ps, sizeof(UNKNOWN_TYPE_10)); 514 if (!hdr->ctr->pac.type_10) { 515 DEBUG(3, ("No memory available\n")); 516 return False; 517 } 518 if (!pac_io_unknown_type_10(desc, hdr->ctr->pac.type_10, 519 ps, depth)) 520 return False; 521 break; 522 523 default: 524 /* dont' know, so we need to skip it */ 525 DEBUG(3, ("unknown PAC type %d\n", hdr->type)); 526 prs_set_offset(ps, prs_offset(ps) + hdr->size); 527 } 528 529 return True; 530} 531 532static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, 533 prs_struct *ps, int depth) 534{ 535 if (NULL == hdr) 536 return False; 537 538 prs_debug(ps, depth, desc, "pac_io_pac_info_hdr"); 539 depth++; 540 541 if (!prs_align(ps)) 542 return False; 543 if (!prs_uint32("type", ps, depth, &hdr->type)) 544 return False; 545 if (!prs_uint32("size", ps, depth, &hdr->size)) 546 return False; 547 if (!prs_uint32("offset", ps, depth, &hdr->offset)) 548 return False; 549 if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi)) 550 return False; 551 552 return True; 553} 554 555static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, 556 prs_struct *ps, int depth) 557{ 558 int i; 559 560 if (NULL == data) 561 return False; 562 563 prs_debug(ps, depth, desc, "pac_io_pac_data"); 564 depth++; 565 566 if (!prs_align(ps)) 567 return False; 568 if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers)) 569 return False; 570 if (!prs_uint32("version", ps, depth, &data->version)) 571 return False; 572 573 if (UNMARSHALLING(ps) && data->num_buffers > 0) { 574 if ((data->pac_info_hdr_ptr = (PAC_INFO_HDR *) 575 prs_alloc_mem(ps, sizeof(PAC_INFO_HDR) * 576 data->num_buffers)) == NULL) { 577 return False; 578 } 579 } 580 581 for (i=0; i<data->num_buffers; i++) { 582 if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, 583 depth)) 584 return False; 585 } 586 587 for (i=0; i<data->num_buffers; i++) { 588 if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i], 589 ps, depth)) 590 return False; 591 } 592 593 return True; 594} 595 596PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx) 597{ 598 DATA_BLOB pac_data_blob = unwrap_pac(auth_data); 599 prs_struct ps; 600 PAC_DATA *pac_data; 601 602 DEBUG(5,("dump_pac_data\n")); 603 prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL); 604 prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length); 605 prs_set_offset(&ps, 0); 606 607 data_blob_free(&pac_data_blob); 608 609 pac_data = (PAC_DATA *) talloc_zero(ctx, sizeof(PAC_DATA)); 610 pac_io_pac_data("pac data", pac_data, &ps, 0); 611 612 prs_mem_free(&ps); 613 614 return pac_data; 615} 616 617#endif 618