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