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