xref: /titanic_50/usr/src/common/smbsrv/smb_token.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1*da6c28aaSamw /*
2*da6c28aaSamw  * CDDL HEADER START
3*da6c28aaSamw  *
4*da6c28aaSamw  * The contents of this file are subject to the terms of the
5*da6c28aaSamw  * Common Development and Distribution License (the "License").
6*da6c28aaSamw  * You may not use this file except in compliance with the License.
7*da6c28aaSamw  *
8*da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10*da6c28aaSamw  * See the License for the specific language governing permissions
11*da6c28aaSamw  * and limitations under the License.
12*da6c28aaSamw  *
13*da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14*da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16*da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17*da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da6c28aaSamw  *
19*da6c28aaSamw  * CDDL HEADER END
20*da6c28aaSamw  */
21*da6c28aaSamw /*
22*da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*da6c28aaSamw  * Use is subject to license terms.
24*da6c28aaSamw  */
25*da6c28aaSamw 
26*da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*da6c28aaSamw 
28*da6c28aaSamw 
29*da6c28aaSamw /*
30*da6c28aaSamw  * NT Token library (kernel/user)
31*da6c28aaSamw  */
32*da6c28aaSamw 
33*da6c28aaSamw #ifdef _KERNEL
34*da6c28aaSamw #include <sys/types.h>
35*da6c28aaSamw #include <sys/ddi.h>
36*da6c28aaSamw #include <sys/sunddi.h>
37*da6c28aaSamw #include <sys/ksynch.h>
38*da6c28aaSamw #include <sys/cmn_err.h>
39*da6c28aaSamw #include <sys/time.h>
40*da6c28aaSamw #include <sys/kmem.h>
41*da6c28aaSamw #else /* _KERNEL */
42*da6c28aaSamw #include <stdlib.h>
43*da6c28aaSamw #include <strings.h>
44*da6c28aaSamw #include <thread.h>
45*da6c28aaSamw #include <synch.h>
46*da6c28aaSamw #include <syslog.h>
47*da6c28aaSamw #include <time.h>
48*da6c28aaSamw #include <arpa/inet.h>
49*da6c28aaSamw #include <sys/varargs.h>
50*da6c28aaSamw #include <smbsrv/alloc.h>
51*da6c28aaSamw #endif /* _KERNEL */
52*da6c28aaSamw 
53*da6c28aaSamw #include <sys/socket.h>
54*da6c28aaSamw #include <netinet/in.h>
55*da6c28aaSamw 
56*da6c28aaSamw #include <smbsrv/alloc.h>
57*da6c28aaSamw #include <smbsrv/string.h>
58*da6c28aaSamw #include <smbsrv/smbinfo.h>
59*da6c28aaSamw #include <smbsrv/smb_token.h>
60*da6c28aaSamw #include <smbsrv/smb_xdr.h>
61*da6c28aaSamw 
62*da6c28aaSamw #ifndef _KERNEL
63*da6c28aaSamw #include <assert.h>
64*da6c28aaSamw #define	ASSERT assert
65*da6c28aaSamw void (*smb_token_logfunc)(int, const char *, ...) = syslog;
66*da6c28aaSamw int smb_token_errlog = LOG_ERR;
67*da6c28aaSamw int smb_token_infolog = LOG_INFO;
68*da6c28aaSamw #else /* _KERNEL */
69*da6c28aaSamw void (*smb_token_logfunc)(int, const char *, ...) = cmn_err;
70*da6c28aaSamw int smb_token_errlog = CE_WARN;
71*da6c28aaSamw int smb_token_infolog = CE_NOTE;
72*da6c28aaSamw #endif /* _KERNEL */
73*da6c28aaSamw 
74*da6c28aaSamw int smb_token_debug = 0;
75*da6c28aaSamw 
76*da6c28aaSamw #ifdef _KERNEL
77*da6c28aaSamw extern char *inet_ntop(int, const void *, char *, int);
78*da6c28aaSamw #endif /* _KERNEL */
79*da6c28aaSamw 
80*da6c28aaSamw /*
81*da6c28aaSamw  * Returns -1 on error. Otherwise, returns 0.
82*da6c28aaSamw  */
83*da6c28aaSamw int
84*da6c28aaSamw smb_token_tobuf(smb_dr_user_ctx_t *usr, char *buf, int len)
85*da6c28aaSamw {
86*da6c28aaSamw 	char ipaddr_buf[INET_ADDRSTRLEN];
87*da6c28aaSamw 
88*da6c28aaSamw 	if (!usr) {
89*da6c28aaSamw 		(void) strcpy(buf, "N/A");
90*da6c28aaSamw 		return (-1);
91*da6c28aaSamw 	}
92*da6c28aaSamw 
93*da6c28aaSamw 	(void) inet_ntop(AF_INET, (char *)&usr->du_ipaddr, ipaddr_buf,
94*da6c28aaSamw 	    sizeof (ipaddr_buf));
95*da6c28aaSamw 	(void) snprintf(buf, len, "%s\\%s %s (%s)",
96*da6c28aaSamw 	    usr->du_domain ? usr->du_domain : "",
97*da6c28aaSamw 	    usr->du_account ? usr->du_account : "",
98*da6c28aaSamw 	    usr->du_workstation ? usr->du_workstation : "",
99*da6c28aaSamw 	    ipaddr_buf);
100*da6c28aaSamw 
101*da6c28aaSamw 	return (0);
102*da6c28aaSamw }
103*da6c28aaSamw 
104*da6c28aaSamw /*PRINTFLIKE3*/
105*da6c28aaSamw void
106*da6c28aaSamw smb_token_log(int level, smb_dr_user_ctx_t *usr, char *fmt, ...)
107*da6c28aaSamw {
108*da6c28aaSamw 	va_list ap;
109*da6c28aaSamw 	char *msg;
110*da6c28aaSamw 	int len;
111*da6c28aaSamw 	char tokenbuf[NTTOKEN_BASIC_INFO_MAXLEN];
112*da6c28aaSamw 
113*da6c28aaSamw 	msg = MEM_MALLOC("nttoken", 1024);
114*da6c28aaSamw 	if (!msg) {
115*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog, "smb_token_log: "
116*da6c28aaSamw 		    "resource shortage");
117*da6c28aaSamw 		return;
118*da6c28aaSamw 	}
119*da6c28aaSamw 
120*da6c28aaSamw 	if (usr)
121*da6c28aaSamw 		(void) smb_token_tobuf(usr, tokenbuf, sizeof (tokenbuf));
122*da6c28aaSamw 	else
123*da6c28aaSamw 		(void) strcpy(tokenbuf, "UNKNOWN");
124*da6c28aaSamw 
125*da6c28aaSamw 	va_start(ap, fmt);
126*da6c28aaSamw 	(void) snprintf(msg, 1024, "Token[%s]: ", tokenbuf);
127*da6c28aaSamw 	len = strlen(msg);
128*da6c28aaSamw 	(void) vsnprintf(msg + len, 1024 - len, fmt, ap);
129*da6c28aaSamw 	va_end(ap);
130*da6c28aaSamw #ifdef _KERNEL
131*da6c28aaSamw 	cmn_err(level, "%s", msg);
132*da6c28aaSamw #else
133*da6c28aaSamw 	syslog(level, "%s", msg);
134*da6c28aaSamw #endif /* _KERNEL */
135*da6c28aaSamw 
136*da6c28aaSamw 	MEM_FREE("nttoken", msg);
137*da6c28aaSamw }
138*da6c28aaSamw 
139*da6c28aaSamw #ifndef _KERNEL
140*da6c28aaSamw /*
141*da6c28aaSamw  * smb_token_print
142*da6c28aaSamw  *
143*da6c28aaSamw  * Diagnostic routine to write the contents of a token to the log.
144*da6c28aaSamw  */
145*da6c28aaSamw void
146*da6c28aaSamw smb_token_print(smb_token_t *token)
147*da6c28aaSamw {
148*da6c28aaSamw 	smb_win_grps_t *w_grps;
149*da6c28aaSamw 	smb_posix_grps_t *x_grps;
150*da6c28aaSamw 	smb_sid_attrs_t *grp;
151*da6c28aaSamw 	char sidstr[128];
152*da6c28aaSamw 	int i;
153*da6c28aaSamw 
154*da6c28aaSamw 	if (token == NULL)
155*da6c28aaSamw 		return;
156*da6c28aaSamw 
157*da6c28aaSamw 	smb_token_logfunc(smb_token_infolog, "Token for %s\\%s",
158*da6c28aaSamw 	    (token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-",
159*da6c28aaSamw 	    (token->tkn_account_name) ? token->tkn_account_name : "-NULL-");
160*da6c28aaSamw 
161*da6c28aaSamw 	smb_token_logfunc(smb_token_infolog, "   User->Attr: %d",
162*da6c28aaSamw 	    token->tkn_user->i_sidattr.attrs);
163*da6c28aaSamw 	nt_sid_format2((nt_sid_t *)token->tkn_user->i_sidattr.sid, sidstr);
164*da6c28aaSamw 	smb_token_logfunc(smb_token_infolog, "   User->Sid: %s (id=%u)",
165*da6c28aaSamw 	    sidstr, token->tkn_user->i_id);
166*da6c28aaSamw 
167*da6c28aaSamw 	nt_sid_format2((nt_sid_t *)token->tkn_owner->i_sidattr.sid, sidstr);
168*da6c28aaSamw 	smb_token_logfunc(smb_token_infolog, "   Ownr->Sid: %s (id=%u)",
169*da6c28aaSamw 	    sidstr, token->tkn_owner->i_id);
170*da6c28aaSamw 
171*da6c28aaSamw 	nt_sid_format2((nt_sid_t *)token->tkn_primary_grp->i_sidattr.sid,
172*da6c28aaSamw 	    sidstr);
173*da6c28aaSamw 	smb_token_logfunc(smb_token_infolog, "   PGrp->Sid: %s (id=%u)",
174*da6c28aaSamw 	    sidstr, token->tkn_primary_grp->i_id);
175*da6c28aaSamw 
176*da6c28aaSamw 	w_grps = token->tkn_win_grps;
177*da6c28aaSamw 	if (w_grps) {
178*da6c28aaSamw 		smb_token_logfunc(smb_token_infolog, "   Windows groups: %d",
179*da6c28aaSamw 		    w_grps->wg_count);
180*da6c28aaSamw 
181*da6c28aaSamw 		for (i = 0; i < w_grps->wg_count; ++i) {
182*da6c28aaSamw 			grp = &w_grps->wg_groups[i].i_sidattr;
183*da6c28aaSamw 			smb_token_logfunc(smb_token_infolog,
184*da6c28aaSamw 			    "    Grp[%d].Attr:%d", i, grp->attrs);
185*da6c28aaSamw 			if (w_grps->wg_groups[i].i_sidattr.sid) {
186*da6c28aaSamw 				nt_sid_format2((nt_sid_t *)grp->sid, sidstr);
187*da6c28aaSamw 				smb_token_logfunc(smb_token_infolog,
188*da6c28aaSamw 				    "    Grp[%d].Sid: %s (id=%u)", i, sidstr,
189*da6c28aaSamw 				    w_grps->wg_groups[i].i_id);
190*da6c28aaSamw 			}
191*da6c28aaSamw 		}
192*da6c28aaSamw 	}
193*da6c28aaSamw 	else
194*da6c28aaSamw 		smb_token_logfunc(smb_token_infolog, "   No Windows groups");
195*da6c28aaSamw 
196*da6c28aaSamw 	x_grps = token->tkn_posix_grps;
197*da6c28aaSamw 	if (x_grps) {
198*da6c28aaSamw 		smb_token_logfunc(smb_token_infolog, "   Solaris groups: %d",
199*da6c28aaSamw 		    x_grps->pg_ngrps);
200*da6c28aaSamw 		for (i = 0; i < x_grps->pg_ngrps; i++)
201*da6c28aaSamw 			smb_token_logfunc(smb_token_infolog, "    %u",
202*da6c28aaSamw 			    x_grps->pg_grps[i]);
203*da6c28aaSamw 	}
204*da6c28aaSamw 	else
205*da6c28aaSamw 		smb_token_logfunc(smb_token_infolog, "   No Solaris groups");
206*da6c28aaSamw 
207*da6c28aaSamw 	if (token->tkn_privileges)
208*da6c28aaSamw 		smb_privset_log(token->tkn_privileges);
209*da6c28aaSamw 	else
210*da6c28aaSamw 		smb_token_logfunc(smb_token_infolog, "   No privileges");
211*da6c28aaSamw }
212*da6c28aaSamw #endif /* _KERNEL */
213*da6c28aaSamw 
214*da6c28aaSamw /*
215*da6c28aaSamw  * smb_token_query_privilege
216*da6c28aaSamw  *
217*da6c28aaSamw  * Find out if the specified privilege is enable in the given
218*da6c28aaSamw  * access token.
219*da6c28aaSamw  */
220*da6c28aaSamw int
221*da6c28aaSamw smb_token_query_privilege(smb_token_t *token, int priv_id)
222*da6c28aaSamw {
223*da6c28aaSamw 	smb_privset_t *privset;
224*da6c28aaSamw 	int i;
225*da6c28aaSamw 
226*da6c28aaSamw 	if ((token == NULL) || (token->tkn_privileges == NULL))
227*da6c28aaSamw 		return (0);
228*da6c28aaSamw 
229*da6c28aaSamw 	privset = token->tkn_privileges;
230*da6c28aaSamw 	for (i = 0; privset->priv_cnt; i++) {
231*da6c28aaSamw 		if (privset->priv[i].luid.lo_part == priv_id) {
232*da6c28aaSamw 			if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED)
233*da6c28aaSamw 				return (1);
234*da6c28aaSamw 			else
235*da6c28aaSamw 				return (0);
236*da6c28aaSamw 		}
237*da6c28aaSamw 	}
238*da6c28aaSamw 
239*da6c28aaSamw 	return (0);
240*da6c28aaSamw }
241*da6c28aaSamw 
242*da6c28aaSamw #ifndef _KERNEL
243*da6c28aaSamw /*
244*da6c28aaSamw  * smb_token_mkselfrel
245*da6c28aaSamw  *
246*da6c28aaSamw  * encode: structure -> flat buffer (buffer size)
247*da6c28aaSamw  * Pre-condition: obj is non-null.
248*da6c28aaSamw  */
249*da6c28aaSamw uint8_t *
250*da6c28aaSamw smb_token_mkselfrel(smb_token_t *obj, uint32_t *len)
251*da6c28aaSamw {
252*da6c28aaSamw 	uint8_t *buf;
253*da6c28aaSamw 	XDR xdrs;
254*da6c28aaSamw 
255*da6c28aaSamw 	if (!obj) {
256*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog,
257*da6c28aaSamw 		    "smb_token_mkselfrel: invalid parameter");
258*da6c28aaSamw 		return (NULL);
259*da6c28aaSamw 	}
260*da6c28aaSamw 
261*da6c28aaSamw 	*len = xdr_sizeof(xdr_smb_token_t, obj);
262*da6c28aaSamw 	buf = (uint8_t *)malloc(*len);
263*da6c28aaSamw 	if (!buf) {
264*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog,
265*da6c28aaSamw 		    "smb_token_mkselfrel: resource shortage");
266*da6c28aaSamw 		return (NULL);
267*da6c28aaSamw 	}
268*da6c28aaSamw 
269*da6c28aaSamw 	xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE);
270*da6c28aaSamw 
271*da6c28aaSamw 	if (!xdr_smb_token_t(&xdrs, obj)) {
272*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog,
273*da6c28aaSamw 		    "smb_token_mkselfrel: XDR encode error");
274*da6c28aaSamw 		*len = 0;
275*da6c28aaSamw 		free(buf);
276*da6c28aaSamw 		buf = NULL;
277*da6c28aaSamw 	}
278*da6c28aaSamw 
279*da6c28aaSamw 	xdr_destroy(&xdrs);
280*da6c28aaSamw 	return (buf);
281*da6c28aaSamw }
282*da6c28aaSamw 
283*da6c28aaSamw /*
284*da6c28aaSamw  * netr_client_mkabsolute
285*da6c28aaSamw  *
286*da6c28aaSamw  * decode: flat buffer -> structure
287*da6c28aaSamw  */
288*da6c28aaSamw netr_client_t *
289*da6c28aaSamw netr_client_mkabsolute(uint8_t *buf, uint32_t len)
290*da6c28aaSamw {
291*da6c28aaSamw 	netr_client_t *obj;
292*da6c28aaSamw 	XDR xdrs;
293*da6c28aaSamw 
294*da6c28aaSamw 	xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE);
295*da6c28aaSamw 	obj = (netr_client_t *)malloc(sizeof (netr_client_t));
296*da6c28aaSamw 	if (!obj) {
297*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog, "netr_client_mkabsolute: "
298*da6c28aaSamw 		    "resource shortage");
299*da6c28aaSamw 		xdr_destroy(&xdrs);
300*da6c28aaSamw 		return (NULL);
301*da6c28aaSamw 	}
302*da6c28aaSamw 
303*da6c28aaSamw 	bzero(obj, sizeof (netr_client_t));
304*da6c28aaSamw 	if (!xdr_netr_client_t(&xdrs, obj)) {
305*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog, "netr_client_mkabsolute: "
306*da6c28aaSamw 		    "XDR decode error");
307*da6c28aaSamw 		free(obj);
308*da6c28aaSamw 		obj = NULL;
309*da6c28aaSamw 	}
310*da6c28aaSamw 
311*da6c28aaSamw 	xdr_destroy(&xdrs);
312*da6c28aaSamw 	return (obj);
313*da6c28aaSamw }
314*da6c28aaSamw #else /* _KERNEL */
315*da6c28aaSamw /*
316*da6c28aaSamw  * smb_token_mkabsolute
317*da6c28aaSamw  *
318*da6c28aaSamw  * decode: flat buffer -> structure
319*da6c28aaSamw  */
320*da6c28aaSamw smb_token_t *
321*da6c28aaSamw smb_token_mkabsolute(uint8_t *buf, uint32_t len)
322*da6c28aaSamw {
323*da6c28aaSamw 	smb_token_t *obj;
324*da6c28aaSamw 	XDR xdrs;
325*da6c28aaSamw 
326*da6c28aaSamw 	xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE);
327*da6c28aaSamw 	obj = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
328*da6c28aaSamw 
329*da6c28aaSamw 	if (!xdr_smb_token_t(&xdrs, obj)) {
330*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog, "smb_token_mkabsolute: XDR "
331*da6c28aaSamw 		    "decode error");
332*da6c28aaSamw 		kmem_free(obj, sizeof (smb_token_t));
333*da6c28aaSamw 		obj = NULL;
334*da6c28aaSamw 	}
335*da6c28aaSamw 
336*da6c28aaSamw 	xdr_destroy(&xdrs);
337*da6c28aaSamw 	return (obj);
338*da6c28aaSamw }
339*da6c28aaSamw 
340*da6c28aaSamw /*
341*da6c28aaSamw  * netr_client_mkselfrel
342*da6c28aaSamw  *
343*da6c28aaSamw  * encode: structure -> flat buffer (buffer size)
344*da6c28aaSamw  * Pre-condition: obj is non-null.
345*da6c28aaSamw  */
346*da6c28aaSamw uint8_t *
347*da6c28aaSamw netr_client_mkselfrel(netr_client_t *obj, uint32_t *len)
348*da6c28aaSamw {
349*da6c28aaSamw 	uint8_t *buf;
350*da6c28aaSamw 	XDR xdrs;
351*da6c28aaSamw 
352*da6c28aaSamw 	*len = xdr_sizeof(xdr_netr_client_t, obj);
353*da6c28aaSamw 	buf = kmem_alloc(*len, KM_SLEEP);
354*da6c28aaSamw 
355*da6c28aaSamw 	xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE);
356*da6c28aaSamw 
357*da6c28aaSamw 	if (!xdr_netr_client_t(&xdrs, obj)) {
358*da6c28aaSamw 		smb_token_logfunc(smb_token_errlog, "netr_client_mkselfrel: "
359*da6c28aaSamw 		    "XDR encode error");
360*da6c28aaSamw 		kmem_free(buf, *len);
361*da6c28aaSamw 		*len = 0;
362*da6c28aaSamw 		buf = NULL;
363*da6c28aaSamw 	}
364*da6c28aaSamw 
365*da6c28aaSamw 	xdr_destroy(&xdrs);
366*da6c28aaSamw 	return (buf);
367*da6c28aaSamw }
368*da6c28aaSamw 
369*da6c28aaSamw void
370*da6c28aaSamw smb_token_free(smb_token_t *token)
371*da6c28aaSamw {
372*da6c28aaSamw 	if (!token)
373*da6c28aaSamw 		return;
374*da6c28aaSamw 
375*da6c28aaSamw 	/*
376*da6c28aaSamw 	 * deallocate any pointer field of an access token object
377*da6c28aaSamw 	 * using xdr_free since they are created by the XDR decode
378*da6c28aaSamw 	 * operation.
379*da6c28aaSamw 	 */
380*da6c28aaSamw 	xdr_free(xdr_smb_token_t, (char *)token);
381*da6c28aaSamw 	kmem_free(token, sizeof (smb_token_t));
382*da6c28aaSamw }
383*da6c28aaSamw #endif /* _KERNEL */
384