1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 24 */ 25 26 #include <assert.h> 27 #include <strings.h> 28 #include <sys/param.h> 29 #include <sys/debug.h> 30 31 #include <libmlrpc.h> 32 33 #ifdef _BIG_ENDIAN 34 static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN; 35 #else 36 static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN; 37 #endif 38 39 static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *); 40 static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *); 41 42 /* 43 * This is the layout of an RPC PDU, as shown in 44 * [MS-RPCE] 2.2.2.13 "Verification Trailer". 45 * 46 * +-------------------------------+ 47 * | PDU Header | 48 * +-------------------------------+ ==== 49 * | Stub Data | 50 * +-------------------------------+ PDU 51 * | Stub Padding Octets | 52 * +-------------------------------+ Body 53 * | Verification Trailer | 54 * +-------------------------------+ Here 55 * | Authentication Padding | 56 * +-------------------------------+ ==== 57 * | sec_trailer | 58 * +-------------------------------+ 59 * | Authentication Token | 60 * +-------------------------------+ 61 * 62 * We don't use the "Verification Trailer" for anything yet. 63 * sec_trailer and Authentication Token are for Secure RPC, 64 * and are collectively the 'auth_verifier_co' in DCERPC. 65 * 66 * Each fragment of a multi-fragment response has a unique 67 * header and, if authentication was requested, a unique 68 * sec_trailer. 69 */ 70 71 static int 72 ndr_convert_nds_error(ndr_stream_t *nds) 73 { 74 int rc; 75 76 switch (nds->error) { 77 case NDR_ERR_MALLOC_FAILED: 78 rc = NDR_DRC_FAULT_OUT_OF_MEMORY; 79 break; 80 81 case NDR_ERR_SWITCH_VALUE_INVALID: 82 rc = NDR_DRC_FAULT_PARAM_0_INVALID; 83 break; 84 85 case NDR_ERR_UNDERFLOW: 86 rc = NDR_DRC_FAULT_RECEIVED_RUNT; 87 break; 88 89 case NDR_ERR_GROW_FAILED: 90 rc = NDR_DRC_FAULT_ENCODE_TOO_BIG; 91 break; 92 93 default: 94 if (nds->m_op == NDR_M_OP_MARSHALL) 95 rc = NDR_DRC_FAULT_ENCODE_FAILED; 96 else 97 rc = NDR_DRC_FAULT_DECODE_FAILED; 98 break; 99 } 100 101 return (rc); 102 } 103 104 static int 105 ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum, 106 ndr_typeinfo_t *ti, void *datum) 107 { 108 /* 109 * Perform the (un)marshalling 110 */ 111 if (ndo_operation(nds, ti, opnum, datum)) 112 return (NDR_DRC_OK); 113 114 return (ndr_convert_nds_error(nds)); 115 } 116 117 static int 118 ndr_encode_decode_type(ndr_stream_t *nds, ndr_typeinfo_t *ti, void *datum) 119 { 120 /* 121 * Perform the (un)marshalling 122 */ 123 if (ndo_process(nds, ti, datum)) 124 return (NDR_DRC_OK); 125 126 return (ndr_convert_nds_error(nds)); 127 } 128 129 ndr_buf_t * 130 ndr_buf_init(ndr_typeinfo_t *ti) 131 { 132 ndr_buf_t *nbuf; 133 134 if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL) 135 return (NULL); 136 137 if ((nbuf->nb_heap = ndr_heap_create()) == NULL) { 138 free(nbuf); 139 return (NULL); 140 } 141 142 nbuf->nb_ti = ti; 143 nbuf->nb_magic = NDR_BUF_MAGIC; 144 return (nbuf); 145 } 146 147 void 148 ndr_buf_fini(ndr_buf_t *nbuf) 149 { 150 assert(nbuf->nb_magic == NDR_BUF_MAGIC); 151 152 nds_destruct(&nbuf->nb_nds); 153 ndr_heap_destroy(nbuf->nb_heap); 154 nbuf->nb_magic = 0; 155 free(nbuf); 156 } 157 158 /* 159 * Decode an NDR encoded buffer. The buffer is expected to contain 160 * a single fragment packet with a valid PDU header followed by NDR 161 * encoded data. The structure to which result points should be 162 * of the appropriate type to hold the decoded output. For example: 163 * 164 * pac_info_t info; 165 * 166 * if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) { 167 * rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info); 168 * ... 169 * ndr_buf_fini(nbuf); 170 * } 171 */ 172 int 173 ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum, 174 const char *data, size_t datalen, void *result) 175 { 176 ndr_common_header_t hdr; 177 ndr_pac_hdr_t pac_hdr; 178 unsigned pdu_size_hint; 179 int rc; 180 181 assert(nbuf->nb_magic == NDR_BUF_MAGIC); 182 assert(nbuf->nb_heap != NULL); 183 assert(nbuf->nb_ti != NULL); 184 185 if (datalen < NDR_PDU_SIZE_HINT_DEFAULT) 186 pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT; 187 else 188 pdu_size_hint = datalen; 189 190 rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE, 191 nbuf->nb_heap); 192 if (NDR_DRC_IS_FAULT(rc)) 193 return (rc); 194 195 bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen); 196 nbuf->nb_nds.pdu_size = datalen; 197 198 switch (hdr_type) { 199 case NDR_PTYPE_COMMON: 200 rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr); 201 if (NDR_DRC_IS_FAULT(rc)) 202 return (rc); 203 204 if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags)) 205 return (NDR_DRC_FAULT_DECODE_FAILED); 206 break; 207 208 case NDR_PTYPE_PAC: 209 rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr); 210 if (NDR_DRC_IS_FAULT(rc)) 211 return (rc); 212 213 if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t)) 214 return (NDR_DRC_FAULT_DECODE_FAILED); 215 break; 216 217 default: 218 return (NDR_ERR_UNIMPLEMENTED); 219 } 220 221 rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti, 222 result); 223 return (rc); 224 } 225 226 /* 227 * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV). 228 */ 229 int 230 ndr_decode_call(ndr_xa_t *mxa, void *params) 231 { 232 ndr_stream_t *nds = &mxa->recv_nds; 233 int rc; 234 235 if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV)) 236 return (NDR_DRC_FAULT_MODE_MISMATCH); 237 238 rc = ndr_encode_decode_common(nds, mxa->opnum, 239 mxa->binding->service->interface_ti, params); 240 241 return (rc + NDR_PTYPE_REQUEST); 242 } 243 244 /* 245 * Use the send stream to marshall data (NDR_MODE_RETURN_SEND). 246 */ 247 int 248 ndr_encode_return(ndr_xa_t *mxa, void *params) 249 { 250 ndr_stream_t *nds = &mxa->send_nds; 251 int rc; 252 253 if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) 254 return (NDR_DRC_FAULT_MODE_MISMATCH); 255 256 rc = ndr_encode_decode_common(nds, mxa->opnum, 257 mxa->binding->service->interface_ti, params); 258 259 return (rc + NDR_PTYPE_RESPONSE); 260 } 261 262 /* 263 * Use the send stream to marshall data (NDR_MODE_CALL_SEND). 264 */ 265 int 266 ndr_encode_call(ndr_xa_t *mxa, void *params) 267 { 268 ndr_stream_t *nds = &mxa->send_nds; 269 int rc; 270 271 if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND)) 272 return (NDR_DRC_FAULT_MODE_MISMATCH); 273 274 rc = ndr_encode_decode_common(nds, mxa->opnum, 275 mxa->binding->service->interface_ti, params); 276 277 return (rc + NDR_PTYPE_REQUEST); 278 } 279 280 /* 281 * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV). 282 */ 283 int 284 ndr_decode_return(ndr_xa_t *mxa, void *params) 285 { 286 ndr_stream_t *nds = &mxa->recv_nds; 287 int rc; 288 289 if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV)) 290 return (NDR_DRC_FAULT_MODE_MISMATCH); 291 292 rc = ndr_encode_decode_common(nds, mxa->opnum, 293 mxa->binding->service->interface_ti, params); 294 295 return (rc + NDR_PTYPE_RESPONSE); 296 } 297 298 int 299 ndr_decode_pdu_hdr(ndr_xa_t *mxa) 300 { 301 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr; 302 ndr_stream_t *nds = &mxa->recv_nds; 303 int rc; 304 ulong_t saved_offset; 305 306 saved_offset = nds->pdu_scan_offset; 307 rc = ndr_decode_hdr_common(nds, hdr); 308 if (NDR_DRC_IS_FAULT(rc)) 309 return (rc); 310 311 /* 312 * Verify the protocol version. 313 */ 314 if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0)) 315 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); 316 317 mxa->ptype = hdr->ptype; 318 /* pdu_scan_offset now points to (this fragment's) stub data */ 319 nds->pdu_body_offset = nds->pdu_scan_offset; 320 nds->pdu_hdr_size = nds->pdu_scan_offset - saved_offset; 321 nds->pdu_body_size = hdr->frag_length - hdr->auth_length - 322 nds->pdu_hdr_size - 323 ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0); 324 325 if (hdr->auth_length != 0 && hdr->auth_length > 326 (hdr->frag_length - nds->pdu_hdr_size - SEC_TRAILER_SIZE)) 327 return (NDR_DRC_FAULT_RECEIVED_MALFORMED); 328 return (NDR_DRC_OK); 329 } 330 331 static int 332 ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) 333 { 334 int ptype; 335 int rc; 336 int charset; 337 int byte_order; 338 ulong_t saved_offset; 339 340 if (nds->m_op != NDR_M_OP_UNMARSHALL) 341 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); 342 343 /* 344 * All PDU headers are at least this big 345 */ 346 saved_offset = nds->pdu_scan_offset; 347 if ((nds->pdu_size - saved_offset) < sizeof (ndr_common_header_t)) 348 return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); 349 350 /* 351 * Peek at the first eight bytes to figure out what we're doing. 352 */ 353 rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); 354 if (!rc) 355 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); 356 357 /* 358 * Check for ASCII as the character set. This is an ASCII 359 * versus EBCDIC option and has nothing to do with Unicode. 360 */ 361 charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK; 362 if (charset != NDR_REPLAB_CHAR_ASCII) 363 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); 364 365 /* 366 * Set the byte swap flag if the PDU byte-order 367 * is different from the local byte-order. 368 */ 369 byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK; 370 nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0; 371 372 ptype = hdr->ptype; 373 if (ptype == NDR_PTYPE_REQUEST && 374 (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) { 375 ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */ 376 } 377 378 rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr); 379 380 if (hdr->frag_length > (nds->pdu_size - saved_offset)) 381 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED; 382 return (NDR_DRC_PTYPE_RPCHDR(rc)); 383 } 384 385 static int 386 ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr) 387 { 388 int rc; 389 390 if (nds->m_op != NDR_M_OP_UNMARSHALL) 391 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); 392 393 /* 394 * All PDU headers are at least this big 395 */ 396 if ((nds->pdu_size - nds->pdu_scan_offset) < sizeof (ndr_pac_hdr_t)) 397 return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); 398 399 /* 400 * Peek at the first eight bytes to figure out what we're doing. 401 */ 402 rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); 403 if (!rc) 404 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); 405 406 /* Must be set to 1 to indicate type serialization version 1. */ 407 if (hdr->common_hdr.version != 1) 408 return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); 409 410 /* 411 * Set the byte swap flag if the PDU byte-order 412 * is different from the local byte-order. 413 */ 414 nds->swap = 415 (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0; 416 417 rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC, 418 &TYPEINFO(ndr_hdr), hdr); 419 420 return (NDR_DRC_PTYPE_RPCHDR(rc)); 421 } 422 423 CTASSERT(sizeof (ndr_common_header_t) >= NDR_CMN_HDR_SIZE); 424 425 /* 426 * Decode an RPC fragment header. Use ndr_decode_pdu_hdr() to process 427 * the first fragment header then this function to process additional 428 * fragment headers. 429 */ 430 void 431 ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr) 432 { 433 ndr_common_header_t *tmp; 434 uint8_t *pdu; 435 int byte_order; 436 437 pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset; 438 bcopy(pdu, hdr, NDR_CMN_HDR_SIZE); 439 440 /* 441 * Swap non-byte fields if the PDU byte-order 442 * is different from the local byte-order. 443 */ 444 byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK; 445 446 if (byte_order != ndr_native_byte_order) { 447 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 448 tmp = (ndr_common_header_t *)pdu; 449 450 nds_bswap(&tmp->frag_length, &hdr->frag_length, 451 sizeof (WORD)); 452 nds_bswap(&tmp->auth_length, &hdr->auth_length, 453 sizeof (WORD)); 454 nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD)); 455 } 456 457 /* pdu_scan_offset points to byte 0 of this fragment */ 458 nds->pdu_hdr_size = NDR_RSP_HDR_SIZE; 459 nds->pdu_body_offset = nds->pdu_scan_offset + nds->pdu_hdr_size; 460 nds->pdu_body_size = hdr->frag_length - hdr->auth_length - 461 nds->pdu_hdr_size - 462 ((hdr->auth_length != 0) ? SEC_TRAILER_SIZE : 0); 463 } 464 465 /* 466 * Remove an RPC fragment header from the received data stream. 467 * 468 * NDR stream on entry: 469 * 470 * |<--- frag --->| 471 * +-----+--------+-----+--------+-----+---------+-----+ 472 * | hdr | data | hdr | data | hdr | data | ... | 473 * +-----+--------+-----+--------+-----+---------+-----+ 474 * <---- 475 * 476 * NDR stream on return: 477 * 478 * +-----+----------------+-----+---------+-----+ 479 * | hdr | data | hdr | data | ... | 480 * +-----+----------------+-----+---------+-----+ 481 */ 482 void 483 ndr_remove_frag_hdr(ndr_stream_t *nds) 484 { 485 char *hdr; 486 char *data; 487 int nbytes; 488 489 hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset; 490 data = hdr + NDR_RSP_HDR_SIZE; 491 nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE; 492 493 /* 494 * Move all of the data after the header back to where the header began. 495 */ 496 memmove(hdr, data, nbytes); 497 nds->pdu_size -= NDR_RSP_HDR_SIZE; 498 } 499 500 void 501 ndr_show_hdr(ndr_common_header_t *hdr) 502 { 503 char *fragtype; 504 505 if (hdr == NULL) { 506 ndo_printf(NULL, NULL, "ndr hdr: <null>"); 507 return; 508 } 509 510 if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags)) 511 fragtype = "single"; 512 else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags)) 513 fragtype = "first"; 514 else if (NDR_IS_LAST_FRAG(hdr->pfc_flags)) 515 fragtype = "last"; 516 else 517 fragtype = "intermediate"; 518 519 ndo_printf(NULL, NULL, 520 "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d " 521 "auth_len=%d", 522 hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype, 523 fragtype, hdr->pfc_flags, hdr->frag_length, hdr->auth_length); 524 } 525 526 void 527 ndr_show_auth(ndr_sec_t *auth) 528 { 529 if (auth == NULL) { 530 ndo_printf(NULL, NULL, "ndr auth: <null>"); 531 return; 532 } 533 534 ndo_printf(NULL, NULL, 535 "ndr auth: type=0x%x, level=0x%x, pad_len=%d, ctx_id=%d", 536 auth->auth_type, auth->auth_level, auth->auth_pad_len, 537 auth->auth_context_id); 538 } 539 540 int 541 ndr_encode_pdu_hdr(ndr_xa_t *mxa) 542 { 543 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr; 544 ndr_stream_t *nds = &mxa->send_nds; 545 int ptype; 546 int rc; 547 548 if (nds->m_op != NDR_M_OP_MARSHALL) 549 return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); 550 551 ptype = hdr->ptype; 552 if (ptype == NDR_PTYPE_REQUEST && 553 (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) { 554 ptype = NDR_PTYPE_REQUEST_WITH; /* fake for sizing */ 555 } 556 557 rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr); 558 559 return (NDR_DRC_PTYPE_RPCHDR(rc)); 560 } 561 562 /* 563 * This is a hand-coded derivative of the automatically generated 564 * (un)marshalling routine for bind_ack headers. bind_ack headers 565 * have an interior conformant array, which is inconsistent with 566 * IDL/NDR rules. 567 */ 568 extern struct ndr_typeinfo ndt__uchar; 569 extern struct ndr_typeinfo ndt__ushort; 570 extern struct ndr_typeinfo ndt__ulong; 571 572 int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref); 573 ndr_typeinfo_t ndt__ndr_bind_ack_hdr = { 574 1, /* NDR version */ 575 3, /* alignment */ 576 NDR_F_STRUCT, /* flags */ 577 ndr__ndr_bind_ack_hdr, /* ndr_func */ 578 68, /* pdu_size_fixed_part */ 579 0, /* pdu_size_variable_part */ 580 68, /* c_size_fixed_part */ 581 0, /* c_size_variable_part */ 582 }; 583 584 /* 585 * [_no_reorder] 586 */ 587 int 588 ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref) 589 { 590 ndr_stream_t *nds = encl_ref->stream; 591 struct ndr_bind_ack_hdr *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/ 592 (struct ndr_bind_ack_hdr *)encl_ref->datum; 593 ndr_ref_t myref; 594 unsigned long offset; 595 596 bzero(&myref, sizeof (myref)); 597 myref.enclosing = encl_ref; 598 myref.stream = encl_ref->stream; 599 myref.packed_alignment = 0; 600 601 /* do all members in order */ 602 NDR_MEMBER(_ndr_common_header, common_hdr, 0UL); 603 NDR_MEMBER(_ushort, max_xmit_frag, 16UL); 604 NDR_MEMBER(_ushort, max_recv_frag, 18UL); 605 NDR_MEMBER(_ulong, assoc_group_id, 20UL); 606 607 /* port any is the conformant culprit */ 608 offset = 24UL; 609 610 switch (nds->m_op) { 611 case NDR_M_OP_MARSHALL: 612 val->sec_addr.length = 613 strlen((char *)val->sec_addr.port_spec) + 1; 614 break; 615 616 case NDR_M_OP_UNMARSHALL: 617 break; 618 619 default: 620 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID); 621 return (0); 622 } 623 624 NDR_MEMBER(_ushort, sec_addr.length, offset); 625 NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec, 626 offset+2UL, val->sec_addr.length); 627 628 offset += 2; 629 offset += val->sec_addr.length; 630 offset += NDR_ALIGN4(offset); 631 632 NDR_MEMBER(_ndr_p_result_list, p_result_list, offset); 633 return (1); 634 } 635 636 /* 637 * Assume a single presentation context element in the result list. 638 */ 639 unsigned 640 ndr_bind_ack_hdr_size(ndr_xa_t *mxa) 641 { 642 ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr; 643 unsigned offset; 644 unsigned length; 645 646 /* port any is the conformant culprit */ 647 offset = 24UL; 648 649 length = strlen((char *)bahdr->sec_addr.port_spec) + 1; 650 651 offset += 2; 652 offset += length; 653 offset += NDR_ALIGN4(offset); 654 offset += sizeof (ndr_p_result_list_t); 655 return (offset); 656 } 657 658 /* 659 * This is a hand-coded derivative of the automatically generated 660 * (un)marshalling routine for alter_context_rsp headers. 661 * Alter context response headers have an interior conformant array, 662 * which is inconsistent with IDL/NDR rules. 663 */ 664 int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref); 665 ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = { 666 1, /* NDR version */ 667 3, /* alignment */ 668 NDR_F_STRUCT, /* flags */ 669 ndr__ndr_alter_context_rsp_hdr, /* ndr_func */ 670 56, /* pdu_size_fixed_part */ 671 0, /* pdu_size_variable_part */ 672 56, /* c_size_fixed_part */ 673 0, /* c_size_variable_part */ 674 }; 675 676 /* 677 * [_no_reorder] 678 */ 679 int 680 ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref) 681 { 682 ndr_stream_t *nds = encl_ref->stream; 683 ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/ 684 (ndr_alter_context_rsp_hdr_t *)encl_ref->datum; 685 ndr_ref_t myref; 686 unsigned long offset; 687 688 bzero(&myref, sizeof (myref)); 689 myref.enclosing = encl_ref; 690 myref.stream = encl_ref->stream; 691 myref.packed_alignment = 0; 692 693 /* do all members in order */ 694 NDR_MEMBER(_ndr_common_header, common_hdr, 0UL); 695 NDR_MEMBER(_ushort, max_xmit_frag, 16UL); 696 NDR_MEMBER(_ushort, max_recv_frag, 18UL); 697 NDR_MEMBER(_ulong, assoc_group_id, 20UL); 698 699 offset = 24UL; /* offset of sec_addr */ 700 701 switch (nds->m_op) { 702 case NDR_M_OP_MARSHALL: 703 val->sec_addr.length = 0; 704 break; 705 706 case NDR_M_OP_UNMARSHALL: 707 break; 708 709 default: 710 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID); 711 return (0); 712 } 713 714 NDR_MEMBER(_ushort, sec_addr.length, offset); 715 NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec, 716 offset+2UL, val->sec_addr.length); 717 718 offset += 2; /* sizeof (sec_addr.length) */ 719 offset += NDR_ALIGN4(offset); 720 721 NDR_MEMBER(_ndr_p_result_list, p_result_list, offset); 722 return (1); 723 } 724 725 /* 726 * Assume a single presentation context element in the result list. 727 */ 728 unsigned 729 ndr_alter_context_rsp_hdr_size(void) 730 { 731 unsigned offset; 732 733 offset = 24UL; /* offset of sec_addr */ 734 offset += 2; /* sizeof (sec_addr.length) */ 735 offset += NDR_ALIGN4(offset); 736 offset += sizeof (ndr_p_result_list_t); 737 return (offset); 738 } 739 740 /* 741 * This is a hand-coded (un)marshalling routine for auth_verifier_co 742 * (aka ndr_sec_t). 743 * 744 * We need to pretend this structure isn't variably sized, until ndrgen 745 * has been modified to support variable-sized arrays. 746 * Here, we only account for the fixed-size members (8 bytes), plus 747 * a pointer for the C structure. 748 * 749 * We then convert between a pointer to the auth token (auth_value, 750 * allocated here during unmarshall) and a flat, 'fixed'-sized array. 751 */ 752 753 int ndr__auth_verifier_co(ndr_ref_t *encl_ref); 754 ndr_typeinfo_t ndt__auth_verifier_co = { 755 1, /* NDR version */ 756 3, /* alignment */ 757 NDR_F_STRUCT, /* flags */ 758 ndr__auth_verifier_co, /* ndr_func */ 759 8, /* pdu_size_fixed_part */ 760 0, /* pdu_size_variable_part */ 761 8 + sizeof (void *), /* c_size_fixed_part */ 762 0, /* c_size_variable_part */ 763 }; 764 765 /* 766 * [_no_reorder] 767 */ 768 int 769 ndr__auth_verifier_co(ndr_ref_t *encl_ref) 770 { 771 ndr_stream_t *nds = encl_ref->stream; 772 ndr_xa_t *mxa = /*LINTED E_BAD_PTR_CAST_ALIGN*/ 773 (ndr_xa_t *)encl_ref->datum; 774 ndr_common_header_t *hdr; 775 ndr_ref_t myref; 776 ndr_sec_t *val; 777 778 /* 779 * Assumes scan_offset points to the end of PDU body. 780 * (That's base + frag_len - auth_len - SEC_TRAILER_SIZE) 781 * 782 * At some point, NDRGEN could use struct initializers instead of 783 * bzero() + initialization. 784 */ 785 bzero(&myref, sizeof (myref)); 786 myref.enclosing = encl_ref; 787 myref.stream = encl_ref->stream; 788 789 switch (nds->m_op) { 790 case NDR_M_OP_MARSHALL: 791 val = &mxa->send_auth; 792 hdr = &mxa->send_hdr.common_hdr; 793 break; 794 795 case NDR_M_OP_UNMARSHALL: 796 val = &mxa->recv_auth; 797 hdr = &mxa->recv_hdr.common_hdr; 798 val->auth_value = (uchar_t *)NDS_MALLOC(nds, hdr->auth_length, 799 encl_ref); 800 break; 801 802 default: 803 NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID); 804 return (0); 805 } 806 807 /* 808 * ndr_topmost() can't account for auth_length (pdu_scan/end_offset). 809 * This would only matter if any of this struct's members 810 * are treated as 'outer' constructs, but they aren't. 811 */ 812 encl_ref->pdu_end_offset += hdr->auth_length; 813 nds->pdu_scan_offset += hdr->auth_length; 814 815 NDR_MEMBER(_uchar, auth_type, 0UL); 816 NDR_MEMBER(_uchar, auth_level, 1UL); 817 NDR_MEMBER(_uchar, auth_pad_len, 2UL); 818 NDR_MEMBER(_uchar, auth_rsvd, 3UL); 819 NDR_MEMBER(_ulong, auth_context_id, 4UL); 820 821 NDR_MEMBER_PTR_WITH_DIMENSION(_uchar, auth_value, 8UL, 822 hdr->auth_length); 823 824 return (1); 825 } 826 827 int 828 ndr_encode_pdu_auth(ndr_xa_t *mxa) 829 { 830 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr; 831 ndr_stream_t *nds = &mxa->send_nds; 832 int rc; 833 ulong_t want_size; 834 835 if (nds->m_op != NDR_M_OP_MARSHALL) 836 return (NDR_DRC_FAULT_MODE_MISMATCH); 837 838 if (hdr->auth_length == 0) 839 return (NDR_DRC_OK); 840 841 want_size = nds->pdu_scan_offset + hdr->auth_length + SEC_TRAILER_SIZE; 842 843 /* 844 * Make sure we have space for the sec trailer - the marshaller 845 * doesn't know how large the auth token is. 846 * Note: ndr_add_auth_token() has already added padding. 847 * 848 * NDS_GROW_PDU will adjust pdu_size for us. 849 */ 850 if (nds->pdu_max_size < want_size) { 851 if (NDS_GROW_PDU(nds, want_size, NULL) == 0) 852 return (NDR_DRC_FAULT_ENCODE_TOO_BIG); 853 } else { 854 nds->pdu_size = want_size; 855 } 856 rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co), 857 mxa); 858 859 return (rc); 860 } 861 862 int 863 ndr_decode_pdu_auth(ndr_xa_t *mxa) 864 { 865 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr; 866 ndr_stream_t *nds = &mxa->recv_nds; 867 ndr_sec_t *auth = &mxa->recv_auth; 868 int rc; 869 ulong_t saved_offset; 870 size_t auth_size; 871 872 if (nds->m_op != NDR_M_OP_UNMARSHALL) 873 return (NDR_DRC_FAULT_MODE_MISMATCH); 874 875 mxa->recv_auth.auth_pad_len = 0; 876 if (hdr->auth_length == 0) 877 return (NDR_DRC_OK); 878 879 /* 880 * Save the current offset, and skip to the sec_trailer. 881 * That's located after the (fragment of) stub data and the auth 882 * pad bytes (collectively the 'PDU Body'). 883 */ 884 saved_offset = nds->pdu_scan_offset; 885 nds->pdu_scan_offset = nds->pdu_body_offset + nds->pdu_body_size; 886 887 /* auth_length is all of the data after the sec_trailer */ 888 if (hdr->auth_length > 889 (nds->pdu_size - nds->pdu_scan_offset - SEC_TRAILER_SIZE)) { 890 nds->pdu_scan_offset = saved_offset; 891 return (NDR_DRC_FAULT_RECEIVED_MALFORMED); 892 } 893 894 rc = ndr_encode_decode_type(nds, &TYPEINFO(auth_verifier_co), 895 mxa); 896 897 /* 898 * Reset the scan_offset for call decode processing. 899 * If we were successful, remove the sec trailer and padding 900 * from size accounting. 901 */ 902 if (auth->auth_pad_len > nds->pdu_body_size) 903 rc = NDR_DRC_FAULT_RECEIVED_MALFORMED; 904 else if (rc == NDR_DRC_OK) { 905 auth_size = hdr->auth_length + SEC_TRAILER_SIZE + 906 auth->auth_pad_len; 907 908 /* 909 * After the authenticator has been decoded, 910 * pdu_scan_offset points to just after the auth token, 911 * which is the end of the fragment. 912 * 913 * If there's no data after the authenticator, then we 914 * just remove the authenticator from size accounting. 915 * Otherwise, need to memmove() all of that data back to after 916 * the stub data. The data we move starts at the beginning of 917 * the next fragment. 918 */ 919 if (nds->pdu_size > nds->pdu_scan_offset) { 920 uchar_t *next_frag_ptr = nds->pdu_base_addr + 921 nds->pdu_scan_offset; 922 923 memmove(next_frag_ptr - auth_size, next_frag_ptr, 924 nds->pdu_size - nds->pdu_scan_offset); 925 } 926 927 nds->pdu_size -= auth_size; 928 } 929 nds->pdu_scan_offset = saved_offset; 930 return (rc); 931 } 932