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 = PRS_ALLOC_MEM(ps, uint16, 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 = PRS_ALLOC_MEM(ps, DOM_SID2, 1); 89 if (!sid_and_attr->sid) { 90 DEBUG(3, ("No memory available\n")); 91 return False; 92 } 93 } 94 95 if(!smb_io_dom_sid2("sid", sid_and_attr->sid, ps, depth)) 96 return False; 97 98 return True; 99} 100 101 102static BOOL pac_io_krb_attrs(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr, 103 prs_struct *ps, int depth) 104{ 105 if (NULL == sid_and_attr) 106 return False; 107 108 prs_debug(ps, depth, desc, "pac_io_krb_attrs"); 109 depth++; 110 111 if (!prs_uint32("sid_ptr", ps, depth, &sid_and_attr->sid_ptr)) 112 return False; 113 if (!prs_uint32("attrs", ps, depth, &sid_and_attr->attrs)) 114 return False; 115 116 return True; 117} 118 119static BOOL pac_io_krb_sid_and_attr_array(const char *desc, 120 KRB_SID_AND_ATTR_ARRAY *array, 121 uint32 num, 122 prs_struct *ps, int depth) 123{ 124 int i; 125 126 if (NULL == array) 127 return False; 128 129 prs_debug(ps, depth, desc, "pac_io_krb_sid_and_attr_array"); 130 depth++; 131 132 133 if (!prs_uint32("count", ps, depth, &array->count)) 134 return False; 135 136 if (UNMARSHALLING(ps)) { 137 array->krb_sid_and_attrs = PRS_ALLOC_MEM(ps, KRB_SID_AND_ATTRS, num); 138 if (!array->krb_sid_and_attrs) { 139 DEBUG(3, ("No memory available\n")); 140 return False; 141 } 142 } 143 144 for (i=0; i<num; i++) { 145 if (!pac_io_krb_attrs(desc, 146 &array->krb_sid_and_attrs[i], 147 ps, depth)) 148 return False; 149 150 } 151 for (i=0; i<num; i++) { 152 if (!pac_io_krb_sids(desc, 153 &array->krb_sid_and_attrs[i], 154 ps, depth)) 155 return False; 156 157 } 158 159 return True; 160 161} 162 163static BOOL pac_io_group_membership(const char *desc, 164 GROUP_MEMBERSHIP *membership, 165 prs_struct *ps, int depth) 166{ 167 if (NULL == membership) 168 return False; 169 170 prs_debug(ps, depth, desc, "pac_io_group_membership"); 171 depth++; 172 173 if (!prs_uint32("rid", ps, depth, &membership->rid)) 174 return False; 175 if (!prs_uint32("attrs", ps, depth, &membership->attrs)) 176 return False; 177 178 return True; 179} 180 181 182static BOOL pac_io_group_membership_array(const char *desc, 183 GROUP_MEMBERSHIP_ARRAY *array, 184 uint32 num, 185 prs_struct *ps, int depth) 186{ 187 int i; 188 189 if (NULL == array) 190 return False; 191 192 prs_debug(ps, depth, desc, "pac_io_group_membership_array"); 193 depth++; 194 195 196 if (!prs_uint32("count", ps, depth, &array->count)) 197 return False; 198 199 if (UNMARSHALLING(ps)) { 200 array->group_membership = PRS_ALLOC_MEM(ps, GROUP_MEMBERSHIP, num); 201 if (!array->group_membership) { 202 DEBUG(3, ("No memory available\n")); 203 return False; 204 } 205 } 206 207 for (i=0; i<num; i++) { 208 if (!pac_io_group_membership(desc, 209 &array->group_membership[i], 210 ps, depth)) 211 return False; 212 213 } 214 215 return True; 216 217} 218 219static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 220 prs_struct *ps, int depth) 221{ 222 uint32 garbage; 223 if (NULL == info) 224 return False; 225 226 prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); 227 depth++; 228 229 if (!prs_uint32("unknown", ps, depth, &garbage)) 230 return False; 231 if (!prs_uint32("unknown", ps, depth, &garbage)) 232 return False; 233 if (!prs_uint32("bufferlen", ps, depth, &garbage)) 234 return False; 235 if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) 236 return False; 237 if (!prs_uint32("pointer", ps, depth, &garbage)) 238 return False; 239 240 if (!smb_io_time("logon_time", &info->logon_time, ps, depth)) 241 return False; 242 if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth)) 243 return False; 244 if (!smb_io_time("kickoff_time", &info->kickoff_time, ps, depth)) 245 return False; 246 if (!smb_io_time("pass_last_set_time", &info->pass_last_set_time, 247 ps, depth)) 248 return False; 249 if (!smb_io_time("pass_can_change_time", &info->pass_can_change_time, 250 ps, depth)) 251 return False; 252 if (!smb_io_time("pass_must_change_time", &info->pass_must_change_time, 253 ps, depth)) 254 return False; 255 256 if (!smb_io_unihdr("hdr_user_name", &info->hdr_user_name, ps, depth)) 257 return False; 258 if (!smb_io_unihdr("hdr_full_name", &info->hdr_full_name, ps, depth)) 259 return False; 260 if (!smb_io_unihdr("hdr_logon_script", &info->hdr_logon_script, 261 ps, depth)) 262 return False; 263 if (!smb_io_unihdr("hdr_profile_path", &info->hdr_profile_path, 264 ps, depth)) 265 return False; 266 if (!smb_io_unihdr("hdr_home_dir", &info->hdr_home_dir, ps, depth)) 267 return False; 268 if (!smb_io_unihdr("hdr_dir_drive", &info->hdr_dir_drive, ps, depth)) 269 return False; 270 271 if (!prs_uint16("logon_count", ps, depth, &info->logon_count)) 272 return False; 273 if (!prs_uint16("reserved12", ps, depth, &info->reserved12)) 274 return False; 275 if (!prs_uint32("user_rid", ps, depth, &info->user_rid)) 276 return False; 277 if (!prs_uint32("group_rid", ps, depth, &info->group_rid)) 278 return False; 279 if (!prs_uint32("group_count", ps, depth, &info->group_count)) 280 return False; 281 /* I haven't seen this contain anything yet, but when it does 282 we will have to make sure we decode the contents in the middle 283 all the unistr2s ... */ 284 if (!prs_uint32("group_mem_ptr", ps, depth, 285 &info->group_membership_ptr)) 286 return False; 287 if (!prs_uint32("user_flags", ps, depth, &info->user_flags)) 288 return False; 289 290 if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0])) 291 return False; 292 if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1])) 293 return False; 294 if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2])) 295 return False; 296 if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3])) 297 return False; 298 299 if (!smb_io_unihdr("hdr_dom_controller", 300 &info->hdr_dom_controller, ps, depth)) 301 return False; 302 if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth)) 303 return False; 304 305 /* this should be followed, but just get ptr for now */ 306 if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid)) 307 return False; 308 309 if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0])) 310 return False; 311 if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1])) 312 return False; 313 314 /* might be acb_info */ 315 if (!prs_uint32("reserved17", ps, depth, &info->reserved17)) 316 return False; 317 318 319 if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0])) 320 return False; 321 if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1])) 322 return False; 323 if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2])) 324 return False; 325 if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3])) 326 return False; 327 if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4])) 328 return False; 329 if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5])) 330 return False; 331 if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6])) 332 return False; 333 334 if (!prs_uint32("sid_count", ps, depth, &info->sid_count)) 335 return False; 336 if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids)) 337 return False; 338 if (!prs_uint32("ptr_res_group_dom_sid", ps, depth, 339 &info->ptr_res_group_dom_sid)) 340 return False; 341 if (!prs_uint32("res_group_count", ps, depth, &info->res_group_count)) 342 return False; 343 if (!prs_uint32("ptr_res_groups", ps, depth, &info->ptr_res_groups)) 344 return False; 345 346 if(!smb_io_unistr2("uni_user_name", &info->uni_user_name, 347 info->hdr_user_name.buffer, ps, depth)) 348 return False; 349 if(!smb_io_unistr2("uni_full_name", &info->uni_full_name, 350 info->hdr_full_name.buffer, ps, depth)) 351 return False; 352 if(!smb_io_unistr2("uni_logon_script", &info->uni_logon_script, 353 info->hdr_logon_script.buffer, ps, depth)) 354 return False; 355 if(!smb_io_unistr2("uni_profile_path", &info->uni_profile_path, 356 info->hdr_profile_path.buffer, ps, depth)) 357 return False; 358 if(!smb_io_unistr2("uni_home_dir", &info->uni_home_dir, 359 info->hdr_home_dir.buffer, ps, depth)) 360 return False; 361 if(!smb_io_unistr2("uni_dir_drive", &info->uni_dir_drive, 362 info->hdr_dir_drive.buffer, ps, depth)) 363 return False; 364 365 if (info->group_membership_ptr) { 366 if (!pac_io_group_membership_array("group membership", 367 &info->groups, 368 info->group_count, 369 ps, depth)) 370 return False; 371 } 372 373 374 if(!smb_io_unistr2("uni_dom_controller", &info->uni_dom_controller, 375 info->hdr_dom_controller.buffer, ps, depth)) 376 return False; 377 if(!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, 378 info->hdr_dom_name.buffer, ps, depth)) 379 return False; 380 381 if(info->ptr_dom_sid) 382 if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth)) 383 return False; 384 385 386 if (info->sid_count && info->ptr_extra_sids) 387 if (!pac_io_krb_sid_and_attr_array("extra_sids", 388 &info->extra_sids, 389 info->sid_count, 390 ps, depth)) 391 return False; 392 393 if (info->ptr_res_group_dom_sid) 394 if (!smb_io_dom_sid2("res_group_dom_sid", 395 &info->res_group_dom_sid, ps, depth)) 396 return False; 397 398 if (info->ptr_res_groups) 399 if (!pac_io_group_membership_array("res group membership", 400 &info->res_groups, 401 info->res_group_count, 402 ps, depth)) 403 return False; 404 405 return True; 406} 407 408 409static BOOL pac_io_pac_signature_data(const char *desc, 410 PAC_SIGNATURE_DATA *data, uint32 length, 411 prs_struct *ps, int depth) 412{ 413 uint32 siglen = length - sizeof(uint32); 414 if (NULL == data) 415 return False; 416 417 prs_debug(ps, depth, desc, "pac_io_pac_signature_data"); 418 depth++; 419 420 if (!prs_uint32("type", ps, depth, &data->type)) 421 return False; 422 if (UNMARSHALLING(ps)) { 423 data->signature = PRS_ALLOC_MEM(ps, unsigned char, siglen); 424 if (!data->signature) { 425 DEBUG(3, ("No memory available\n")); 426 return False; 427 } 428 } 429 if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen)) 430 return False; 431 432 return True; 433} 434 435static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, 436 prs_struct *ps, int depth) 437{ 438 if (NULL == hdr) 439 return False; 440 441 prs_debug(ps, depth, desc, "pac_io_pac_info_hdr_ctr"); 442 depth++; 443 444 if (!prs_align(ps)) 445 return False; 446 447 if (hdr->offset != prs_offset(ps)) { 448 DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n", 449 hdr->offset, prs_offset(ps))); 450 prs_set_offset(ps, hdr->offset); 451 } 452 453 if (UNMARSHALLING(ps) && hdr->size > 0) { 454 hdr->ctr = PRS_ALLOC_MEM(ps, PAC_INFO_CTR, 1); 455 if (!hdr->ctr) { 456 DEBUG(3, ("No memory available\n")); 457 return False; 458 } 459 } 460 461 switch(hdr->type) { 462 case PAC_TYPE_LOGON_INFO: 463 DEBUG(5, ("PAC_TYPE_LOGON_INFO\n")); 464 if (UNMARSHALLING(ps)) 465 hdr->ctr->pac.logon_info = PRS_ALLOC_MEM(ps, PAC_LOGON_INFO, 1); 466 if (!hdr->ctr->pac.logon_info) { 467 DEBUG(3, ("No memory available\n")); 468 return False; 469 } 470 if (!pac_io_pac_logon_info(desc, hdr->ctr->pac.logon_info, 471 ps, depth)) 472 return False; 473 break; 474 475 case PAC_TYPE_SERVER_CHECKSUM: 476 DEBUG(5, ("PAC_TYPE_SERVER_CHECKSUM\n")); 477 if (UNMARSHALLING(ps)) 478 hdr->ctr->pac.srv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1); 479 if (!hdr->ctr->pac.srv_cksum) { 480 DEBUG(3, ("No memory available\n")); 481 return False; 482 } 483 if (!pac_io_pac_signature_data(desc, hdr->ctr->pac.srv_cksum, 484 hdr->size, ps, depth)) 485 return False; 486 break; 487 488 case PAC_TYPE_PRIVSVR_CHECKSUM: 489 DEBUG(5, ("PAC_TYPE_PRIVSVR_CHECKSUM\n")); 490 if (UNMARSHALLING(ps)) 491 hdr->ctr->pac.privsrv_cksum = PRS_ALLOC_MEM(ps, PAC_SIGNATURE_DATA, 1); 492 if (!hdr->ctr->pac.privsrv_cksum) { 493 DEBUG(3, ("No memory available\n")); 494 return False; 495 } 496 if (!pac_io_pac_signature_data(desc, 497 hdr->ctr->pac.privsrv_cksum, 498 hdr->size, ps, depth)) 499 return False; 500 break; 501 502 case PAC_TYPE_UNKNOWN_10: 503 DEBUG(5, ("PAC_TYPE_UNKNOWN_10\n")); 504 if (UNMARSHALLING(ps)) 505 hdr->ctr->pac.type_10 = PRS_ALLOC_MEM(ps, UNKNOWN_TYPE_10, 1); 506 if (!hdr->ctr->pac.type_10) { 507 DEBUG(3, ("No memory available\n")); 508 return False; 509 } 510 if (!pac_io_unknown_type_10(desc, hdr->ctr->pac.type_10, 511 ps, depth)) 512 return False; 513 break; 514 515 default: 516 /* dont' know, so we need to skip it */ 517 DEBUG(3, ("unknown PAC type %d\n", hdr->type)); 518 prs_set_offset(ps, prs_offset(ps) + hdr->size); 519 } 520 521 return True; 522} 523 524static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, 525 prs_struct *ps, int depth) 526{ 527 if (NULL == hdr) 528 return False; 529 530 prs_debug(ps, depth, desc, "pac_io_pac_info_hdr"); 531 depth++; 532 533 if (!prs_align(ps)) 534 return False; 535 if (!prs_uint32("type", ps, depth, &hdr->type)) 536 return False; 537 if (!prs_uint32("size", ps, depth, &hdr->size)) 538 return False; 539 if (!prs_uint32("offset", ps, depth, &hdr->offset)) 540 return False; 541 if (!prs_uint32("offsethi", ps, depth, &hdr->offsethi)) 542 return False; 543 544 return True; 545} 546 547static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, 548 prs_struct *ps, int depth) 549{ 550 int i; 551 552 if (NULL == data) 553 return False; 554 555 prs_debug(ps, depth, desc, "pac_io_pac_data"); 556 depth++; 557 558 if (!prs_align(ps)) 559 return False; 560 if (!prs_uint32("num_buffers", ps, depth, &data->num_buffers)) 561 return False; 562 if (!prs_uint32("version", ps, depth, &data->version)) 563 return False; 564 565 if (UNMARSHALLING(ps) && data->num_buffers > 0) { 566 if ((data->pac_info_hdr_ptr = PRS_ALLOC_MEM(ps, PAC_INFO_HDR, data->num_buffers)) == NULL) { 567 return False; 568 } 569 } 570 571 for (i=0; i<data->num_buffers; i++) { 572 if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, 573 depth)) 574 return False; 575 } 576 577 for (i=0; i<data->num_buffers; i++) { 578 if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i], 579 ps, depth)) 580 return False; 581 } 582 583 return True; 584} 585 586PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx) 587{ 588 DATA_BLOB pac_data_blob = unwrap_pac(auth_data); 589 prs_struct ps; 590 PAC_DATA *pac_data; 591 592 DEBUG(5,("dump_pac_data\n")); 593 prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL); 594 prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length); 595 prs_set_offset(&ps, 0); 596 597 data_blob_free(&pac_data_blob); 598 599 pac_data = TALLOC_ZERO_P(ctx, PAC_DATA); 600 pac_io_pac_data("pac data", pac_data, &ps, 0); 601 602 prs_mem_free(&ps); 603 604 return pac_data; 605} 606 607#endif 608