xref: /onnv-gate/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c (revision 5772:237ac22142fe)
1*5772Sas200622 /*
2*5772Sas200622  * CDDL HEADER START
3*5772Sas200622  *
4*5772Sas200622  * The contents of this file are subject to the terms of the
5*5772Sas200622  * Common Development and Distribution License (the "License").
6*5772Sas200622  * You may not use this file except in compliance with the License.
7*5772Sas200622  *
8*5772Sas200622  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5772Sas200622  * or http://www.opensolaris.org/os/licensing.
10*5772Sas200622  * See the License for the specific language governing permissions
11*5772Sas200622  * and limitations under the License.
12*5772Sas200622  *
13*5772Sas200622  * When distributing Covered Code, include this CDDL HEADER in each
14*5772Sas200622  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5772Sas200622  * If applicable, add the following below this CDDL HEADER, with the
16*5772Sas200622  * fields enclosed by brackets "[]" replaced with your own identifying
17*5772Sas200622  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5772Sas200622  *
19*5772Sas200622  * CDDL HEADER END
20*5772Sas200622  */
21*5772Sas200622 /*
22*5772Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*5772Sas200622  * Use is subject to license terms.
24*5772Sas200622  */
25*5772Sas200622 
26*5772Sas200622 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5772Sas200622 
28*5772Sas200622 
29*5772Sas200622 #include <synch.h>
30*5772Sas200622 #include <stdio.h>
31*5772Sas200622 #include <unistd.h>
32*5772Sas200622 #include <string.h>
33*5772Sas200622 #include <strings.h>
34*5772Sas200622 #include <assert.h>
35*5772Sas200622 
36*5772Sas200622 #include <smbsrv/libsmb.h>
37*5772Sas200622 #include <smbsrv/ndr.h>
38*5772Sas200622 #include <smbsrv/mlrpc.h>
39*5772Sas200622 #include <smbsrv/ntsid.h>
40*5772Sas200622 
41*5772Sas200622 
42*5772Sas200622 /*
43*5772Sas200622  * Global list of allocated handles.  Handles are used in various
44*5772Sas200622  * server-side RPC functions: typically, issued when a service is
45*5772Sas200622  * opened and obsoleted when it is closed.  Clients should treat
46*5772Sas200622  * handles as opaque data.
47*5772Sas200622  */
48*5772Sas200622 static ndr_handle_t *ndr_handle_list;
49*5772Sas200622 static mutex_t ndr_handle_lock;
50*5772Sas200622 
51*5772Sas200622 /*
52*5772Sas200622  * Table of registered services.
53*5772Sas200622  */
54*5772Sas200622 #define	NDL_MAX_SERVICES	32
55*5772Sas200622 static mlrpc_service_t *mlrpc_services[NDL_MAX_SERVICES];
56*5772Sas200622 
57*5772Sas200622 
58*5772Sas200622 struct mlrpc_stub_table *
59*5772Sas200622 mlrpc_find_stub_in_svc(mlrpc_service_t *msvc, int opnum)
60*5772Sas200622 {
61*5772Sas200622 	struct mlrpc_stub_table *ste;
62*5772Sas200622 
63*5772Sas200622 	for (ste = msvc->stub_table; ste->func; ste++) {
64*5772Sas200622 		if (ste->opnum == opnum)
65*5772Sas200622 			return (ste);
66*5772Sas200622 	}
67*5772Sas200622 
68*5772Sas200622 	return (NULL);
69*5772Sas200622 }
70*5772Sas200622 
71*5772Sas200622 mlrpc_service_t *
72*5772Sas200622 mlrpc_find_service_by_name(const char *name)
73*5772Sas200622 {
74*5772Sas200622 	mlrpc_service_t 	*msvc;
75*5772Sas200622 	int			i;
76*5772Sas200622 
77*5772Sas200622 	for (i = 0; i < NDL_MAX_SERVICES; i++) {
78*5772Sas200622 		if ((msvc = mlrpc_services[i]) == NULL)
79*5772Sas200622 			continue;
80*5772Sas200622 
81*5772Sas200622 		if (strcasecmp(name, msvc->name) != 0)
82*5772Sas200622 			continue;
83*5772Sas200622 
84*5772Sas200622 		mlndo_printf(0, 0, "%s %s", msvc->name, msvc->desc);
85*5772Sas200622 		return (msvc);
86*5772Sas200622 	}
87*5772Sas200622 
88*5772Sas200622 	return (NULL);
89*5772Sas200622 }
90*5772Sas200622 
91*5772Sas200622 mlrpc_service_t *
92*5772Sas200622 mlrpc_find_service_by_uuids(ndr_uuid_t *as_uuid, int as_vers,
93*5772Sas200622     ndr_uuid_t *ts_uuid, int ts_vers)
94*5772Sas200622 {
95*5772Sas200622 	mlrpc_service_t *msvc;
96*5772Sas200622 	char abstract_syntax[128];
97*5772Sas200622 	char transfer_syntax[128];
98*5772Sas200622 	int i;
99*5772Sas200622 
100*5772Sas200622 	if (as_uuid)
101*5772Sas200622 		mlrpc_uuid_to_str(as_uuid, abstract_syntax);
102*5772Sas200622 
103*5772Sas200622 	if (ts_uuid)
104*5772Sas200622 		mlrpc_uuid_to_str(ts_uuid, transfer_syntax);
105*5772Sas200622 
106*5772Sas200622 	for (i = 0; i < NDL_MAX_SERVICES; i++) {
107*5772Sas200622 		if ((msvc = mlrpc_services[i]) == NULL)
108*5772Sas200622 			continue;
109*5772Sas200622 
110*5772Sas200622 		if (as_uuid) {
111*5772Sas200622 			if (msvc->abstract_syntax_uuid == 0)
112*5772Sas200622 				continue;
113*5772Sas200622 
114*5772Sas200622 			if (msvc->abstract_syntax_version != as_vers)
115*5772Sas200622 				continue;
116*5772Sas200622 
117*5772Sas200622 			if (strcasecmp(abstract_syntax,
118*5772Sas200622 			    msvc->abstract_syntax_uuid))
119*5772Sas200622 				continue;
120*5772Sas200622 		}
121*5772Sas200622 
122*5772Sas200622 		if (ts_uuid) {
123*5772Sas200622 			if (msvc->transfer_syntax_uuid == 0)
124*5772Sas200622 				continue;
125*5772Sas200622 
126*5772Sas200622 			if (msvc->transfer_syntax_version != ts_vers)
127*5772Sas200622 				continue;
128*5772Sas200622 
129*5772Sas200622 			if (strcasecmp(transfer_syntax,
130*5772Sas200622 			    msvc->transfer_syntax_uuid))
131*5772Sas200622 				continue;
132*5772Sas200622 		}
133*5772Sas200622 
134*5772Sas200622 		mlndo_printf(0, 0, "%s %s", msvc->name, msvc->desc);
135*5772Sas200622 		return (msvc);
136*5772Sas200622 	}
137*5772Sas200622 
138*5772Sas200622 	return (NULL);
139*5772Sas200622 }
140*5772Sas200622 
141*5772Sas200622 /*
142*5772Sas200622  * Register a service.
143*5772Sas200622  *
144*5772Sas200622  * Returns:
145*5772Sas200622  *	0	Success
146*5772Sas200622  *	-1	Duplicate service
147*5772Sas200622  *	-2	Duplicate name
148*5772Sas200622  *	-3	Table overflow
149*5772Sas200622  */
150*5772Sas200622 int
151*5772Sas200622 mlrpc_register_service(mlrpc_service_t *msvc)
152*5772Sas200622 {
153*5772Sas200622 	mlrpc_service_t 	*p;
154*5772Sas200622 	int			free_slot = -1;
155*5772Sas200622 	int			i;
156*5772Sas200622 
157*5772Sas200622 	for (i = 0; i < NDL_MAX_SERVICES; i++) {
158*5772Sas200622 		if ((p = mlrpc_services[i]) == NULL) {
159*5772Sas200622 			if (free_slot < 0)
160*5772Sas200622 				free_slot = i;
161*5772Sas200622 			continue;
162*5772Sas200622 		}
163*5772Sas200622 
164*5772Sas200622 		if (p == msvc)
165*5772Sas200622 			return (-1);
166*5772Sas200622 
167*5772Sas200622 		if (strcasecmp(p->name, msvc->name) == 0)
168*5772Sas200622 			return (-2);
169*5772Sas200622 	}
170*5772Sas200622 
171*5772Sas200622 	if (free_slot < 0)
172*5772Sas200622 		return (-3);
173*5772Sas200622 
174*5772Sas200622 	mlrpc_services[free_slot] = msvc;
175*5772Sas200622 	return (0);
176*5772Sas200622 }
177*5772Sas200622 
178*5772Sas200622 void
179*5772Sas200622 mlrpc_unregister_service(mlrpc_service_t *msvc)
180*5772Sas200622 {
181*5772Sas200622 	int i;
182*5772Sas200622 
183*5772Sas200622 	for (i = 0; i < NDL_MAX_SERVICES; i++) {
184*5772Sas200622 		if (mlrpc_services[i] == msvc)
185*5772Sas200622 			mlrpc_services[i] = NULL;
186*5772Sas200622 	}
187*5772Sas200622 }
188*5772Sas200622 
189*5772Sas200622 int
190*5772Sas200622 mlrpc_list_services(char *buffer, int bufsize)
191*5772Sas200622 {
192*5772Sas200622 	mlrpc_service_t *msvc;
193*5772Sas200622 	smb_ctxbuf_t ctx;
194*5772Sas200622 	int i;
195*5772Sas200622 
196*5772Sas200622 	(void) smb_ctxbuf_init(&ctx, (uint8_t *)buffer, bufsize);
197*5772Sas200622 
198*5772Sas200622 	for (i = 0; i < NDL_MAX_SERVICES; i++) {
199*5772Sas200622 		if ((msvc = mlrpc_services[i]) != 0) {
200*5772Sas200622 			(void) smb_ctxbuf_printf(&ctx, "%-16s %s\n",
201*5772Sas200622 			    msvc->name, msvc->desc);
202*5772Sas200622 		}
203*5772Sas200622 	}
204*5772Sas200622 
205*5772Sas200622 	return (smb_ctxbuf_len(&ctx));
206*5772Sas200622 }
207*5772Sas200622 
208*5772Sas200622 /*
209*5772Sas200622  * Allocate a handle for use with the server-side RPC functions.
210*5772Sas200622  * The handle contains the machine SID and an incrementing counter,
211*5772Sas200622  * which should make each handle unique.
212*5772Sas200622  *
213*5772Sas200622  * An arbitrary caller context can be associated with the handle
214*5772Sas200622  * via data; it will not be dereferenced by the handle API.
215*5772Sas200622  *
216*5772Sas200622  * The uuid for the new handle is returned after it has been added
217*5772Sas200622  * to the global handle list.
218*5772Sas200622  */
219*5772Sas200622 ndr_hdid_t *
220*5772Sas200622 ndr_hdalloc(const ndr_xa_t *xa, const void *data)
221*5772Sas200622 {
222*5772Sas200622 	static ndr_hdid_t uuid;
223*5772Sas200622 	ndr_handle_t *hd;
224*5772Sas200622 	nt_sid_t *sid;
225*5772Sas200622 
226*5772Sas200622 	if ((hd = malloc(sizeof (ndr_handle_t))) == NULL)
227*5772Sas200622 		return (NULL);
228*5772Sas200622 
229*5772Sas200622 	if (uuid.data[1] == 0) {
230*5772Sas200622 		if ((sid = nt_domain_local_sid()) == NULL)
231*5772Sas200622 			return (NULL);
232*5772Sas200622 
233*5772Sas200622 		uuid.data[0] = 0;
234*5772Sas200622 		uuid.data[1] = 0;
235*5772Sas200622 		uuid.data[2] = sid->SubAuthority[1];
236*5772Sas200622 		uuid.data[3] = sid->SubAuthority[2];
237*5772Sas200622 		uuid.data[4] = sid->SubAuthority[3];
238*5772Sas200622 	}
239*5772Sas200622 
240*5772Sas200622 	++uuid.data[1];
241*5772Sas200622 
242*5772Sas200622 	bcopy(&uuid, &hd->nh_id, sizeof (ndr_hdid_t));
243*5772Sas200622 	hd->nh_fid = xa->fid;
244*5772Sas200622 	hd->nh_svc = xa->binding->service;
245*5772Sas200622 	hd->nh_data = (void *)data;
246*5772Sas200622 
247*5772Sas200622 	(void) mutex_lock(&ndr_handle_lock);
248*5772Sas200622 	hd->nh_next = ndr_handle_list;
249*5772Sas200622 	ndr_handle_list = hd;
250*5772Sas200622 	(void) mutex_unlock(&ndr_handle_lock);
251*5772Sas200622 
252*5772Sas200622 	return (&hd->nh_id);
253*5772Sas200622 }
254*5772Sas200622 
255*5772Sas200622 /*
256*5772Sas200622  * Remove a handle from the global list and free it.
257*5772Sas200622  */
258*5772Sas200622 void
259*5772Sas200622 ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id)
260*5772Sas200622 {
261*5772Sas200622 	mlrpc_service_t *svc = xa->binding->service;
262*5772Sas200622 	ndr_handle_t *hd;
263*5772Sas200622 	ndr_handle_t **pphd;
264*5772Sas200622 
265*5772Sas200622 	assert(id);
266*5772Sas200622 
267*5772Sas200622 	(void) mutex_lock(&ndr_handle_lock);
268*5772Sas200622 	pphd = &ndr_handle_list;
269*5772Sas200622 
270*5772Sas200622 	while (*pphd) {
271*5772Sas200622 		hd = *pphd;
272*5772Sas200622 
273*5772Sas200622 		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
274*5772Sas200622 			if (hd->nh_svc == svc) {
275*5772Sas200622 				*pphd = hd->nh_next;
276*5772Sas200622 				free(hd);
277*5772Sas200622 			}
278*5772Sas200622 			break;
279*5772Sas200622 		}
280*5772Sas200622 
281*5772Sas200622 		pphd = &(*pphd)->nh_next;
282*5772Sas200622 	}
283*5772Sas200622 
284*5772Sas200622 	(void) mutex_unlock(&ndr_handle_lock);
285*5772Sas200622 }
286*5772Sas200622 
287*5772Sas200622 /*
288*5772Sas200622  * Lookup a handle by id.  If the handle is in the list and it matches
289*5772Sas200622  * the specified service, a pointer to it is returned.  Otherwise a null
290*5772Sas200622  * pointer is returned.
291*5772Sas200622  */
292*5772Sas200622 ndr_handle_t *
293*5772Sas200622 ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id)
294*5772Sas200622 {
295*5772Sas200622 	mlrpc_service_t *svc = xa->binding->service;
296*5772Sas200622 	ndr_handle_t *hd;
297*5772Sas200622 
298*5772Sas200622 	assert(id);
299*5772Sas200622 	(void) mutex_lock(&ndr_handle_lock);
300*5772Sas200622 	hd = ndr_handle_list;
301*5772Sas200622 
302*5772Sas200622 	while (hd) {
303*5772Sas200622 		if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) {
304*5772Sas200622 			if (hd->nh_svc != svc)
305*5772Sas200622 				break;
306*5772Sas200622 			(void) mutex_unlock(&ndr_handle_lock);
307*5772Sas200622 			return (hd);
308*5772Sas200622 		}
309*5772Sas200622 
310*5772Sas200622 		hd = hd->nh_next;
311*5772Sas200622 	}
312*5772Sas200622 
313*5772Sas200622 	(void) mutex_unlock(&ndr_handle_lock);
314*5772Sas200622 	return (NULL);
315*5772Sas200622 }
316*5772Sas200622 
317*5772Sas200622 /*
318*5772Sas200622  * Called when a pipe is closed to release any associated handles.
319*5772Sas200622  */
320*5772Sas200622 void
321*5772Sas200622 ndr_hdclose(int fid)
322*5772Sas200622 {
323*5772Sas200622 	ndr_handle_t *hd;
324*5772Sas200622 	ndr_handle_t **pphd;
325*5772Sas200622 
326*5772Sas200622 	(void) mutex_lock(&ndr_handle_lock);
327*5772Sas200622 	pphd = &ndr_handle_list;
328*5772Sas200622 
329*5772Sas200622 	while (*pphd) {
330*5772Sas200622 		hd = *pphd;
331*5772Sas200622 
332*5772Sas200622 		if (hd->nh_fid == fid) {
333*5772Sas200622 			*pphd = hd->nh_next;
334*5772Sas200622 			free(hd);
335*5772Sas200622 			continue;
336*5772Sas200622 		}
337*5772Sas200622 
338*5772Sas200622 		pphd = &(*pphd)->nh_next;
339*5772Sas200622 	}
340*5772Sas200622 
341*5772Sas200622 	(void) mutex_unlock(&ndr_handle_lock);
342*5772Sas200622 }
343*5772Sas200622 
344*5772Sas200622 void
345*5772Sas200622 mlrpc_uuid_to_str(ndr_uuid_t *uuid, char *str)
346*5772Sas200622 {
347*5772Sas200622 	(void) sprintf(str, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
348*5772Sas200622 	    uuid->data1, uuid->data2, uuid->data3,
349*5772Sas200622 	    uuid->data4[0], uuid->data4[1],
350*5772Sas200622 	    uuid->data4[2], uuid->data4[3],
351*5772Sas200622 	    uuid->data4[4], uuid->data4[5],
352*5772Sas200622 	    uuid->data4[6], uuid->data4[7]);
353*5772Sas200622 }
354*5772Sas200622 
355*5772Sas200622 int
356*5772Sas200622 mlrpc_str_to_uuid(char *str, ndr_uuid_t *uuid)
357*5772Sas200622 {
358*5772Sas200622 	char 		*p = str;
359*5772Sas200622 	char 		*q;
360*5772Sas200622 	char		buf[4];
361*5772Sas200622 	int		i;
362*5772Sas200622 
363*5772Sas200622 	uuid->data1 = strtoul(p, &p, 16);
364*5772Sas200622 	if (*p != '-')
365*5772Sas200622 		return (0);
366*5772Sas200622 	p++;
367*5772Sas200622 
368*5772Sas200622 	uuid->data2 = strtol(p, &p, 16);
369*5772Sas200622 	if (*p != '-')
370*5772Sas200622 		return (0);
371*5772Sas200622 	p++;
372*5772Sas200622 
373*5772Sas200622 	uuid->data3 = strtol(p, &p, 16);
374*5772Sas200622 	if (*p != '-')
375*5772Sas200622 		return (0);
376*5772Sas200622 	p++;
377*5772Sas200622 
378*5772Sas200622 	for (i = 0; i < 8; i++) {
379*5772Sas200622 		if (p[0] == 0 || p[1] == 0)
380*5772Sas200622 			return (0);
381*5772Sas200622 
382*5772Sas200622 		buf[0] = *p++;
383*5772Sas200622 		buf[1] = *p++;
384*5772Sas200622 		buf[2] = 0;
385*5772Sas200622 		uuid->data4[i] = strtol(buf, &q, 16);
386*5772Sas200622 		if (*q != 0)
387*5772Sas200622 			return (0);
388*5772Sas200622 	}
389*5772Sas200622 
390*5772Sas200622 	if (*p != 0)
391*5772Sas200622 		return (0);
392*5772Sas200622 
393*5772Sas200622 	return (1);
394*5772Sas200622 }
395*5772Sas200622 
396*5772Sas200622 void
397*5772Sas200622 mlrpc_binding_pool_initialize(struct mlrpc_binding **headpp,
398*5772Sas200622     struct mlrpc_binding pool[], unsigned n_pool)
399*5772Sas200622 {
400*5772Sas200622 	struct mlrpc_binding	*head = NULL;
401*5772Sas200622 	int			ix;
402*5772Sas200622 
403*5772Sas200622 	for (ix = n_pool - 1; ix >= 0; ix--) {
404*5772Sas200622 		pool[ix].next = head;
405*5772Sas200622 		pool[ix].service = NULL;
406*5772Sas200622 		pool[ix].p_cont_id = 0xffff;
407*5772Sas200622 		pool[ix].instance_specific = 0;
408*5772Sas200622 		head = &pool[ix];
409*5772Sas200622 	}
410*5772Sas200622 
411*5772Sas200622 	*headpp = head;
412*5772Sas200622 }
413*5772Sas200622 
414*5772Sas200622 struct mlrpc_binding *
415*5772Sas200622 mlrpc_find_binding(struct mlrpc_xaction *mxa, mlrpc_p_context_id_t p_cont_id)
416*5772Sas200622 {
417*5772Sas200622 	struct mlrpc_binding *mbind;
418*5772Sas200622 
419*5772Sas200622 	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
420*5772Sas200622 		if (mbind->service != NULL &&
421*5772Sas200622 		    mbind->which_side == MLRPC_BIND_SIDE_SERVER &&
422*5772Sas200622 		    mbind->p_cont_id == p_cont_id)
423*5772Sas200622 			break;
424*5772Sas200622 	}
425*5772Sas200622 
426*5772Sas200622 	return (mbind);
427*5772Sas200622 }
428*5772Sas200622 
429*5772Sas200622 struct mlrpc_binding *
430*5772Sas200622 mlrpc_new_binding(struct mlrpc_xaction *mxa)
431*5772Sas200622 {
432*5772Sas200622 	struct mlrpc_binding *mbind;
433*5772Sas200622 
434*5772Sas200622 	for (mbind = mxa->binding_list; mbind; mbind = mbind->next) {
435*5772Sas200622 		if (mbind->service == NULL)
436*5772Sas200622 			break;
437*5772Sas200622 	}
438*5772Sas200622 
439*5772Sas200622 	return (mbind);
440*5772Sas200622 }
441