13299f39fSGordon Ross /* 23299f39fSGordon Ross * CDDL HEADER START 33299f39fSGordon Ross * 43299f39fSGordon Ross * The contents of this file are subject to the terms of the 53299f39fSGordon Ross * Common Development and Distribution License (the "License"). 63299f39fSGordon Ross * You may not use this file except in compliance with the License. 73299f39fSGordon Ross * 83299f39fSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93299f39fSGordon Ross * or http://www.opensolaris.org/os/licensing. 103299f39fSGordon Ross * See the License for the specific language governing permissions 113299f39fSGordon Ross * and limitations under the License. 123299f39fSGordon Ross * 133299f39fSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 143299f39fSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153299f39fSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 163299f39fSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 173299f39fSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 183299f39fSGordon Ross * 193299f39fSGordon Ross * CDDL HEADER END 203299f39fSGordon Ross */ 213299f39fSGordon Ross /* 223299f39fSGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23ce8560eeSMatt Barden * Copyright 2020 Tintri by DDN, Inc. All rights reserved. 24*0ccfe583SMatt Barden * Copyright 2023 RackTop Systems, Inc. 253299f39fSGordon Ross */ 263299f39fSGordon Ross 273299f39fSGordon Ross #ifndef _LIBMLRPC_H 283299f39fSGordon Ross #define _LIBMLRPC_H 293299f39fSGordon Ross 303299f39fSGordon Ross #include <sys/types.h> 313299f39fSGordon Ross #include <sys/uio.h> 323299f39fSGordon Ross 333299f39fSGordon Ross #include <smb/wintypes.h> 343299f39fSGordon Ross #include <libmlrpc/ndr.h> 353299f39fSGordon Ross 363299f39fSGordon Ross #ifdef __cplusplus 373299f39fSGordon Ross extern "C" { 383299f39fSGordon Ross #endif 393299f39fSGordon Ross 403299f39fSGordon Ross /* 413299f39fSGordon Ross * An MSRPC compatible implementation of OSF DCE RPC. DCE RPC is derived 423299f39fSGordon Ross * from the Apollo Network Computing Architecture (NCA) RPC implementation. 433299f39fSGordon Ross * 443299f39fSGordon Ross * CAE Specification (1997) 453299f39fSGordon Ross * DCE 1.1: Remote Procedure Call 463299f39fSGordon Ross * Document Number: C706 473299f39fSGordon Ross * The Open Group 483299f39fSGordon Ross * ogspecs@opengroup.org 493299f39fSGordon Ross * 503299f39fSGordon Ross * This implementation is based on the DCE Remote Procedure Call spec with 513299f39fSGordon Ross * enhancements to support Unicode strings. The diagram below shows the 523299f39fSGordon Ross * DCE RPC layers compared against ONC SUN RPC. 533299f39fSGordon Ross * 543299f39fSGordon Ross * NDR RPC Layers Sun RPC Layers Remark 553299f39fSGordon Ross * +---------------+ +---------------+ +---------------+ 563299f39fSGordon Ross * +---------------+ +---------------+ 573299f39fSGordon Ross * | Application | | Application | The application 583299f39fSGordon Ross * +---------------+ +---------------+ 593299f39fSGordon Ross * | Hand coded | | RPCGEN gen'd | Where the real 603299f39fSGordon Ross * | client/server | | client/server | work happens 613299f39fSGordon Ross * | srvsvc.ndl | | *_svc.c *_clnt| 623299f39fSGordon Ross * | srvsvc.c | | | 633299f39fSGordon Ross * +---------------+ +---------------+ 643299f39fSGordon Ross * | RPC Library | | RPC Library | Calls/Return 653299f39fSGordon Ross * | ndr_*.c | | | Binding/PMAP 663299f39fSGordon Ross * +---------------+ +---------------+ 673299f39fSGordon Ross * | RPC Protocol | | RPC Protocol | Headers, Auth, 683299f39fSGordon Ross * | rpcpdu.ndl | | | 693299f39fSGordon Ross * +---------------+ +---------------+ 703299f39fSGordon Ross * | IDL gen'd | | RPCGEN gen'd | Aggregate 713299f39fSGordon Ross * | NDR stubs | | XDR stubs | Composition 723299f39fSGordon Ross * | *__ndr.c | | *_xdr.c | 733299f39fSGordon Ross * +---------------+ +---------------+ 743299f39fSGordon Ross * | NDR Represen | | XDR Represen | Byte order, padding 753299f39fSGordon Ross * +---------------+ +---------------+ 763299f39fSGordon Ross * | Packet Heaps | | Network Conn | DCERPC does not talk 773299f39fSGordon Ross * | ndo_*.c | | clnt_{tcp,udp}| directly to network. 783299f39fSGordon Ross * +---------------+ +---------------+ 793299f39fSGordon Ross * 803299f39fSGordon Ross * There are two major differences between the DCE RPC and ONC RPC: 813299f39fSGordon Ross * 823299f39fSGordon Ross * 1. NDR RPC only generates or processes packets from buffers. Other 833299f39fSGordon Ross * layers must take care of packet transmission and reception. 843299f39fSGordon Ross * The packet heaps are managed through a simple interface provided 853299f39fSGordon Ross * by the Network Data Representation (NDR) module called ndr_stream_t. 863299f39fSGordon Ross * ndo_*.c modules implement the different flavors (operations) of 873299f39fSGordon Ross * packet heaps. 883299f39fSGordon Ross * 893299f39fSGordon Ross * ONC RPC communicates directly with the network. You have to do 903299f39fSGordon Ross * something special for the RPC packet to be placed in a buffer 913299f39fSGordon Ross * rather than sent to the wire. 923299f39fSGordon Ross * 933299f39fSGordon Ross * 2. NDR RPC uses application provided heaps to support operations. 943299f39fSGordon Ross * A heap is a single, monolithic chunk of memory that NDR RPC manages 953299f39fSGordon Ross * as it allocates. When the operation and its result are done, the 963299f39fSGordon Ross * heap is disposed of as a single item. The transaction, which 973299f39fSGordon Ross * is the anchor of most operations, contains the necessary book- 983299f39fSGordon Ross * keeping for the heap. 993299f39fSGordon Ross * 1003299f39fSGordon Ross * ONC RPC uses malloc() liberally throughout its run-time system. 1013299f39fSGordon Ross * To free results, ONC RPC supports an XDR_FREE operation that 1023299f39fSGordon Ross * traverses data structures freeing memory as it goes, whether 1033299f39fSGordon Ross * it was malloc'd or not. 1043299f39fSGordon Ross */ 1053299f39fSGordon Ross 1063299f39fSGordon Ross /* 1073299f39fSGordon Ross * Dispatch Return Code (DRC) 1083299f39fSGordon Ross * 1093299f39fSGordon Ross * 0x8000 15:01 Set to indicate a fault, clear indicates status 1103299f39fSGordon Ross * 0x7F00 08:07 Status/Fault specific 1113299f39fSGordon Ross * 0x00FF 00:08 PTYPE_... of PDU, 0xFF for header 1123299f39fSGordon Ross */ 1133299f39fSGordon Ross #define NDR_DRC_OK 0x0000 1143299f39fSGordon Ross #define NDR_DRC_MASK_FAULT 0x8000 1153299f39fSGordon Ross #define NDR_DRC_MASK_SPECIFIER 0xFF00 1163299f39fSGordon Ross #define NDR_DRC_MASK_PTYPE 0x00FF 1173299f39fSGordon Ross 1183299f39fSGordon Ross /* Fake PTYPE DRC discriminators */ 1193299f39fSGordon Ross #define NDR_DRC_PTYPE_RPCHDR(DRC) ((DRC) | 0x00FF) 1203299f39fSGordon Ross #define NDR_DRC_PTYPE_API(DRC) ((DRC) | 0x00AA) 121ce8560eeSMatt Barden #define NDR_DRC_PTYPE_SEC(DRC) ((DRC) | 0x00CC) 1223299f39fSGordon Ross 1233299f39fSGordon Ross /* DRC Recognizers */ 1243299f39fSGordon Ross #define NDR_DRC_IS_OK(DRC) (((DRC) & NDR_DRC_MASK_SPECIFIER) == 0) 1253299f39fSGordon Ross #define NDR_DRC_IS_FAULT(DRC) (((DRC) & NDR_DRC_MASK_FAULT) != 0) 1263299f39fSGordon Ross 1273299f39fSGordon Ross /* 1283299f39fSGordon Ross * (Un)Marshalling category specifiers 1293299f39fSGordon Ross */ 1303299f39fSGordon Ross #define NDR_DRC_FAULT_MODE_MISMATCH 0x8100 1313299f39fSGordon Ross #define NDR_DRC_RECEIVED 0x0200 1323299f39fSGordon Ross #define NDR_DRC_FAULT_RECEIVED_RUNT 0x8300 1333299f39fSGordon Ross #define NDR_DRC_FAULT_RECEIVED_MALFORMED 0x8400 1343299f39fSGordon Ross #define NDR_DRC_DECODED 0x0500 1353299f39fSGordon Ross #define NDR_DRC_FAULT_DECODE_FAILED 0x8600 1363299f39fSGordon Ross #define NDR_DRC_ENCODED 0x0700 1373299f39fSGordon Ross #define NDR_DRC_FAULT_ENCODE_FAILED 0x8800 1383299f39fSGordon Ross #define NDR_DRC_FAULT_ENCODE_TOO_BIG 0x8900 1393299f39fSGordon Ross #define NDR_DRC_SENT 0x0A00 1403299f39fSGordon Ross #define NDR_DRC_FAULT_SEND_FAILED 0x8B00 1413299f39fSGordon Ross 1423299f39fSGordon Ross /* 1433299f39fSGordon Ross * Resource category specifier 1443299f39fSGordon Ross */ 1453299f39fSGordon Ross #define NDR_DRC_FAULT_RESOURCE_1 0x9100 1463299f39fSGordon Ross #define NDR_DRC_FAULT_RESOURCE_2 0x9200 1473299f39fSGordon Ross 1483299f39fSGordon Ross /* 1493299f39fSGordon Ross * Parameters. Usually #define'd with useful alias 1503299f39fSGordon Ross */ 1513299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_0_INVALID 0xC000 1523299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED 0xD000 1533299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_1_INVALID 0xC100 1543299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED 0xD100 1553299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_2_INVALID 0xC200 1563299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED 0xD200 1573299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_3_INVALID 0xC300 1583299f39fSGordon Ross #define NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED 0xD300 159ce8560eeSMatt Barden #define NDR_DRC_FAULT_PARAM_4_INVALID 0xC400 160ce8560eeSMatt Barden #define NDR_DRC_FAULT_PARAM_4_UNIMPLEMENTED 0xD400 161ce8560eeSMatt Barden #define NDR_DRC_FAULT_PARAM_5_INVALID 0xC500 162ce8560eeSMatt Barden #define NDR_DRC_FAULT_PARAM_5_UNIMPLEMENTED 0xD500 1633299f39fSGordon Ross 1643299f39fSGordon Ross #define NDR_DRC_FAULT_OUT_OF_MEMORY 0xF000 1653299f39fSGordon Ross 1663299f39fSGordon Ross /* RPCHDR */ 1673299f39fSGordon Ross #define NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH 0x81FF 1683299f39fSGordon Ross #define NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT 0x83FF 1693299f39fSGordon Ross #define NDR_DRC_FAULT_RPCHDR_DECODE_FAILED 0x86FF 1703299f39fSGordon Ross #define NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID 0xC0FF /* PARAM_0_INVALID */ 1713299f39fSGordon Ross #define NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF /* PARAM_0_UNIMP */ 1723299f39fSGordon Ross 1733299f39fSGordon Ross /* Request */ 1743299f39fSGordon Ross #define NDR_DRC_FAULT_REQUEST_PCONT_INVALID 0xC000 /* PARAM_0_INVALID */ 1753299f39fSGordon Ross #define NDR_DRC_FAULT_REQUEST_OPNUM_INVALID 0xC100 /* PARAM_1_INVALID */ 1763299f39fSGordon Ross 1773299f39fSGordon Ross /* Bind */ 1783299f39fSGordon Ross #define NDR_DRC_BINDING_MADE 0x000B /* OK */ 1793299f39fSGordon Ross #define NDR_DRC_FAULT_BIND_PCONT_BUSY 0xC00B /* PARAM_0_INVALID */ 1803299f39fSGordon Ross #define NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE 0xC10B /* PARAM_1_INVALID */ 1813299f39fSGordon Ross #define NDR_DRC_FAULT_BIND_NO_SLOTS 0x910B /* RESOURCE_1 */ 1823299f39fSGordon Ross 1833299f39fSGordon Ross /* API */ 1843299f39fSGordon Ross #define NDR_DRC_FAULT_API_SERVICE_INVALID 0xC0AA /* PARAM_0_INVALID */ 1853299f39fSGordon Ross #define NDR_DRC_FAULT_API_BIND_NO_SLOTS 0x91AA /* RESOURCE_1 */ 1863299f39fSGordon Ross #define NDR_DRC_FAULT_API_OPNUM_INVALID 0xC1AA /* PARAM_1_INVALID */ 1873299f39fSGordon Ross 188ce8560eeSMatt Barden /* Secure RPC and SSPs */ 189ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED \ 190ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED) 191ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED \ 192ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED) 193ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_SSP_FAILED \ 194ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_RESOURCE_1) 195ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_ENCODE_TOO_BIG \ 196ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_ENCODE_TOO_BIG) 197ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID \ 198ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_2_INVALID) 199ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID \ 200ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_0_INVALID) 201ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID \ 202ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_1_INVALID) 203ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_OUT_OF_MEMORY \ 204ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_OUT_OF_MEMORY) 205ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_ENCODE_FAILED \ 206ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_ENCODE_FAILED) 207ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_META_INVALID \ 208ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_3_INVALID) 209ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_SEQNUM_INVALID \ 210ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_4_INVALID) 211ce8560eeSMatt Barden #define NDR_DRC_FAULT_SEC_SIG_INVALID \ 212ce8560eeSMatt Barden NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_5_INVALID) 213ce8560eeSMatt Barden 2143299f39fSGordon Ross struct ndr_xa; 2153299f39fSGordon Ross struct ndr_client; 2163299f39fSGordon Ross 2173299f39fSGordon Ross typedef struct ndr_stub_table { 2183299f39fSGordon Ross int (*func)(void *, struct ndr_xa *); 2193299f39fSGordon Ross unsigned short opnum; 2203299f39fSGordon Ross } ndr_stub_table_t; 2213299f39fSGordon Ross 2223299f39fSGordon Ross typedef struct ndr_service { 2233299f39fSGordon Ross char *name; 2243299f39fSGordon Ross char *desc; 2253299f39fSGordon Ross char *endpoint; 2263299f39fSGordon Ross char *sec_addr_port; 2273299f39fSGordon Ross char *abstract_syntax_uuid; 2283299f39fSGordon Ross int abstract_syntax_version; 2293299f39fSGordon Ross char *transfer_syntax_uuid; 2303299f39fSGordon Ross int transfer_syntax_version; 2313299f39fSGordon Ross unsigned bind_instance_size; 2323299f39fSGordon Ross int (*bind_req)(); 2333299f39fSGordon Ross int (*unbind_and_close)(); 2343299f39fSGordon Ross int (*call_stub)(struct ndr_xa *); 2353299f39fSGordon Ross ndr_typeinfo_t *interface_ti; 2363299f39fSGordon Ross ndr_stub_table_t *stub_table; 2373299f39fSGordon Ross } ndr_service_t; 2383299f39fSGordon Ross 2393299f39fSGordon Ross /* 2403299f39fSGordon Ross * The list of bindings is anchored at a connection. Nothing in the 2413299f39fSGordon Ross * RPC mechanism allocates them. Binding elements which have service==0 2423299f39fSGordon Ross * indicate free elements. When a connection is instantiated, at least 2433299f39fSGordon Ross * one free binding entry should also be established. Something like 2443299f39fSGordon Ross * this should suffice for most (all) situations: 2453299f39fSGordon Ross * 2463299f39fSGordon Ross * struct connection { 2473299f39fSGordon Ross * .... 2483299f39fSGordon Ross * ndr_binding_t *binding_list_head; 2493299f39fSGordon Ross * ndr_binding_t binding_pool[N_BINDING_POOL]; 2503299f39fSGordon Ross * .... 2513299f39fSGordon Ross * }; 2523299f39fSGordon Ross * 2533299f39fSGordon Ross * init_connection(struct connection *conn) { 2543299f39fSGordon Ross * .... 2553299f39fSGordon Ross * ndr_svc_binding_pool_init(&conn->binding_list_head, 2563299f39fSGordon Ross * conn->binding_pool, N_BINDING_POOL); 2573299f39fSGordon Ross */ 2583299f39fSGordon Ross typedef struct ndr_binding { 2593299f39fSGordon Ross struct ndr_binding *next; 2603299f39fSGordon Ross ndr_p_context_id_t p_cont_id; 2613299f39fSGordon Ross unsigned char which_side; 2623299f39fSGordon Ross struct ndr_client *clnt; 2633299f39fSGordon Ross ndr_service_t *service; 2643299f39fSGordon Ross void *instance_specific; 2653299f39fSGordon Ross } ndr_binding_t; 2663299f39fSGordon Ross 2673299f39fSGordon Ross #define NDR_BIND_SIDE_CLIENT 1 2683299f39fSGordon Ross #define NDR_BIND_SIDE_SERVER 2 2693299f39fSGordon Ross 2703299f39fSGordon Ross #define NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \ 2713299f39fSGordon Ross ((TYPE *) (BINDING)->instance_specific) 2723299f39fSGordon Ross 2733299f39fSGordon Ross /* 2743299f39fSGordon Ross * The binding list space must be provided by the application library 2753299f39fSGordon Ross * for use by the underlying RPC library. We need at least two binding 2763299f39fSGordon Ross * slots per connection. 2773299f39fSGordon Ross */ 2783299f39fSGordon Ross #define NDR_N_BINDING_POOL 2 2793299f39fSGordon Ross 2803299f39fSGordon Ross typedef struct ndr_pipe { 2813299f39fSGordon Ross void *np_listener; 2823299f39fSGordon Ross const char *np_endpoint; 2833299f39fSGordon Ross struct smb_netuserinfo *np_user; 2843299f39fSGordon Ross int (*np_send)(struct ndr_pipe *, void *, size_t); 2853299f39fSGordon Ross int (*np_recv)(struct ndr_pipe *, void *, size_t); 2863299f39fSGordon Ross int np_fid; 2873299f39fSGordon Ross uint16_t np_max_xmit_frag; 2883299f39fSGordon Ross uint16_t np_max_recv_frag; 2893299f39fSGordon Ross ndr_binding_t *np_binding; 2903299f39fSGordon Ross ndr_binding_t np_binding_pool[NDR_N_BINDING_POOL]; 2913299f39fSGordon Ross } ndr_pipe_t; 2923299f39fSGordon Ross 2933299f39fSGordon Ross /* 2943299f39fSGordon Ross * Number of bytes required to align SIZE on the next dword/4-byte 2953299f39fSGordon Ross * boundary. 2963299f39fSGordon Ross */ 2973299f39fSGordon Ross #define NDR_ALIGN4(SIZE) ((4 - (SIZE)) & 3); 2983299f39fSGordon Ross 2993299f39fSGordon Ross /* 3003299f39fSGordon Ross * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying 3013299f39fSGordon Ross * and conformant one-dimensional arrays. Characters can be single-byte 3023299f39fSGordon Ross * or multi-byte as long as all characters conform to a fixed element size, 3033299f39fSGordon Ross * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The 3043299f39fSGordon Ross * string is terminated by a null character of the appropriate element size. 3053299f39fSGordon Ross * 3063299f39fSGordon Ross * MSRPC strings should always be varying/conformant and not null terminated. 3073299f39fSGordon Ross * This format uses the size_is, first_is and length_is attributes (CAE 3083299f39fSGordon Ross * section 4.2.18). 3093299f39fSGordon Ross * 3103299f39fSGordon Ross * typedef struct string { 3113299f39fSGordon Ross * DWORD size_is; 3123299f39fSGordon Ross * DWORD first_is; 3133299f39fSGordon Ross * DWORD length_is; 3143299f39fSGordon Ross * wchar_t string[ANY_SIZE_ARRAY]; 3153299f39fSGordon Ross * } string_t; 3163299f39fSGordon Ross * 3173299f39fSGordon Ross * The size_is attribute is used to specify the number of data elements in 3183299f39fSGordon Ross * each dimension of an array. 3193299f39fSGordon Ross * 3203299f39fSGordon Ross * The first_is attribute is used to define the lower bound for significant 3213299f39fSGordon Ross * elements in each dimension of an array. For strings this is always 0. 3223299f39fSGordon Ross * 3233299f39fSGordon Ross * The length_is attribute is used to define the number of significant 3243299f39fSGordon Ross * elements in each dimension of an array. For strings this is typically 3253299f39fSGordon Ross * the same as size_is. Although it might be (size_is - 1) if the string 3263299f39fSGordon Ross * is null terminated. 3273299f39fSGordon Ross * 3283299f39fSGordon Ross * 4 bytes 4 bytes 4 bytes 2bytes 2bytes 2bytes 2bytes 3293299f39fSGordon Ross * +---------+---------+---------+------+------+------+------+ 3303299f39fSGordon Ross * |size_is |first_is |length_is| char | char | char | char | 3313299f39fSGordon Ross * +---------+---------+---------+------+------+------+------+ 3323299f39fSGordon Ross * 3333299f39fSGordon Ross * Unfortunately, not all MSRPC Unicode strings are null terminated, which 3343299f39fSGordon Ross * means that the recipient has to manually null-terminate the string after 3353299f39fSGordon Ross * it has been unmarshalled. There may be a wide-char pad following a 3363299f39fSGordon Ross * string, and it may sometimes contains zero, but it's not guaranteed. 3373299f39fSGordon Ross * 3383299f39fSGordon Ross * To deal with this, MSRPC sometimes uses an additional wrapper with two 3393299f39fSGordon Ross * more fields, as shown below. 3403299f39fSGordon Ross * length: the array length in bytes excluding terminating null bytes 3413299f39fSGordon Ross * maxlen: the array length in bytes including null terminator bytes 3423299f39fSGordon Ross * LPTSTR: converted to a string_t by NDR 3433299f39fSGordon Ross * 3443299f39fSGordon Ross * typedef struct ms_string { 3453299f39fSGordon Ross * WORD length; 3463299f39fSGordon Ross * WORD maxlen; 3473299f39fSGordon Ross * LPTSTR str; 3483299f39fSGordon Ross * } ms_string_t; 3493299f39fSGordon Ross */ 3503299f39fSGordon Ross typedef struct ndr_mstring { 3513299f39fSGordon Ross uint16_t length; 3523299f39fSGordon Ross uint16_t allosize; 3533299f39fSGordon Ross LPTSTR str; 3543299f39fSGordon Ross } ndr_mstring_t; 3553299f39fSGordon Ross 3563299f39fSGordon Ross /* 3573299f39fSGordon Ross * A number of heap areas are used during marshalling and unmarshalling. 3583299f39fSGordon Ross * Under some circumstances these areas can be discarded by the library 3593299f39fSGordon Ross * code, i.e. on the server side before returning to the client and on 3603299f39fSGordon Ross * completion of a client side bind. In the case of a client side RPC 3613299f39fSGordon Ross * call, these areas must be preserved after an RPC returns to give the 3623299f39fSGordon Ross * caller time to take a copy of the data. In this case the client must 3633299f39fSGordon Ross * call ndr_clnt_free_heap to free the memory. 3643299f39fSGordon Ross * 3653299f39fSGordon Ross * The heap management data definition looks a bit like this: 3663299f39fSGordon Ross * 3673299f39fSGordon Ross * heap -> +---------------+ +------------+ 3683299f39fSGordon Ross * | iovec[0].base | --> | data block | 3693299f39fSGordon Ross * | iovec[0].len | +------------+ 3703299f39fSGordon Ross * +---------------+ 3713299f39fSGordon Ross * :: 3723299f39fSGordon Ross * :: 3733299f39fSGordon Ross * iov -> +---------------+ +------------+ 3743299f39fSGordon Ross * | iovec[n].base | --> | data block | 3753299f39fSGordon Ross * | iovec[n].len | +------------+ 3763299f39fSGordon Ross * +---------------+ ^ ^ 3773299f39fSGordon Ross * | | 3783299f39fSGordon Ross * next ----------------------+ | 3793299f39fSGordon Ross * top -----------------------------------+ 3803299f39fSGordon Ross * 3813299f39fSGordon Ross */ 3823299f39fSGordon Ross 3833299f39fSGordon Ross /* 3843299f39fSGordon Ross * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes 3853299f39fSGordon Ross * of the first heap block. 3863299f39fSGordon Ross */ 3873299f39fSGordon Ross #define NDR_HEAP_MAXIOV 384 3883299f39fSGordon Ross #define NDR_HEAP_BLKSZ 8192 3893299f39fSGordon Ross 3903299f39fSGordon Ross typedef struct ndr_heap { 3913299f39fSGordon Ross struct iovec iovec[NDR_HEAP_MAXIOV]; 3923299f39fSGordon Ross struct iovec *iov; 3933299f39fSGordon Ross int iovcnt; 3943299f39fSGordon Ross char *top; 3953299f39fSGordon Ross char *next; 3963299f39fSGordon Ross } ndr_heap_t; 3973299f39fSGordon Ross 3983299f39fSGordon Ross /* 3993299f39fSGordon Ross * Alternate varying/conformant string definition 4003299f39fSGordon Ross * - for non-null-terminated strings. 4013299f39fSGordon Ross */ 4023299f39fSGordon Ross typedef struct ndr_vcs { 4033299f39fSGordon Ross /* 4043299f39fSGordon Ross * size_is (actually a copy of length_is) will 4053299f39fSGordon Ross * be inserted here by the marshalling library. 4063299f39fSGordon Ross */ 4073299f39fSGordon Ross uint32_t vc_first_is; 4083299f39fSGordon Ross uint32_t vc_length_is; 4093299f39fSGordon Ross uint16_t buffer[ANY_SIZE_ARRAY]; 4103299f39fSGordon Ross } ndr_vcs_t; 4113299f39fSGordon Ross 4123299f39fSGordon Ross typedef struct ndr_vcstr { 4133299f39fSGordon Ross uint16_t wclen; 4143299f39fSGordon Ross uint16_t wcsize; 4153299f39fSGordon Ross ndr_vcs_t *vcs; 4163299f39fSGordon Ross } ndr_vcstr_t; 4173299f39fSGordon Ross 4183299f39fSGordon Ross typedef struct ndr_vcb { 4193299f39fSGordon Ross /* 4203299f39fSGordon Ross * size_is (actually a copy of length_is) will 4213299f39fSGordon Ross * be inserted here by the marshalling library. 4223299f39fSGordon Ross */ 4233299f39fSGordon Ross uint32_t vc_first_is; 4243299f39fSGordon Ross uint32_t vc_length_is; 4253299f39fSGordon Ross uint8_t buffer[ANY_SIZE_ARRAY]; 4263299f39fSGordon Ross } ndr_vcb_t; 4273299f39fSGordon Ross 4283299f39fSGordon Ross typedef struct ndr_vcbuf { 4293299f39fSGordon Ross uint16_t len; 4303299f39fSGordon Ross uint16_t size; 4313299f39fSGordon Ross ndr_vcb_t *vcb; 4323299f39fSGordon Ross } ndr_vcbuf_t; 4333299f39fSGordon Ross 4343299f39fSGordon Ross ndr_heap_t *ndr_heap_create(void); 4353299f39fSGordon Ross void ndr_heap_destroy(ndr_heap_t *); 4363299f39fSGordon Ross void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t); 4373299f39fSGordon Ross void *ndr_heap_malloc(ndr_heap_t *, unsigned); 4383299f39fSGordon Ross void *ndr_heap_strdup(ndr_heap_t *, const char *); 4393299f39fSGordon Ross int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *); 4403299f39fSGordon Ross void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *); 4413299f39fSGordon Ross void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *); 4423299f39fSGordon Ross int ndr_heap_used(ndr_heap_t *); 4433299f39fSGordon Ross int ndr_heap_avail(ndr_heap_t *); 4443299f39fSGordon Ross 4453299f39fSGordon Ross #define NDR_MALLOC(XA, SZ) ndr_heap_malloc((XA)->heap, SZ) 4463299f39fSGordon Ross #define NDR_NEW(XA, T) ndr_heap_malloc((XA)->heap, sizeof (T)) 4473299f39fSGordon Ross #define NDR_NEWN(XA, T, N) ndr_heap_malloc((XA)->heap, sizeof (T)*(N)) 4483299f39fSGordon Ross #define NDR_STRDUP(XA, S) ndr_heap_strdup((XA)->heap, (S)) 4493299f39fSGordon Ross #define NDR_MSTRING(XA, S, OUT) ndr_heap_mstring((XA)->heap, (S), (OUT)) 4503299f39fSGordon Ross #define NDR_SIDDUP(XA, S) ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S)) 4513299f39fSGordon Ross 4523299f39fSGordon Ross typedef struct ndr_xa { 4533299f39fSGordon Ross unsigned short ptype; /* high bits special */ 4543299f39fSGordon Ross unsigned short opnum; 4553299f39fSGordon Ross ndr_stream_t recv_nds; 4563299f39fSGordon Ross ndr_hdr_t recv_hdr; 457ce8560eeSMatt Barden ndr_sec_t recv_auth; 4583299f39fSGordon Ross ndr_stream_t send_nds; 4593299f39fSGordon Ross ndr_hdr_t send_hdr; 460ce8560eeSMatt Barden ndr_sec_t send_auth; 4613299f39fSGordon Ross ndr_binding_t *binding; /* what we're using */ 4623299f39fSGordon Ross ndr_binding_t *binding_list; /* from connection */ 4633299f39fSGordon Ross ndr_heap_t *heap; 4643299f39fSGordon Ross ndr_pipe_t *pipe; 4653299f39fSGordon Ross } ndr_xa_t; 4663299f39fSGordon Ross 467ce8560eeSMatt Barden typedef struct ndr_auth_ops { 468ce8560eeSMatt Barden int (*nao_init)(void *, ndr_xa_t *); 469ce8560eeSMatt Barden int (*nao_recv)(void *, ndr_xa_t *); 470ce8560eeSMatt Barden int (*nao_sign)(void *, ndr_xa_t *); 471ce8560eeSMatt Barden int (*nao_verify)(void *, ndr_xa_t *, boolean_t); 472*0ccfe583SMatt Barden int (*nao_encrypt)(void *, ndr_xa_t *); 473*0ccfe583SMatt Barden int (*nao_decrypt)(void *, ndr_xa_t *, boolean_t); 474ce8560eeSMatt Barden } ndr_auth_ops_t; 475ce8560eeSMatt Barden 476ce8560eeSMatt Barden /* 477ce8560eeSMatt Barden * A client provides this structure during bind to indicate 478ce8560eeSMatt Barden * that the RPC runtime should use "Secure RPC" (RPC-level auth). 479ce8560eeSMatt Barden * 480ce8560eeSMatt Barden * Currently, only NETLOGON uses this, and only NETLOGON-based 481ce8560eeSMatt Barden * Integrity protection is supported. 482ce8560eeSMatt Barden */ 483ce8560eeSMatt Barden typedef struct ndr_auth_ctx { 484ce8560eeSMatt Barden ndr_auth_ops_t auth_ops; 485ce8560eeSMatt Barden void *auth_ctx; /* SSP-specific context */ 486ce8560eeSMatt Barden uint32_t auth_context_id; 487ce8560eeSMatt Barden uint8_t auth_type; 488ce8560eeSMatt Barden uint8_t auth_level; 489ce8560eeSMatt Barden boolean_t auth_verify_resp; 490ce8560eeSMatt Barden } ndr_auth_ctx_t; 491ce8560eeSMatt Barden 4923299f39fSGordon Ross /* 4933299f39fSGordon Ross * 20-byte opaque id used by various RPC services. 4943299f39fSGordon Ross */ 4953299f39fSGordon Ross CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t; 4963299f39fSGordon Ross 4973299f39fSGordon Ross typedef struct ndr_client { 4983299f39fSGordon Ross /* transport stuff (xa_* members) */ 4993299f39fSGordon Ross int (*xa_init)(struct ndr_client *, ndr_xa_t *); 5003299f39fSGordon Ross int (*xa_exchange)(struct ndr_client *, ndr_xa_t *); 5013299f39fSGordon Ross int (*xa_read)(struct ndr_client *, ndr_xa_t *); 5023299f39fSGordon Ross void (*xa_preserve)(struct ndr_client *, ndr_xa_t *); 5033299f39fSGordon Ross void (*xa_destruct)(struct ndr_client *, ndr_xa_t *); 5043299f39fSGordon Ross void (*xa_release)(struct ndr_client *); 5053299f39fSGordon Ross void *xa_private; 5063299f39fSGordon Ross int xa_fd; 5073299f39fSGordon Ross 5083299f39fSGordon Ross ndr_hdid_t *handle; 5093299f39fSGordon Ross ndr_binding_t *binding; 5103299f39fSGordon Ross ndr_binding_t *binding_list; 5113299f39fSGordon Ross ndr_binding_t binding_pool[NDR_N_BINDING_POOL]; 5123299f39fSGordon Ross 5133299f39fSGordon Ross boolean_t nonull; 5143299f39fSGordon Ross boolean_t heap_preserved; 5153299f39fSGordon Ross ndr_heap_t *heap; 5163299f39fSGordon Ross ndr_stream_t *recv_nds; 5173299f39fSGordon Ross ndr_stream_t *send_nds; 5183299f39fSGordon Ross 5193299f39fSGordon Ross uint32_t next_call_id; 5203299f39fSGordon Ross unsigned next_p_cont_id; 521ce8560eeSMatt Barden 522ce8560eeSMatt Barden ndr_auth_ctx_t auth_ctx; 5233299f39fSGordon Ross } ndr_client_t; 5243299f39fSGordon Ross 5253299f39fSGordon Ross typedef struct ndr_handle { 5263299f39fSGordon Ross ndr_hdid_t nh_id; 5273299f39fSGordon Ross struct ndr_handle *nh_next; 5283299f39fSGordon Ross ndr_pipe_t *nh_pipe; 5293299f39fSGordon Ross const ndr_service_t *nh_svc; 5303299f39fSGordon Ross ndr_client_t *nh_clnt; 5313299f39fSGordon Ross void *nh_data; 5323299f39fSGordon Ross void (*nh_data_free)(void *); 5333299f39fSGordon Ross } ndr_handle_t; 5343299f39fSGordon Ross 5353299f39fSGordon Ross #define NDR_PDU_SIZE_HINT_DEFAULT (16*1024) 5363299f39fSGordon Ross #define NDR_BUF_MAGIC 0x4E425546 /* NBUF */ 5373299f39fSGordon Ross 5383299f39fSGordon Ross typedef struct ndr_buf { 5393299f39fSGordon Ross uint32_t nb_magic; 5403299f39fSGordon Ross ndr_stream_t nb_nds; 5413299f39fSGordon Ross ndr_heap_t *nb_heap; 5423299f39fSGordon Ross ndr_typeinfo_t *nb_ti; 5433299f39fSGordon Ross } ndr_buf_t; 5443299f39fSGordon Ross 5453299f39fSGordon Ross /* ndr_ops.c */ 5463299f39fSGordon Ross int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *); 5473299f39fSGordon Ross void nds_destruct(ndr_stream_t *); 5483299f39fSGordon Ross void nds_show_state(ndr_stream_t *); 5493299f39fSGordon Ross 5503299f39fSGordon Ross /* ndr_client.c */ 5513299f39fSGordon Ross int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **); 5523299f39fSGordon Ross int ndr_clnt_call(ndr_binding_t *, int, void *); 5533299f39fSGordon Ross void ndr_clnt_free_heap(ndr_client_t *); 5543299f39fSGordon Ross 5553299f39fSGordon Ross /* ndr_marshal.c */ 5563299f39fSGordon Ross ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *); 5573299f39fSGordon Ross void ndr_buf_fini(ndr_buf_t *); 5583299f39fSGordon Ross int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t, 5593299f39fSGordon Ross void *); 5603299f39fSGordon Ross int ndr_decode_call(ndr_xa_t *, void *); 5613299f39fSGordon Ross int ndr_encode_return(ndr_xa_t *, void *); 5623299f39fSGordon Ross int ndr_encode_call(ndr_xa_t *, void *); 5633299f39fSGordon Ross int ndr_decode_return(ndr_xa_t *, void *); 5643299f39fSGordon Ross int ndr_decode_pdu_hdr(ndr_xa_t *); 5653299f39fSGordon Ross int ndr_encode_pdu_hdr(ndr_xa_t *); 5663299f39fSGordon Ross void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *); 5673299f39fSGordon Ross void ndr_remove_frag_hdr(ndr_stream_t *); 5683299f39fSGordon Ross void ndr_show_hdr(ndr_common_header_t *); 5693299f39fSGordon Ross unsigned ndr_bind_ack_hdr_size(ndr_xa_t *); 5703299f39fSGordon Ross unsigned ndr_alter_context_rsp_hdr_size(void); 571ce8560eeSMatt Barden int ndr_decode_pdu_auth(ndr_xa_t *); 572ce8560eeSMatt Barden int ndr_encode_pdu_auth(ndr_xa_t *); 573ce8560eeSMatt Barden void ndr_show_auth(ndr_sec_t *); 574ce8560eeSMatt Barden 575ce8560eeSMatt Barden /* 576ce8560eeSMatt Barden * MS-RPCE "Secure RPC" (RPC-level auth). 577ce8560eeSMatt Barden * These call the functions in ndr_auth_ops_t, which should be 578ce8560eeSMatt Barden * GSSAPI (or equivalent) calls. 579ce8560eeSMatt Barden */ 580ce8560eeSMatt Barden int ndr_add_sec_context(ndr_auth_ctx_t *, ndr_xa_t *); 581ce8560eeSMatt Barden int ndr_recv_sec_context(ndr_auth_ctx_t *, ndr_xa_t *); 582ce8560eeSMatt Barden int ndr_add_auth(ndr_auth_ctx_t *, ndr_xa_t *); 583ce8560eeSMatt Barden int ndr_check_auth(ndr_auth_ctx_t *, ndr_xa_t *); 5843299f39fSGordon Ross 5853299f39fSGordon Ross /* ndr_server.c */ 5863299f39fSGordon Ross void ndr_pipe_worker(ndr_pipe_t *); 5873299f39fSGordon Ross 5883299f39fSGordon Ross int ndr_generic_call_stub(ndr_xa_t *); 5893299f39fSGordon Ross 5903299f39fSGordon Ross /* ndr_svc.c */ 5913299f39fSGordon Ross ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int); 5923299f39fSGordon Ross ndr_service_t *ndr_svc_lookup_name(const char *); 5933299f39fSGordon Ross ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int); 5943299f39fSGordon Ross int ndr_svc_register(ndr_service_t *); 5953299f39fSGordon Ross void ndr_svc_unregister(ndr_service_t *); 5963299f39fSGordon Ross void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int); 5973299f39fSGordon Ross ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t); 5983299f39fSGordon Ross ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *); 5993299f39fSGordon Ross 6003299f39fSGordon Ross int ndr_uuid_parse(char *, ndr_uuid_t *); 6013299f39fSGordon Ross void ndr_uuid_unparse(ndr_uuid_t *, char *); 6023299f39fSGordon Ross 6033299f39fSGordon Ross ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *); 6043299f39fSGordon Ross void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *); 6053299f39fSGordon Ross ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *); 6063299f39fSGordon Ross void ndr_hdclose(ndr_pipe_t *); 6073299f39fSGordon Ross 6083299f39fSGordon Ross ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *); 6093299f39fSGordon Ross 6103299f39fSGordon Ross /* 6113299f39fSGordon Ross * An ndr_client_t is created while binding a client connection to hold 6123299f39fSGordon Ross * the context for calls made using that connection. 6133299f39fSGordon Ross * 6143299f39fSGordon Ross * Handles are RPC call specific and we use an inheritance mechanism to 6153299f39fSGordon Ross * ensure that each handle has a pointer to the client_t. When the top 6163299f39fSGordon Ross * level (bind) handle is released, we close the connection. 6173299f39fSGordon Ross * 6183299f39fSGordon Ross * There are some places in libmlsvc where the code assumes that the 619ce8560eeSMatt Barden * handle member is first in this struct. Careful! 620ce8560eeSMatt Barden * 621ce8560eeSMatt Barden * Note that this entire structure is bzero()'d once the ndr_client_t 622ce8560eeSMatt Barden * has been created. 6233299f39fSGordon Ross */ 6243299f39fSGordon Ross typedef struct mlrpc_handle { 6253299f39fSGordon Ross ndr_hdid_t handle; /* keep first */ 6263299f39fSGordon Ross ndr_client_t *clnt; 6273299f39fSGordon Ross } mlrpc_handle_t; 6283299f39fSGordon Ross 6293299f39fSGordon Ross int mlrpc_clh_create(mlrpc_handle_t *, void *); 630ce8560eeSMatt Barden uint32_t mlrpc_clh_set_auth(mlrpc_handle_t *, ndr_auth_ctx_t *); 6313299f39fSGordon Ross uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *); 6323299f39fSGordon Ross void mlrpc_clh_unbind(mlrpc_handle_t *); 6333299f39fSGordon Ross void *mlrpc_clh_free(mlrpc_handle_t *); 6343299f39fSGordon Ross 6353299f39fSGordon Ross int ndr_rpc_call(mlrpc_handle_t *, int, void *); 6363299f39fSGordon Ross int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t); 6373299f39fSGordon Ross void *ndr_rpc_malloc(mlrpc_handle_t *, size_t); 6383299f39fSGordon Ross ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *); 6393299f39fSGordon Ross void ndr_rpc_release(mlrpc_handle_t *); 6403299f39fSGordon Ross void ndr_rpc_set_nonull(mlrpc_handle_t *); 6413299f39fSGordon Ross 6423299f39fSGordon Ross boolean_t ndr_is_null_handle(mlrpc_handle_t *); 6433299f39fSGordon Ross boolean_t ndr_is_bind_handle(mlrpc_handle_t *); 6443299f39fSGordon Ross void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *); 6453299f39fSGordon Ross 6463299f39fSGordon Ross #ifdef __cplusplus 6473299f39fSGordon Ross } 6483299f39fSGordon Ross #endif 6493299f39fSGordon Ross 6503299f39fSGordon Ross #endif /* _LIBMLRPC_H */ 651