xref: /titanic_50/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h (revision 53a7b6b6763f5865522a76e5e887390a8f4777d7)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_LIBMLRPC_H
27 #define	_LIBMLRPC_H
28 
29 #include <sys/types.h>
30 #include <sys/uio.h>
31 #include <smbsrv/wintypes.h>
32 #include <smbsrv/ndr.h>
33 #include <smbsrv/smb_sid.h>
34 #include <smbsrv/smb_xdr.h>
35 
36 #ifdef	__cplusplus
37 extern "C" {
38 #endif
39 
40 /*
41  * An MSRPC compatible implementation of OSF DCE RPC.  DCE RPC is derived
42  * from the Apollo Network Computing Architecture (NCA) RPC implementation.
43  *
44  * CAE Specification (1997)
45  * DCE 1.1: Remote Procedure Call
46  * Document Number: C706
47  * The Open Group
48  * ogspecs@opengroup.org
49  *
50  * This implementation is based on the DCE Remote Procedure Call spec with
51  * enhancements to support Unicode strings.  The diagram below shows the
52  * DCE RPC layers compared against ONC SUN RPC.
53  *
54  *	NDR RPC Layers		Sun RPC Layers		Remark
55  *	+---------------+	+---------------+	+---------------+
56  *	+---------------+	+---------------+
57  *	| Application	|	| Application	|	The application
58  *	+---------------+	+---------------+
59  *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
60  *	| client/server |	| client/server |	work happens
61  *	| srvsvc.ndl	|	| *_svc.c *_clnt|
62  *	| srvsvc.c	|	|               |
63  *	+---------------+	+---------------+
64  *	| RPC Library	|	| RPC Library   |	Calls/Return
65  *	| ndr_*.c       |	|               |	Binding/PMAP
66  *	+---------------+	+---------------+
67  *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
68  *	| rpcpdu.ndl    |	|               |
69  *	+---------------+	+---------------+
70  *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
71  *	| NDR stubs	|	| XDR stubs     |	Composition
72  *	| *__ndr.c      |	| *_xdr.c       |
73  *	+---------------+	+---------------+
74  *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
75  *	+---------------+	+---------------+
76  *	| Packet Heaps  |	| Network Conn  |	DCERPC does not talk
77  *	| ndo_*.c       |	| clnt_{tcp,udp}|	directly to network.
78  *	+---------------+	+---------------+
79  *
80  * There are two major differences between the DCE RPC and ONC RPC:
81  *
82  * 1. NDR RPC only generates or processes packets from buffers.  Other
83  *    layers must take care of packet transmission and reception.
84  *    The packet heaps are managed through a simple interface provided
85  *    by the Network Data Representation (NDR) module called ndr_stream_t.
86  *    ndo_*.c modules implement the different flavors (operations) of
87  *    packet heaps.
88  *
89  *    ONC RPC communicates directly with the network.  You have to do
90  *    something special for the RPC packet to be placed in a buffer
91  *    rather than sent to the wire.
92  *
93  * 2. NDR RPC uses application provided heaps to support operations.
94  *    A heap is a single, monolithic chunk of memory that NDR RPC manages
95  *    as it allocates.  When the operation and its result are done, the
96  *    heap is disposed of as a single item.  The transaction, which
97  *    is the anchor of most operations, contains the necessary book-
98  *    keeping for the heap.
99  *
100  *    ONC RPC uses malloc() liberally throughout its run-time system.
101  *    To free results, ONC RPC supports an XDR_FREE operation that
102  *    traverses data structures freeing memory as it goes, whether
103  *    it was malloc'd or not.
104  */
105 
106 /*
107  * Dispatch Return Code (DRC)
108  *
109  *	0x8000	15:01	Set to indicate a fault, clear indicates status
110  *	0x7F00	08:07	Status/Fault specific
111  *	0x00FF	00:08	PTYPE_... of PDU, 0xFF for header
112  */
113 #define	NDR_DRC_OK				0x0000
114 #define	NDR_DRC_MASK_FAULT			0x8000
115 #define	NDR_DRC_MASK_SPECIFIER			0xFF00
116 #define	NDR_DRC_MASK_PTYPE			0x00FF
117 
118 /* Fake PTYPE DRC discriminators */
119 #define	NDR_DRC_PTYPE_RPCHDR(DRC)		((DRC) | 0x00FF)
120 #define	NDR_DRC_PTYPE_API(DRC)			((DRC) | 0x00AA)
121 
122 /* DRC Recognizers */
123 #define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
124 #define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
125 
126 /*
127  * (Un)Marshalling category specifiers
128  */
129 #define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
130 #define	NDR_DRC_RECEIVED			0x0200
131 #define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
132 #define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
133 #define	NDR_DRC_DECODED				0x0500
134 #define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
135 #define	NDR_DRC_ENCODED				0x0700
136 #define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
137 #define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
138 #define	NDR_DRC_SENT				0x0A00
139 #define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
140 
141 /*
142  * Resource category specifier
143  */
144 #define	NDR_DRC_FAULT_RESOURCE_1		0x9100
145 #define	NDR_DRC_FAULT_RESOURCE_2		0x9200
146 
147 /*
148  * Parameters. Usually #define'd with useful alias
149  */
150 #define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
151 #define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
152 #define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
153 #define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
154 #define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
155 #define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
156 #define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
157 #define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
158 
159 #define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
160 
161 /* RPCHDR */
162 #define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
163 #define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF /* PARAM_0_UNIMP */
164 
165 /* Request */
166 #define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
167 #define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
168 
169 /* Bind */
170 #define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
171 #define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
172 #define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
173 #define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
174 
175 /* API */
176 #define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
177 #define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
178 #define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
179 
180 struct ndr_xa;
181 struct ndr_client;
182 
183 typedef struct ndr_stub_table {
184 	int		(*func)(void *, struct ndr_xa *);
185 	unsigned short	opnum;
186 } ndr_stub_table_t;
187 
188 typedef struct ndr_service {
189 	char		*name;
190 	char		*desc;
191 	char		*endpoint;
192 	char		*sec_addr_port;
193 	char		*abstract_syntax_uuid;
194 	int		abstract_syntax_version;
195 	char		*transfer_syntax_uuid;
196 	int		transfer_syntax_version;
197 	unsigned	bind_instance_size;
198 	int		(*bind_req)();
199 	int		(*unbind_and_close)();
200 	int		(*call_stub)(struct ndr_xa *);
201 	ndr_typeinfo_t	*interface_ti;
202 	ndr_stub_table_t *stub_table;
203 } ndr_service_t;
204 
205 /*
206  * The list of bindings is anchored at a connection.  Nothing in the
207  * RPC mechanism allocates them.  Binding elements which have service==0
208  * indicate free elements.  When a connection is instantiated, at least
209  * one free binding entry should also be established.  Something like
210  * this should suffice for most (all) situations:
211  *
212  *	struct connection {
213  *		....
214  *		ndr_binding_t *binding_list_head;
215  *		ndr_binding_t binding_pool[N_BINDING_POOL];
216  *		....
217  *	};
218  *
219  *	init_connection(struct connection *conn) {
220  *		....
221  *		ndr_svc_binding_pool_init(&conn->binding_list_head,
222  *		    conn->binding_pool, N_BINDING_POOL);
223  */
224 typedef struct ndr_binding {
225 	struct ndr_binding 	*next;
226 	ndr_p_context_id_t	p_cont_id;
227 	unsigned char		which_side;
228 	struct ndr_client	*clnt;
229 	ndr_service_t		*service;
230 	void 			*instance_specific;
231 } ndr_binding_t;
232 
233 #define	NDR_BIND_SIDE_CLIENT	1
234 #define	NDR_BIND_SIDE_SERVER	2
235 
236 #define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
237 	((TYPE *) (BINDING)->instance_specific)
238 
239 /*
240  * The binding list space must be provided by the application library
241  * for use by the underlying RPC library.  We need at least two binding
242  * slots per connection.
243  */
244 #define	NDR_N_BINDING_POOL	2
245 
246 typedef struct ndr_pipe {
247 	int			np_fid;
248 	smb_opipe_context_t	np_ctx;
249 	char			*np_buf;
250 	struct uio		np_uio;
251 	iovec_t			np_iov;
252 	ndr_fraglist_t		np_frags;
253 	int			np_refcnt;
254 	uint16_t		np_max_xmit_frag;
255 	uint16_t		np_max_recv_frag;
256 	ndr_binding_t		*np_binding;
257 	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
258 } ndr_pipe_t;
259 
260 /*
261  * Number of bytes required to align SIZE on the next dword/4-byte
262  * boundary.
263  */
264 #define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
265 
266 /*
267  * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
268  * and conformant one-dimensional arrays. Characters can be single-byte
269  * or multi-byte as long as all characters conform to a fixed element size,
270  * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
271  * string is terminated by a null character of the appropriate element size.
272  *
273  * MSRPC strings should always be varying/conformant and not null terminated.
274  * This format uses the size_is, first_is and length_is attributes (CAE
275  * section 4.2.18).
276  *
277  *	typedef struct string {
278  *		DWORD size_is;
279  *		DWORD first_is;
280  *		DWORD length_is;
281  *		wchar_t string[ANY_SIZE_ARRAY];
282  *	} string_t;
283  *
284  * The size_is attribute is used to specify the number of data elements in
285  * each dimension of an array.
286  *
287  * The first_is attribute is used to define the lower bound for significant
288  * elements in each dimension of an array. For strings this is always 0.
289  *
290  * The length_is attribute is used to define the number of significant
291  * elements in each dimension of an array. For strings this is typically
292  * the same as size_is. Although it might be (size_is - 1) if the string
293  * is null terminated.
294  *
295  *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
296  * +---------+---------+---------+------+------+------+------+
297  * |size_is  |first_is |length_is| char | char | char | char |
298  * +---------+---------+---------+------+------+------+------+
299  *
300  * Unfortunately, not all MSRPC Unicode strings are null terminated, which
301  * means that the recipient has to manually null-terminate the string after
302  * it has been unmarshalled.  There may be a wide-char pad following a
303  * string, and it may sometimes contains zero, but it's not guaranteed.
304  *
305  * To deal with this, MSRPC sometimes uses an additional wrapper with two
306  * more fields, as shown below.
307  *	length: the array length in bytes excluding terminating null bytes
308  *	maxlen: the array length in bytes including null terminator bytes
309  *	LPTSTR: converted to a string_t by NDR
310  *
311  * typedef struct ms_string {
312  *		WORD length;
313  *		WORD maxlen;
314  *		LPTSTR str;
315  * } ms_string_t;
316  */
317 typedef struct ndr_mstring {
318 	uint16_t length;
319 	uint16_t allosize;
320 	LPTSTR str;
321 } ndr_mstring_t;
322 
323 /*
324  * A number of heap areas are used during marshalling and unmarshalling.
325  * Under some circumstances these areas can be discarded by the library
326  * code, i.e. on the server side before returning to the client and on
327  * completion of a client side bind.  In the case of a client side RPC
328  * call, these areas must be preserved after an RPC returns to give the
329  * caller time to take a copy of the data.  In this case the client must
330  * call ndr_clnt_free_heap to free the memory.
331  *
332  * The heap management data definition looks a bit like this:
333  *
334  * heap -> +---------------+     +------------+
335  *         | iovec[0].base | --> | data block |
336  *         | iovec[0].len  |     +------------+
337  *         +---------------+
338  *                ::
339  *                ::
340  * iov  -> +---------------+     +------------+
341  *         | iovec[n].base | --> | data block |
342  *         | iovec[n].len  |     +------------+
343  *         +---------------+     ^            ^
344  *                               |            |
345  *    next ----------------------+            |
346  *    top  -----------------------------------+
347  *
348  */
349 
350 /*
351  * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
352  * of the first heap block.
353  */
354 #define	NDR_HEAP_MAXIOV		384
355 #define	NDR_HEAP_BLKSZ		8192
356 
357 typedef struct ndr_heap {
358 	struct iovec iovec[NDR_HEAP_MAXIOV];
359 	struct iovec *iov;
360 	int iovcnt;
361 	char *top;
362 	char *next;
363 } ndr_heap_t;
364 
365 /*
366  * Alternate varying/conformant string definition
367  * - for non-null-terminated strings.
368  */
369 typedef struct ndr_vcs {
370 	/*
371 	 * size_is (actually a copy of length_is) will
372 	 * be inserted here by the marshalling library.
373 	 */
374 	uint32_t vc_first_is;
375 	uint32_t vc_length_is;
376 	uint16_t buffer[ANY_SIZE_ARRAY];
377 } ndr_vcs_t;
378 
379 typedef struct ndr_vcstr {
380 	uint16_t wclen;
381 	uint16_t wcsize;
382 	ndr_vcs_t *vcs;
383 } ndr_vcstr_t;
384 
385 typedef struct ndr_vcb {
386 	/*
387 	 * size_is (actually a copy of length_is) will
388 	 * be inserted here by the marshalling library.
389 	 */
390 	uint32_t vc_first_is;
391 	uint32_t vc_length_is;
392 	uint8_t buffer[ANY_SIZE_ARRAY];
393 } ndr_vcb_t;
394 
395 typedef struct ndr_vcbuf {
396 	uint16_t len;
397 	uint16_t size;
398 	ndr_vcb_t *vcb;
399 } ndr_vcbuf_t;
400 
401 ndr_heap_t *ndr_heap_create(void);
402 void ndr_heap_destroy(ndr_heap_t *);
403 void *ndr_heap_malloc(ndr_heap_t *, unsigned);
404 void *ndr_heap_strdup(ndr_heap_t *, const char *);
405 int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
406 void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
407 void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
408 smb_sid_t *ndr_heap_siddup(ndr_heap_t *, smb_sid_t *);
409 int ndr_heap_used(ndr_heap_t *);
410 int ndr_heap_avail(ndr_heap_t *);
411 
412 #define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
413 #define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
414 #define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
415 #define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
416 #define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
417 #define	NDR_SIDDUP(XA, S)	ndr_heap_siddup((XA)->heap, (S))
418 
419 typedef struct ndr_xa {
420 	int			fid;
421 	unsigned short		ptype;		/* high bits special */
422 	unsigned short		opnum;
423 	ndr_stream_t		recv_nds;
424 	ndr_hdr_t		recv_hdr;
425 	ndr_stream_t		send_nds;
426 	ndr_hdr_t		send_hdr;
427 	ndr_binding_t		*binding;	/* what we're using */
428 	ndr_binding_t		*binding_list;	/* from connection */
429 	ndr_heap_t		*heap;
430 	ndr_pipe_t		*pipe;
431 } ndr_xa_t;
432 
433 /*
434  * 20-byte opaque id used by various RPC services.
435  */
436 CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
437 
438 typedef struct ndr_client {
439 	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
440 	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
441 	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
442 	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
443 	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
444 	void (*xa_release)(struct ndr_client *);
445 
446 	int			fid;
447 	ndr_hdid_t		*handle;
448 	ndr_binding_t		*binding;
449 	ndr_binding_t		*binding_list;
450 	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
451 
452 	boolean_t		heap_preserved;
453 	ndr_heap_t		*heap;
454 	ndr_stream_t		*recv_nds;
455 	ndr_stream_t		*send_nds;
456 
457 	uint32_t		next_call_id;
458 	unsigned		next_p_cont_id;
459 } ndr_client_t;
460 
461 typedef struct ndr_handle {
462 	ndr_hdid_t		nh_id;
463 	struct ndr_handle	*nh_next;
464 	int			nh_fid;
465 	int			nh_remote_os;
466 	const ndr_service_t	*nh_svc;
467 	ndr_client_t		*nh_clnt;
468 	void *nh_data;
469 } ndr_handle_t;
470 
471 /* ndr_ops.c */
472 void nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
473 void nds_finalize(ndr_stream_t *, ndr_fraglist_t *);
474 void nds_destruct(ndr_stream_t *);
475 
476 /* ndr_client.c */
477 int ndr_clnt_bind(ndr_client_t *, const char *, ndr_binding_t **);
478 int ndr_clnt_call(ndr_binding_t *, int, void *);
479 void ndr_clnt_free_heap(ndr_client_t *);
480 
481 /* ndr_marshal.c */
482 int ndr_encode_decode_common(ndr_xa_t *, int, unsigned, ndr_typeinfo_t *,
483     void *);
484 int ndr_decode_call(ndr_xa_t *, void *);
485 int ndr_encode_return(ndr_xa_t *, void *);
486 int ndr_encode_call(ndr_xa_t *, void *);
487 int ndr_decode_return(ndr_xa_t *, void *);
488 int ndr_decode_pdu_hdr(ndr_xa_t *);
489 int ndr_encode_pdu_hdr(ndr_xa_t *);
490 void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
491 unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
492 unsigned ndr_alter_context_rsp_hdr_size(void);
493 
494 /* ndr_server.c */
495 int ndr_pipe_open(int, uint8_t *, uint32_t);
496 int ndr_pipe_close(int);
497 int ndr_pipe_read(int, uint8_t *, uint32_t *, uint32_t *);
498 int ndr_pipe_write(int, uint8_t *, uint32_t);
499 
500 int ndr_generic_call_stub(ndr_xa_t *);
501 
502 boolean_t ndr_is_admin(ndr_xa_t *);
503 boolean_t ndr_is_poweruser(ndr_xa_t *);
504 int32_t ndr_native_os(ndr_xa_t *);
505 
506 /* ndr_svc.c */
507 ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
508 ndr_service_t *ndr_svc_lookup_name(const char *);
509 ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
510 int ndr_svc_register(ndr_service_t *);
511 void ndr_svc_unregister(ndr_service_t *);
512 void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
513 ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
514 ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
515 
516 int ndr_uuid_parse(char *, ndr_uuid_t *);
517 void ndr_uuid_unparse(ndr_uuid_t *, char *);
518 
519 ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
520 void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
521 ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
522 void ndr_hdclose(int fid);
523 
524 ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
525 
526 #ifdef	__cplusplus
527 }
528 #endif
529 
530 #endif	/* _LIBMLRPC_H */
531