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