1/* 2 Unix SMB/CIFS implementation. 3 Samba memory buffer functions 4 Copyright (C) Andrew Tridgell 1992-1997 5 Copyright (C) Luke Kenneth Casson Leighton 1996-1997 6 Copyright (C) Jeremy Allison 1999 7 Copyright (C) Andrew Bartlett 2003. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24#include "includes.h" 25 26#undef DBGC_CLASS 27#define DBGC_CLASS DBGC_RPC_PARSE 28 29/** 30 * Dump a prs to a file: from the current location through to the end. 31 **/ 32void prs_dump(char *name, int v, prs_struct *ps) 33{ 34 prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size); 35} 36 37 38/** 39 * Dump from the start of the prs to the current location. 40 **/ 41void prs_dump_before(char *name, int v, prs_struct *ps) 42{ 43 prs_dump_region(name, v, ps, 0, ps->data_offset); 44} 45 46 47/** 48 * Dump everything from the start of the prs up to the current location. 49 **/ 50void prs_dump_region(char *name, int v, prs_struct *ps, 51 int from_off, int to_off) 52{ 53 int fd, i; 54 pstring fname; 55 if (DEBUGLEVEL < 50) return; 56 for (i=1;i<100;i++) { 57 if (v != -1) { 58 slprintf(fname,sizeof(fname)-1, "/tmp/%s_%d.%d.prs", name, v, i); 59 } else { 60 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.prs", name, i); 61 } 62 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); 63 if (fd != -1 || errno != EEXIST) break; 64 } 65 if (fd != -1) { 66 write(fd, ps->data_p + from_off, to_off - from_off); 67 close(fd); 68 DEBUG(0,("created %s\n", fname)); 69 } 70} 71 72 73 74/******************************************************************* 75 debug output for parsing info. 76 77 XXXX side-effect of this function is to increase the debug depth XXXX 78 79 ********************************************************************/ 80void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name) 81{ 82 DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc)); 83} 84 85 86/** 87 * Initialise an expandable parse structure. 88 * 89 * @param size Initial buffer size. If >0, a new buffer will be 90 * created with malloc(). 91 * 92 * @return False if allocation fails, otherwise True. 93 **/ 94BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io) 95{ 96 ZERO_STRUCTP(ps); 97 ps->io = io; 98 ps->bigendian_data = RPC_LITTLE_ENDIAN; 99 ps->align = RPC_PARSE_ALIGN; 100 ps->is_dynamic = False; 101 ps->data_offset = 0; 102 ps->buffer_size = 0; 103 ps->data_p = NULL; 104 ps->mem_ctx = ctx; 105 106 if (size != 0) { 107 ps->buffer_size = size; 108 if((ps->data_p = (char *)SMB_MALLOC((size_t)size)) == NULL) { 109 DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size)); 110 return False; 111 } 112 memset(ps->data_p, '\0', (size_t)size); 113 ps->is_dynamic = True; /* We own this memory. */ 114 } 115 116 return True; 117} 118 119/******************************************************************* 120 Delete the memory in a parse structure - if we own it. 121 ********************************************************************/ 122 123void prs_mem_free(prs_struct *ps) 124{ 125 if(ps->is_dynamic) 126 SAFE_FREE(ps->data_p); 127 ps->is_dynamic = False; 128 ps->buffer_size = 0; 129 ps->data_offset = 0; 130} 131 132/******************************************************************* 133 Clear the memory in a parse structure. 134 ********************************************************************/ 135 136void prs_mem_clear(prs_struct *ps) 137{ 138 if (ps->buffer_size) 139 memset(ps->data_p, '\0', (size_t)ps->buffer_size); 140} 141 142/******************************************************************* 143 Allocate memory when unmarshalling... Always zero clears. 144 ********************************************************************/ 145 146#if defined(PARANOID_MALLOC_CHECKER) 147char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count) 148#else 149char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count) 150#endif 151{ 152 char *ret = NULL; 153 154 if (size) { 155 /* We can't call the type-safe version here. */ 156#if defined(PARANOID_MALLOC_CHECKER) 157 ret = talloc_zero_array_(ps->mem_ctx, size, count); 158#else 159 ret = talloc_zero_array(ps->mem_ctx, size, count); 160#endif 161 } 162 return ret; 163} 164 165/******************************************************************* 166 Return the current talloc context we're using. 167 ********************************************************************/ 168 169TALLOC_CTX *prs_get_mem_context(prs_struct *ps) 170{ 171 return ps->mem_ctx; 172} 173 174/******************************************************************* 175 Hand some already allocated memory to a prs_struct. 176 ********************************************************************/ 177 178void prs_give_memory(prs_struct *ps, char *buf, uint32 size, BOOL is_dynamic) 179{ 180 ps->is_dynamic = is_dynamic; 181 ps->data_p = buf; 182 ps->buffer_size = size; 183} 184 185/******************************************************************* 186 Take some memory back from a prs_struct. 187 ********************************************************************/ 188 189char *prs_take_memory(prs_struct *ps, uint32 *psize) 190{ 191 char *ret = ps->data_p; 192 if(psize) 193 *psize = ps->buffer_size; 194 ps->is_dynamic = False; 195 prs_mem_free(ps); 196 return ret; 197} 198 199/******************************************************************* 200 Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary. 201 ********************************************************************/ 202 203BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize) 204{ 205 if (newsize > ps->buffer_size) 206 return prs_force_grow(ps, newsize - ps->buffer_size); 207 208 if (newsize < ps->buffer_size) { 209 char *new_data_p = SMB_REALLOC(ps->data_p, newsize); 210 /* if newsize is zero, Realloc acts like free() & returns NULL*/ 211 if (new_data_p == NULL && newsize != 0) { 212 DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n", 213 (unsigned int)newsize)); 214 DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno))); 215 return False; 216 } 217 ps->data_p = new_data_p; 218 ps->buffer_size = newsize; 219 } 220 221 return True; 222} 223 224/******************************************************************* 225 Attempt, if needed, to grow a data buffer. 226 Also depends on the data stream mode (io). 227 ********************************************************************/ 228 229BOOL prs_grow(prs_struct *ps, uint32 extra_space) 230{ 231 uint32 new_size; 232 char *new_data; 233 234 ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space); 235 236 if(ps->data_offset + extra_space <= ps->buffer_size) 237 return True; 238 239 /* 240 * We cannot grow the buffer if we're not reading 241 * into the prs_struct, or if we don't own the memory. 242 */ 243 244 if(UNMARSHALLING(ps) || !ps->is_dynamic) { 245 DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", 246 (unsigned int)extra_space)); 247 return False; 248 } 249 250 /* 251 * Decide how much extra space we really need. 252 */ 253 254 extra_space -= (ps->buffer_size - ps->data_offset); 255 if(ps->buffer_size == 0) { 256 /* 257 * Ensure we have at least a PDU's length, or extra_space, whichever 258 * is greater. 259 */ 260 261 new_size = MAX(MAX_PDU_FRAG_LEN,extra_space); 262 263 if((new_data = SMB_MALLOC(new_size)) == NULL) { 264 DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size)); 265 return False; 266 } 267 memset(new_data, '\0', (size_t)new_size ); 268 } else { 269 /* 270 * If the current buffer size is bigger than the space needed, just 271 * double it, else add extra_space. 272 */ 273 new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space); 274 275 if ((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) { 276 DEBUG(0,("prs_grow: Realloc failure for size %u.\n", 277 (unsigned int)new_size)); 278 return False; 279 } 280 281 memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); 282 } 283 ps->buffer_size = new_size; 284 ps->data_p = new_data; 285 286 return True; 287} 288 289/******************************************************************* 290 Attempt to force a data buffer to grow by len bytes. 291 This is only used when appending more data onto a prs_struct 292 when reading an rpc reply, before unmarshalling it. 293 ********************************************************************/ 294 295BOOL prs_force_grow(prs_struct *ps, uint32 extra_space) 296{ 297 uint32 new_size = ps->buffer_size + extra_space; 298 char *new_data; 299 300 if(!UNMARSHALLING(ps) || !ps->is_dynamic) { 301 DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", 302 (unsigned int)extra_space)); 303 return False; 304 } 305 306 if((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) { 307 DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n", 308 (unsigned int)new_size)); 309 return False; 310 } 311 312 memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); 313 314 ps->buffer_size = new_size; 315 ps->data_p = new_data; 316 317 return True; 318} 319 320/******************************************************************* 321 Get the data pointer (external interface). 322********************************************************************/ 323 324char *prs_data_p(prs_struct *ps) 325{ 326 return ps->data_p; 327} 328 329/******************************************************************* 330 Get the current data size (external interface). 331 ********************************************************************/ 332 333uint32 prs_data_size(prs_struct *ps) 334{ 335 return ps->buffer_size; 336} 337 338/******************************************************************* 339 Fetch the current offset (external interface). 340 ********************************************************************/ 341 342uint32 prs_offset(prs_struct *ps) 343{ 344 return ps->data_offset; 345} 346 347/******************************************************************* 348 Set the current offset (external interface). 349 ********************************************************************/ 350 351BOOL prs_set_offset(prs_struct *ps, uint32 offset) 352{ 353 if(offset <= ps->data_offset) { 354 ps->data_offset = offset; 355 return True; 356 } 357 358 if(!prs_grow(ps, offset - ps->data_offset)) 359 return False; 360 361 ps->data_offset = offset; 362 return True; 363} 364 365/******************************************************************* 366 Append the data from one parse_struct into another. 367 ********************************************************************/ 368 369BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src) 370{ 371 if (prs_offset(src) == 0) 372 return True; 373 374 if(!prs_grow(dst, prs_offset(src))) 375 return False; 376 377 memcpy(&dst->data_p[dst->data_offset], src->data_p, (size_t)prs_offset(src)); 378 dst->data_offset += prs_offset(src); 379 380 return True; 381} 382 383/******************************************************************* 384 Append some data from one parse_struct into another. 385 ********************************************************************/ 386 387BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len) 388{ 389 if (len == 0) 390 return True; 391 392 if(!prs_grow(dst, len)) 393 return False; 394 395 memcpy(&dst->data_p[dst->data_offset], src->data_p + start, (size_t)len); 396 dst->data_offset += len; 397 398 return True; 399} 400 401/******************************************************************* 402 Append the data from a buffer into a parse_struct. 403 ********************************************************************/ 404 405BOOL prs_copy_data_in(prs_struct *dst, char *src, uint32 len) 406{ 407 if (len == 0) 408 return True; 409 410 if(!prs_grow(dst, len)) 411 return False; 412 413 memcpy(&dst->data_p[dst->data_offset], src, (size_t)len); 414 dst->data_offset += len; 415 416 return True; 417} 418 419/******************************************************************* 420 Copy some data from a parse_struct into a buffer. 421 ********************************************************************/ 422 423BOOL prs_copy_data_out(char *dst, prs_struct *src, uint32 len) 424{ 425 if (len == 0) 426 return True; 427 428 if(!prs_mem_get(src, len)) 429 return False; 430 431 memcpy(dst, &src->data_p[src->data_offset], (size_t)len); 432 src->data_offset += len; 433 434 return True; 435} 436 437/******************************************************************* 438 Copy all the data from a parse_struct into a buffer. 439 ********************************************************************/ 440 441BOOL prs_copy_all_data_out(char *dst, prs_struct *src) 442{ 443 uint32 len = prs_offset(src); 444 445 if (!len) 446 return True; 447 448 prs_set_offset(src, 0); 449 return prs_copy_data_out(dst, src, len); 450} 451 452/******************************************************************* 453 Set the data as X-endian (external interface). 454 ********************************************************************/ 455 456void prs_set_endian_data(prs_struct *ps, BOOL endian) 457{ 458 ps->bigendian_data = endian; 459} 460 461/******************************************************************* 462 Align a the data_len to a multiple of align bytes - filling with 463 zeros. 464 ********************************************************************/ 465 466BOOL prs_align(prs_struct *ps) 467{ 468 uint32 mod = ps->data_offset & (ps->align-1); 469 470 if (ps->align != 0 && mod != 0) { 471 uint32 extra_space = (ps->align - mod); 472 if(!prs_grow(ps, extra_space)) 473 return False; 474 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); 475 ps->data_offset += extra_space; 476 } 477 478 return True; 479} 480 481/****************************************************************** 482 Align on a 2 byte boundary 483 *****************************************************************/ 484 485BOOL prs_align_uint16(prs_struct *ps) 486{ 487 BOOL ret; 488 uint8 old_align = ps->align; 489 490 ps->align = 2; 491 ret = prs_align(ps); 492 ps->align = old_align; 493 494 return ret; 495} 496 497/****************************************************************** 498 Align on a 8 byte boundary 499 *****************************************************************/ 500 501BOOL prs_align_uint64(prs_struct *ps) 502{ 503 BOOL ret; 504 uint8 old_align = ps->align; 505 506 ps->align = 8; 507 ret = prs_align(ps); 508 ps->align = old_align; 509 510 return ret; 511} 512 513/******************************************************************* 514 Align only if required (for the unistr2 string mainly) 515 ********************************************************************/ 516 517BOOL prs_align_needed(prs_struct *ps, uint32 needed) 518{ 519 if (needed==0) 520 return True; 521 else 522 return prs_align(ps); 523} 524 525/******************************************************************* 526 Ensure we can read/write to a given offset. 527 ********************************************************************/ 528 529char *prs_mem_get(prs_struct *ps, uint32 extra_size) 530{ 531 if(UNMARSHALLING(ps)) { 532 /* 533 * If reading, ensure that we can read the requested size item. 534 */ 535 if (ps->data_offset + extra_size > ps->buffer_size) { 536 DEBUG(0,("prs_mem_get: reading data of size %u would overrun buffer.\n", 537 (unsigned int)extra_size )); 538 return NULL; 539 } 540 } else { 541 /* 542 * Writing - grow the buffer if needed. 543 */ 544 if(!prs_grow(ps, extra_size)) 545 return NULL; 546 } 547 return &ps->data_p[ps->data_offset]; 548} 549 550/******************************************************************* 551 Change the struct type. 552 ********************************************************************/ 553 554void prs_switch_type(prs_struct *ps, BOOL io) 555{ 556 if ((ps->io ^ io) == True) 557 ps->io=io; 558} 559 560/******************************************************************* 561 Force a prs_struct to be dynamic even when it's size is 0. 562 ********************************************************************/ 563 564void prs_force_dynamic(prs_struct *ps) 565{ 566 ps->is_dynamic=True; 567} 568 569/******************************************************************* 570 Stream a uint8. 571 ********************************************************************/ 572 573BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) 574{ 575 char *q = prs_mem_get(ps, 1); 576 if (q == NULL) 577 return False; 578 579 if (UNMARSHALLING(ps)) 580 *data8 = CVAL(q,0); 581 else 582 SCVAL(q,0,*data8); 583 584 DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8)); 585 586 ps->data_offset += 1; 587 588 return True; 589} 590 591/******************************************************************* 592 Stream a uint16. 593 ********************************************************************/ 594 595BOOL prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16) 596{ 597 char *q = prs_mem_get(ps, sizeof(uint16)); 598 if (q == NULL) 599 return False; 600 601 if (UNMARSHALLING(ps)) { 602 if (ps->bigendian_data) 603 *data16 = RSVAL(q,0); 604 else 605 *data16 = SVAL(q,0); 606 } else { 607 if (ps->bigendian_data) 608 RSSVAL(q,0,*data16); 609 else 610 SSVAL(q,0,*data16); 611 } 612 613 DEBUG(5,("%s%04x %s: %04x\n", tab_depth(depth), ps->data_offset, name, *data16)); 614 615 ps->data_offset += sizeof(uint16); 616 617 return True; 618} 619 620/******************************************************************* 621 Stream a uint32. 622 ********************************************************************/ 623 624BOOL prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32) 625{ 626 char *q = prs_mem_get(ps, sizeof(uint32)); 627 if (q == NULL) 628 return False; 629 630 if (UNMARSHALLING(ps)) { 631 if (ps->bigendian_data) 632 *data32 = RIVAL(q,0); 633 else 634 *data32 = IVAL(q,0); 635 } else { 636 if (ps->bigendian_data) 637 RSIVAL(q,0,*data32); 638 else 639 SIVAL(q,0,*data32); 640 } 641 642 DEBUG(5,("%s%04x %s: %08x\n", tab_depth(depth), ps->data_offset, name, *data32)); 643 644 ps->data_offset += sizeof(uint32); 645 646 return True; 647} 648 649/******************************************************************* 650 Stream a NTSTATUS 651 ********************************************************************/ 652 653BOOL prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status) 654{ 655 char *q = prs_mem_get(ps, sizeof(uint32)); 656 if (q == NULL) 657 return False; 658 659 if (UNMARSHALLING(ps)) { 660 if (ps->bigendian_data) 661 *status = NT_STATUS(RIVAL(q,0)); 662 else 663 *status = NT_STATUS(IVAL(q,0)); 664 } else { 665 if (ps->bigendian_data) 666 RSIVAL(q,0,NT_STATUS_V(*status)); 667 else 668 SIVAL(q,0,NT_STATUS_V(*status)); 669 } 670 671 DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, 672 nt_errstr(*status))); 673 674 ps->data_offset += sizeof(uint32); 675 676 return True; 677} 678 679/******************************************************************* 680 Stream a WERROR 681 ********************************************************************/ 682 683BOOL prs_werror(const char *name, prs_struct *ps, int depth, WERROR *status) 684{ 685 char *q = prs_mem_get(ps, sizeof(uint32)); 686 if (q == NULL) 687 return False; 688 689 if (UNMARSHALLING(ps)) { 690 if (ps->bigendian_data) 691 *status = W_ERROR(RIVAL(q,0)); 692 else 693 *status = W_ERROR(IVAL(q,0)); 694 } else { 695 if (ps->bigendian_data) 696 RSIVAL(q,0,W_ERROR_V(*status)); 697 else 698 SIVAL(q,0,W_ERROR_V(*status)); 699 } 700 701 DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, 702 dos_errstr(*status))); 703 704 ps->data_offset += sizeof(uint32); 705 706 return True; 707} 708 709 710/****************************************************************** 711 Stream an array of uint8s. Length is number of uint8s. 712 ********************************************************************/ 713 714BOOL prs_uint8s(BOOL charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len) 715{ 716 int i; 717 char *q = prs_mem_get(ps, len); 718 if (q == NULL) 719 return False; 720 721 if (UNMARSHALLING(ps)) { 722 for (i = 0; i < len; i++) 723 data8s[i] = CVAL(q,i); 724 } else { 725 for (i = 0; i < len; i++) 726 SCVAL(q, i, data8s[i]); 727 } 728 729 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset ,name)); 730 if (charmode) 731 print_asc(5, (unsigned char*)data8s, len); 732 else { 733 for (i = 0; i < len; i++) 734 DEBUG(5,("%02x ", data8s[i])); 735 } 736 DEBUG(5,("\n")); 737 738 ps->data_offset += len; 739 740 return True; 741} 742 743/****************************************************************** 744 Stream an array of uint16s. Length is number of uint16s. 745 ********************************************************************/ 746 747BOOL prs_uint16s(BOOL charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len) 748{ 749 int i; 750 char *q = prs_mem_get(ps, len * sizeof(uint16)); 751 if (q == NULL) 752 return False; 753 754 if (UNMARSHALLING(ps)) { 755 if (ps->bigendian_data) { 756 for (i = 0; i < len; i++) 757 data16s[i] = RSVAL(q, 2*i); 758 } else { 759 for (i = 0; i < len; i++) 760 data16s[i] = SVAL(q, 2*i); 761 } 762 } else { 763 if (ps->bigendian_data) { 764 for (i = 0; i < len; i++) 765 RSSVAL(q, 2*i, data16s[i]); 766 } else { 767 for (i = 0; i < len; i++) 768 SSVAL(q, 2*i, data16s[i]); 769 } 770 } 771 772 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 773 if (charmode) 774 print_asc(5, (unsigned char*)data16s, 2*len); 775 else { 776 for (i = 0; i < len; i++) 777 DEBUG(5,("%04x ", data16s[i])); 778 } 779 DEBUG(5,("\n")); 780 781 ps->data_offset += (len * sizeof(uint16)); 782 783 return True; 784} 785 786/****************************************************************** 787 Start using a function for streaming unicode chars. If unmarshalling, 788 output must be little-endian, if marshalling, input must be little-endian. 789 ********************************************************************/ 790 791static void dbg_rw_punival(BOOL charmode, const char *name, int depth, prs_struct *ps, 792 char *in_buf, char *out_buf, int len) 793{ 794 int i; 795 796 if (UNMARSHALLING(ps)) { 797 if (ps->bigendian_data) { 798 for (i = 0; i < len; i++) 799 SSVAL(out_buf,2*i,RSVAL(in_buf, 2*i)); 800 } else { 801 for (i = 0; i < len; i++) 802 SSVAL(out_buf, 2*i, SVAL(in_buf, 2*i)); 803 } 804 } else { 805 if (ps->bigendian_data) { 806 for (i = 0; i < len; i++) 807 RSSVAL(in_buf, 2*i, SVAL(out_buf,2*i)); 808 } else { 809 for (i = 0; i < len; i++) 810 SSVAL(in_buf, 2*i, SVAL(out_buf,2*i)); 811 } 812 } 813 814 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 815 if (charmode) 816 print_asc(5, (unsigned char*)out_buf, 2*len); 817 else { 818 for (i = 0; i < len; i++) 819 DEBUG(5,("%04x ", out_buf[i])); 820 } 821 DEBUG(5,("\n")); 822} 823 824/****************************************************************** 825 Stream a unistr. Always little endian. 826 ********************************************************************/ 827 828BOOL prs_uint16uni(BOOL charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len) 829{ 830 char *q = prs_mem_get(ps, len * sizeof(uint16)); 831 if (q == NULL) 832 return False; 833 834 dbg_rw_punival(charmode, name, depth, ps, q, (char *)data16s, len); 835 ps->data_offset += (len * sizeof(uint16)); 836 837 return True; 838} 839 840/****************************************************************** 841 Stream an array of uint32s. Length is number of uint32s. 842 ********************************************************************/ 843 844BOOL prs_uint32s(BOOL charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len) 845{ 846 int i; 847 char *q = prs_mem_get(ps, len * sizeof(uint32)); 848 if (q == NULL) 849 return False; 850 851 if (UNMARSHALLING(ps)) { 852 if (ps->bigendian_data) { 853 for (i = 0; i < len; i++) 854 data32s[i] = RIVAL(q, 4*i); 855 } else { 856 for (i = 0; i < len; i++) 857 data32s[i] = IVAL(q, 4*i); 858 } 859 } else { 860 if (ps->bigendian_data) { 861 for (i = 0; i < len; i++) 862 RSIVAL(q, 4*i, data32s[i]); 863 } else { 864 for (i = 0; i < len; i++) 865 SIVAL(q, 4*i, data32s[i]); 866 } 867 } 868 869 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 870 if (charmode) 871 print_asc(5, (unsigned char*)data32s, 4*len); 872 else { 873 for (i = 0; i < len; i++) 874 DEBUG(5,("%08x ", data32s[i])); 875 } 876 DEBUG(5,("\n")); 877 878 ps->data_offset += (len * sizeof(uint32)); 879 880 return True; 881} 882 883/****************************************************************** 884 Stream an array of unicode string, length/buffer specified separately, 885 in uint16 chars. The unicode string is already in little-endian format. 886 ********************************************************************/ 887 888BOOL prs_buffer5(BOOL charmode, const char *name, prs_struct *ps, int depth, BUFFER5 *str) 889{ 890 char *p; 891 char *q = prs_mem_get(ps, str->buf_len * sizeof(uint16)); 892 if (q == NULL) 893 return False; 894 895 if (UNMARSHALLING(ps)) { 896 str->buffer = PRS_ALLOC_MEM(ps,uint16,str->buf_len); 897 if (str->buffer == NULL) 898 return False; 899 } 900 901 /* If the string is empty, we don't have anything to stream */ 902 if (str->buf_len==0) 903 return True; 904 905 p = (char *)str->buffer; 906 907 dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len); 908 909 ps->data_offset += (str->buf_len * sizeof(uint16)); 910 911 return True; 912} 913 914/****************************************************************** 915 Stream a "not" unicode string, length/buffer specified separately, 916 in byte chars. String is in little-endian format. 917 ********************************************************************/ 918 919BOOL prs_buffer2(BOOL charmode, const char *name, prs_struct *ps, int depth, BUFFER2 *str) 920{ 921 char *p; 922 char *q = prs_mem_get(ps, str->buf_len); 923 if (q == NULL) 924 return False; 925 926 if (UNMARSHALLING(ps)) { 927 if (str->buf_len > str->buf_max_len) { 928 return False; 929 } 930 if ( str->buf_max_len ) { 931 str->buffer = PRS_ALLOC_MEM(ps, uint16, str->buf_max_len); 932 if ( str->buffer == NULL ) 933 return False; 934 } 935 } 936 937 p = (char *)str->buffer; 938 939 dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len/2); 940 ps->data_offset += str->buf_len; 941 942 return True; 943} 944 945/****************************************************************** 946 Stream a string, length/buffer specified separately, 947 in uint8 chars. 948 ********************************************************************/ 949 950BOOL prs_string2(BOOL charmode, const char *name, prs_struct *ps, int depth, STRING2 *str) 951{ 952 unsigned int i; 953 char *q = prs_mem_get(ps, str->str_str_len); 954 if (q == NULL) 955 return False; 956 957 if (UNMARSHALLING(ps)) { 958 if (str->str_str_len > str->str_max_len) { 959 return False; 960 } 961 str->buffer = PRS_ALLOC_MEM(ps,unsigned char, str->str_max_len); 962 if (str->buffer == NULL) 963 return False; 964 } 965 966 if (UNMARSHALLING(ps)) { 967 for (i = 0; i < str->str_str_len; i++) 968 str->buffer[i] = CVAL(q,i); 969 } else { 970 for (i = 0; i < str->str_str_len; i++) 971 SCVAL(q, i, str->buffer[i]); 972 } 973 974 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 975 if (charmode) 976 print_asc(5, (unsigned char*)str->buffer, str->str_str_len); 977 else { 978 for (i = 0; i < str->str_str_len; i++) 979 DEBUG(5,("%02x ", str->buffer[i])); 980 } 981 DEBUG(5,("\n")); 982 983 ps->data_offset += str->str_str_len; 984 985 return True; 986} 987 988/****************************************************************** 989 Stream a unicode string, length/buffer specified separately, 990 in uint16 chars. The unicode string is already in little-endian format. 991 ********************************************************************/ 992 993BOOL prs_unistr2(BOOL charmode, const char *name, prs_struct *ps, int depth, UNISTR2 *str) 994{ 995 char *p; 996 char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16)); 997 if (q == NULL) 998 return False; 999 1000 /* If the string is empty, we don't have anything to stream */ 1001 if (str->uni_str_len==0) 1002 return True; 1003 1004 if (UNMARSHALLING(ps)) { 1005 if (str->uni_str_len > str->uni_max_len) { 1006 return False; 1007 } 1008 str->buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_max_len); 1009 if (str->buffer == NULL) 1010 return False; 1011 } 1012 1013 p = (char *)str->buffer; 1014 1015 dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len); 1016 1017 ps->data_offset += (str->uni_str_len * sizeof(uint16)); 1018 1019 return True; 1020} 1021 1022/****************************************************************** 1023 Stream a unicode string, length/buffer specified separately, 1024 in uint16 chars. The unicode string is already in little-endian format. 1025 ********************************************************************/ 1026 1027BOOL prs_unistr3(BOOL charmode, const char *name, UNISTR3 *str, prs_struct *ps, int depth) 1028{ 1029 char *p; 1030 char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16)); 1031 if (q == NULL) 1032 return False; 1033 1034 if (UNMARSHALLING(ps)) { 1035 str->str.buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_str_len); 1036 if (str->str.buffer == NULL) 1037 return False; 1038 } 1039 1040 p = (char *)str->str.buffer; 1041 1042 dbg_rw_punival(charmode, name, depth, ps, q, p, str->uni_str_len); 1043 ps->data_offset += (str->uni_str_len * sizeof(uint16)); 1044 1045 return True; 1046} 1047 1048/******************************************************************* 1049 Stream a unicode null-terminated string. As the string is already 1050 in little-endian format then do it as a stream of bytes. 1051 ********************************************************************/ 1052 1053BOOL prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str) 1054{ 1055 unsigned int len = 0; 1056 unsigned char *p = (unsigned char *)str->buffer; 1057 uint8 *start; 1058 char *q; 1059 uint32 max_len; 1060 uint16* ptr; 1061 1062 if (MARSHALLING(ps)) { 1063 1064 for(len = 0; str->buffer[len] != 0; len++) 1065 ; 1066 1067 q = prs_mem_get(ps, (len+1)*2); 1068 if (q == NULL) 1069 return False; 1070 1071 start = (uint8*)q; 1072 1073 for(len = 0; str->buffer[len] != 0; len++) { 1074 if(ps->bigendian_data) { 1075 /* swap bytes - p is little endian, q is big endian. */ 1076 q[0] = (char)p[1]; 1077 q[1] = (char)p[0]; 1078 p += 2; 1079 q += 2; 1080 } 1081 else 1082 { 1083 q[0] = (char)p[0]; 1084 q[1] = (char)p[1]; 1085 p += 2; 1086 q += 2; 1087 } 1088 } 1089 1090 /* 1091 * even if the string is 'empty' (only an \0 char) 1092 * at this point the leading \0 hasn't been parsed. 1093 * so parse it now 1094 */ 1095 1096 q[0] = 0; 1097 q[1] = 0; 1098 q += 2; 1099 1100 len++; 1101 1102 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 1103 print_asc(5, (unsigned char*)start, 2*len); 1104 DEBUG(5, ("\n")); 1105 } 1106 else { /* unmarshalling */ 1107 1108 uint32 alloc_len = 0; 1109 q = ps->data_p + prs_offset(ps); 1110 1111 /* 1112 * Work out how much space we need and talloc it. 1113 */ 1114 max_len = (ps->buffer_size - ps->data_offset)/sizeof(uint16); 1115 1116 /* the test of the value of *ptr helps to catch the circumstance 1117 where we have an emtpty (non-existent) string in the buffer */ 1118 for ( ptr = (uint16 *)q; *ptr++ && (alloc_len <= max_len); alloc_len++) 1119 /* do nothing */ 1120 ; 1121 1122 if (alloc_len < max_len) 1123 alloc_len += 1; 1124 1125 /* should we allocate anything at all? */ 1126 str->buffer = PRS_ALLOC_MEM(ps,uint16,alloc_len); 1127 if ((str->buffer == NULL) && (alloc_len > 0)) 1128 return False; 1129 1130 p = (unsigned char *)str->buffer; 1131 1132 len = 0; 1133 /* the (len < alloc_len) test is to prevent us from overwriting 1134 memory that is not ours...if we get that far, we have a non-null 1135 terminated string in the buffer and have messed up somewhere */ 1136 while ((len < alloc_len) && (*(uint16 *)q != 0)) { 1137 if(ps->bigendian_data) 1138 { 1139 /* swap bytes - q is big endian, p is little endian. */ 1140 p[0] = (unsigned char)q[1]; 1141 p[1] = (unsigned char)q[0]; 1142 p += 2; 1143 q += 2; 1144 } else { 1145 1146 p[0] = (unsigned char)q[0]; 1147 p[1] = (unsigned char)q[1]; 1148 p += 2; 1149 q += 2; 1150 } 1151 1152 len++; 1153 } 1154 if (len < alloc_len) { 1155 /* NULL terminate the UNISTR */ 1156 str->buffer[len++] = '\0'; 1157 } 1158 1159 DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name)); 1160 print_asc(5, (unsigned char*)str->buffer, 2*len); 1161 DEBUG(5, ("\n")); 1162 } 1163 1164 /* set the offset in the prs_struct; 'len' points to the 1165 terminiating NULL in the UNISTR so we need to go one more 1166 uint16 */ 1167 ps->data_offset += (len)*2; 1168 1169 return True; 1170} 1171 1172 1173/******************************************************************* 1174 Stream a null-terminated string. len is strlen, and therefore does 1175 not include the null-termination character. 1176 ********************************************************************/ 1177 1178BOOL prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_buf_size) 1179{ 1180 char *q; 1181 int i; 1182 int len; 1183 1184 if (UNMARSHALLING(ps)) 1185 len = strlen(&ps->data_p[ps->data_offset]); 1186 else 1187 len = strlen(str); 1188 1189 len = MIN(len, (max_buf_size-1)); 1190 1191 q = prs_mem_get(ps, len+1); 1192 if (q == NULL) 1193 return False; 1194 1195 for(i = 0; i < len; i++) { 1196 if (UNMARSHALLING(ps)) 1197 str[i] = q[i]; 1198 else 1199 q[i] = str[i]; 1200 } 1201 1202 /* The terminating null. */ 1203 str[i] = '\0'; 1204 1205 if (MARSHALLING(ps)) { 1206 q[i] = '\0'; 1207 } 1208 1209 ps->data_offset += len+1; 1210 1211 dump_data(5+depth, q, len); 1212 1213 return True; 1214} 1215 1216/******************************************************************* 1217 prs_uint16 wrapper. Call this and it sets up a pointer to where the 1218 uint16 should be stored, or gets the size if reading. 1219 ********************************************************************/ 1220 1221BOOL prs_uint16_pre(const char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset) 1222{ 1223 *offset = ps->data_offset; 1224 if (UNMARSHALLING(ps)) { 1225 /* reading. */ 1226 return prs_uint16(name, ps, depth, data16); 1227 } else { 1228 char *q = prs_mem_get(ps, sizeof(uint16)); 1229 if(q ==NULL) 1230 return False; 1231 ps->data_offset += sizeof(uint16); 1232 } 1233 return True; 1234} 1235 1236/******************************************************************* 1237 prs_uint16 wrapper. call this and it retrospectively stores the size. 1238 does nothing on reading, as that is already handled by ...._pre() 1239 ********************************************************************/ 1240 1241BOOL prs_uint16_post(const char *name, prs_struct *ps, int depth, uint16 *data16, 1242 uint32 ptr_uint16, uint32 start_offset) 1243{ 1244 if (MARSHALLING(ps)) { 1245 /* 1246 * Writing - temporarily move the offset pointer. 1247 */ 1248 uint16 data_size = ps->data_offset - start_offset; 1249 uint32 old_offset = ps->data_offset; 1250 1251 ps->data_offset = ptr_uint16; 1252 if(!prs_uint16(name, ps, depth, &data_size)) { 1253 ps->data_offset = old_offset; 1254 return False; 1255 } 1256 ps->data_offset = old_offset; 1257 } else { 1258 ps->data_offset = start_offset + (uint32)(*data16); 1259 } 1260 return True; 1261} 1262 1263/******************************************************************* 1264 prs_uint32 wrapper. Call this and it sets up a pointer to where the 1265 uint32 should be stored, or gets the size if reading. 1266 ********************************************************************/ 1267 1268BOOL prs_uint32_pre(const char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset) 1269{ 1270 *offset = ps->data_offset; 1271 if (UNMARSHALLING(ps) && (data32 != NULL)) { 1272 /* reading. */ 1273 return prs_uint32(name, ps, depth, data32); 1274 } else { 1275 ps->data_offset += sizeof(uint32); 1276 } 1277 return True; 1278} 1279 1280/******************************************************************* 1281 prs_uint32 wrapper. call this and it retrospectively stores the size. 1282 does nothing on reading, as that is already handled by ...._pre() 1283 ********************************************************************/ 1284 1285BOOL prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32, 1286 uint32 ptr_uint32, uint32 data_size) 1287{ 1288 if (MARSHALLING(ps)) { 1289 /* 1290 * Writing - temporarily move the offset pointer. 1291 */ 1292 uint32 old_offset = ps->data_offset; 1293 ps->data_offset = ptr_uint32; 1294 if(!prs_uint32(name, ps, depth, &data_size)) { 1295 ps->data_offset = old_offset; 1296 return False; 1297 } 1298 ps->data_offset = old_offset; 1299 } 1300 return True; 1301} 1302 1303/* useful function to store a structure in rpc wire format */ 1304int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps) 1305{ 1306 TDB_DATA kbuf, dbuf; 1307 kbuf.dptr = keystr; 1308 kbuf.dsize = strlen(keystr)+1; 1309 dbuf.dptr = ps->data_p; 1310 dbuf.dsize = prs_offset(ps); 1311 return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); 1312} 1313 1314/* useful function to fetch a structure into rpc wire format */ 1315int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *mem_ctx) 1316{ 1317 TDB_DATA kbuf, dbuf; 1318 kbuf.dptr = keystr; 1319 kbuf.dsize = strlen(keystr)+1; 1320 1321 dbuf = tdb_fetch(tdb, kbuf); 1322 if (!dbuf.dptr) 1323 return -1; 1324 1325 prs_init(ps, 0, mem_ctx, UNMARSHALL); 1326 prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True); 1327 1328 return 0; 1329} 1330 1331/******************************************************************* 1332 hash a stream. 1333 ********************************************************************/ 1334 1335BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) 1336{ 1337 char *q; 1338 1339 q = ps->data_p; 1340 q = &q[offset]; 1341 1342#ifdef DEBUG_PASSWORD 1343 DEBUG(100, ("prs_hash1\n")); 1344 dump_data(100, sess_key, 16); 1345 dump_data(100, q, len); 1346#endif 1347 SamOEMhash((uchar *) q, sess_key, len); 1348 1349#ifdef DEBUG_PASSWORD 1350 dump_data(100, q, len); 1351#endif 1352 1353 return True; 1354} 1355 1356/******************************************************************* 1357 Create a digest over the entire packet (including the data), and 1358 MD5 it with the session key. 1359 ********************************************************************/ 1360 1361static void netsec_digest(struct netsec_auth_struct *a, 1362 int auth_flags, 1363 RPC_AUTH_NETSEC_CHK * verf, 1364 char *data, size_t data_len, 1365 uchar digest_final[16]) 1366{ 1367 uchar whole_packet_digest[16]; 1368 static uchar zeros[4]; 1369 struct MD5Context ctx3; 1370 1371 /* verfiy the signature on the packet by MD5 over various bits */ 1372 MD5Init(&ctx3); 1373 /* use our sequence number, which ensures the packet is not 1374 out of order */ 1375 MD5Update(&ctx3, zeros, sizeof(zeros)); 1376 MD5Update(&ctx3, verf->sig, sizeof(verf->sig)); 1377 if (auth_flags & AUTH_PIPE_SEAL) { 1378 MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder)); 1379 } 1380 MD5Update(&ctx3, (const unsigned char *)data, data_len); 1381 MD5Final(whole_packet_digest, &ctx3); 1382 dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest)); 1383 1384 /* MD5 this result and the session key, to prove that 1385 only a valid client could had produced this */ 1386 hmac_md5(a->sess_key, whole_packet_digest, sizeof(whole_packet_digest), digest_final); 1387} 1388 1389/******************************************************************* 1390 Calculate the key with which to encode the data payload 1391 ********************************************************************/ 1392 1393static void netsec_get_sealing_key(struct netsec_auth_struct *a, 1394 RPC_AUTH_NETSEC_CHK *verf, 1395 uchar sealing_key[16]) 1396{ 1397 static uchar zeros[4]; 1398 uchar digest2[16]; 1399 uchar sess_kf0[16]; 1400 int i; 1401 1402 for (i = 0; i < sizeof(sess_kf0); i++) { 1403 sess_kf0[i] = a->sess_key[i] ^ 0xf0; 1404 } 1405 1406 dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); 1407 1408 /* MD5 of sess_kf0 and 4 zero bytes */ 1409 hmac_md5(sess_kf0, zeros, 0x4, digest2); 1410 dump_data_pw("digest2:\n", digest2, sizeof(digest2)); 1411 1412 /* MD5 of the above result, plus 8 bytes of sequence number */ 1413 hmac_md5(digest2, verf->seq_num, sizeof(verf->seq_num), sealing_key); 1414 dump_data_pw("sealing_key:\n", sealing_key, 16); 1415} 1416 1417/******************************************************************* 1418 Encode or Decode the sequence number (which is symmetric) 1419 ********************************************************************/ 1420 1421static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, 1422 RPC_AUTH_NETSEC_CHK *verf) 1423{ 1424 static uchar zeros[4]; 1425 uchar sequence_key[16]; 1426 uchar digest1[16]; 1427 1428 hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1); 1429 dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1)); 1430 1431 hmac_md5(digest1, verf->packet_digest, 8, sequence_key); 1432 1433 dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key)); 1434 1435 dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num)); 1436 SamOEMhash(verf->seq_num, sequence_key, 8); 1437 dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num)); 1438} 1439 1440/******************************************************************* 1441creates an RPC_AUTH_NETSEC_CHK structure. 1442********************************************************************/ 1443 1444static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, 1445 const uchar sig[8], 1446 const uchar packet_digest[8], 1447 const uchar seq_num[8], const uchar confounder[8]) 1448{ 1449 if (chk == NULL) 1450 return False; 1451 1452 memcpy(chk->sig, sig, sizeof(chk->sig)); 1453 memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest)); 1454 memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num)); 1455 memcpy(chk->confounder, confounder, sizeof(chk->confounder)); 1456 1457 return True; 1458} 1459 1460/******************************************************************* 1461 Encode a blob of data using the netsec (schannel) alogrithm, also produceing 1462 a checksum over the original data. We currently only support 1463 signing and sealing togeather - the signing-only code is close, but not 1464 quite compatible with what MS does. 1465 ********************************************************************/ 1466 1467void netsec_encode(struct netsec_auth_struct *a, int auth_flags, 1468 enum netsec_direction direction, 1469 RPC_AUTH_NETSEC_CHK * verf, 1470 char *data, size_t data_len) 1471{ 1472 uchar digest_final[16]; 1473 uchar confounder[8]; 1474 uchar seq_num[8]; 1475 static const uchar nullbytes[8]; 1476 1477 static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; 1478 static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; 1479 const uchar *netsec_sig = NULL; 1480 1481 DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); 1482 1483 if (auth_flags & AUTH_PIPE_SEAL) { 1484 netsec_sig = netsec_seal_sig; 1485 } else if (auth_flags & AUTH_PIPE_SIGN) { 1486 netsec_sig = netsec_sign_sig; 1487 } 1488 1489 /* fill the 'confounder' with random data */ 1490 generate_random_buffer(confounder, sizeof(confounder)); 1491 1492 dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); 1493 1494 RSIVAL(seq_num, 0, a->seq_num); 1495 1496 switch (direction) { 1497 case SENDER_IS_INITIATOR: 1498 SIVAL(seq_num, 4, 0x80); 1499 break; 1500 case SENDER_IS_ACCEPTOR: 1501 SIVAL(seq_num, 4, 0x0); 1502 break; 1503 } 1504 1505 dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num)); 1506 1507 init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes, 1508 seq_num, confounder); 1509 1510 /* produce a digest of the packet to prove it's legit (before we seal it) */ 1511 netsec_digest(a, auth_flags, verf, data, data_len, digest_final); 1512 memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest)); 1513 1514 if (auth_flags & AUTH_PIPE_SEAL) { 1515 uchar sealing_key[16]; 1516 1517 /* get the key to encode the data with */ 1518 netsec_get_sealing_key(a, verf, sealing_key); 1519 1520 /* encode the verification data */ 1521 dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder)); 1522 SamOEMhash(verf->confounder, sealing_key, 8); 1523 1524 dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder)); 1525 1526 /* encode the packet payload */ 1527 dump_data_pw("data:\n", (const unsigned char *)data, data_len); 1528 SamOEMhash((unsigned char *)data, sealing_key, data_len); 1529 dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len); 1530 } 1531 1532 /* encode the sequence number (key based on packet digest) */ 1533 /* needs to be done after the sealing, as the original version 1534 is used in the sealing stuff... */ 1535 netsec_deal_with_seq_num(a, verf); 1536 1537 return; 1538} 1539 1540/******************************************************************* 1541 Decode a blob of data using the netsec (schannel) alogrithm, also verifiying 1542 a checksum over the original data. We currently can verify signed messages, 1543 as well as decode sealed messages 1544 ********************************************************************/ 1545 1546BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, 1547 enum netsec_direction direction, 1548 RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) 1549{ 1550 uchar digest_final[16]; 1551 1552 static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; 1553 static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; 1554 const uchar *netsec_sig = NULL; 1555 1556 uchar seq_num[8]; 1557 1558 DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); 1559 1560 if (auth_flags & AUTH_PIPE_SEAL) { 1561 netsec_sig = netsec_seal_sig; 1562 } else if (auth_flags & AUTH_PIPE_SIGN) { 1563 netsec_sig = netsec_sign_sig; 1564 } 1565 1566 /* Create the expected sequence number for comparison */ 1567 RSIVAL(seq_num, 0, a->seq_num); 1568 1569 switch (direction) { 1570 case SENDER_IS_INITIATOR: 1571 SIVAL(seq_num, 4, 0x80); 1572 break; 1573 case SENDER_IS_ACCEPTOR: 1574 SIVAL(seq_num, 4, 0x0); 1575 break; 1576 } 1577 1578 DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); 1579 dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); 1580 1581 dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num)); 1582 1583 /* extract the sequence number (key based on supplied packet digest) */ 1584 /* needs to be done before the sealing, as the original version 1585 is used in the sealing stuff... */ 1586 netsec_deal_with_seq_num(a, verf); 1587 1588 if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) { 1589 /* don't even bother with the below if the sequence number is out */ 1590 /* The sequence number is MD5'ed with a key based on the whole-packet 1591 digest, as supplied by the client. We check that it's a valid 1592 checksum after the decode, below 1593 */ 1594 DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n")); 1595 dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num)); 1596 DEBUG(2, ("should be:\n")); 1597 dump_data(2, (const char*)seq_num, sizeof(seq_num)); 1598 1599 return False; 1600 } 1601 1602 if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) { 1603 /* Validate that the other end sent the expected header */ 1604 DEBUG(2, ("netsec_decode: FAILED: packet header:\n")); 1605 dump_data(2, (const char*)verf->sig, sizeof(verf->sig)); 1606 DEBUG(2, ("should be:\n")); 1607 dump_data(2, (const char*)netsec_sig, sizeof(netsec_sig)); 1608 return False; 1609 } 1610 1611 if (auth_flags & AUTH_PIPE_SEAL) { 1612 uchar sealing_key[16]; 1613 1614 /* get the key to extract the data with */ 1615 netsec_get_sealing_key(a, verf, sealing_key); 1616 1617 /* extract the verification data */ 1618 dump_data_pw("verf->confounder:\n", verf->confounder, 1619 sizeof(verf->confounder)); 1620 SamOEMhash(verf->confounder, sealing_key, 8); 1621 1622 dump_data_pw("verf->confounder_dec:\n", verf->confounder, 1623 sizeof(verf->confounder)); 1624 1625 /* extract the packet payload */ 1626 dump_data_pw("data :\n", (const unsigned char *)data, data_len); 1627 SamOEMhash((unsigned char *)data, sealing_key, data_len); 1628 dump_data_pw("datadec:\n", (const unsigned char *)data, data_len); 1629 } 1630 1631 /* digest includes 'data' after unsealing */ 1632 netsec_digest(a, auth_flags, verf, data, data_len, digest_final); 1633 1634 dump_data_pw("Calculated digest:\n", digest_final, 1635 sizeof(digest_final)); 1636 dump_data_pw("verf->packet_digest:\n", verf->packet_digest, 1637 sizeof(verf->packet_digest)); 1638 1639 /* compare - if the client got the same result as us, then 1640 it must know the session key */ 1641 return (memcmp(digest_final, verf->packet_digest, 1642 sizeof(verf->packet_digest)) == 0); 1643} 1644