xref: /illumos-gate/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c (revision 257873cfc1dd3337766407f80397db60a56f2f5a)
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 /*
27  * Security database interface.
28  */
29 #include <unistd.h>
30 #include <strings.h>
31 #include <pwd.h>
32 #include <grp.h>
33 #include <time.h>
34 #include <syslog.h>
35 #include <assert.h>
36 
37 #include <smbsrv/libsmb.h>
38 #include <smbsrv/libmlsvc.h>
39 
40 #include <smbsrv/smbinfo.h>
41 #include <smbsrv/smb_token.h>
42 #include <smbsrv/lsalib.h>
43 
44 extern uint32_t netlogon_logon(netr_client_t *clnt, smb_userinfo_t *uinfo);
45 static uint32_t smb_logon_domain(netr_client_t *clnt, smb_userinfo_t *uinfo);
46 static uint32_t smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo);
47 static uint32_t smb_logon_none(netr_client_t *clnt, smb_userinfo_t *uinfo);
48 
49 static uint32_t smb_setup_luinfo(smb_userinfo_t *, netr_client_t *, uid_t);
50 
51 static int smb_token_is_member(smb_token_t *token, smb_sid_t *sid);
52 static int smb_token_is_valid(smb_token_t *token);
53 static smb_win_grps_t *smb_token_create_wingrps(smb_userinfo_t *user_info);
54 
55 static smb_posix_grps_t *smb_token_create_pxgrps(uid_t uid);
56 
57 /* Consolidation private function from Network Repository */
58 extern int _getgroupsbymember(const char *, gid_t[], int, int);
59 
60 static idmap_stat
61 smb_token_idmap(smb_token_t *token, smb_idmap_batch_t *sib)
62 {
63 	idmap_stat stat;
64 	smb_idmap_t *sim;
65 	smb_id_t *id;
66 	int i;
67 
68 	if (!token || !sib)
69 		return (IDMAP_ERR_ARG);
70 
71 	sim = sib->sib_maps;
72 
73 	if (token->tkn_flags & SMB_ATF_ANON) {
74 		token->tkn_user->i_id = UID_NOBODY;
75 		token->tkn_owner->i_id = UID_NOBODY;
76 	} else {
77 		/* User SID */
78 		id = token->tkn_user;
79 		sim->sim_id = &id->i_id;
80 		stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
81 		    id->i_sidattr.sid, SMB_IDMAP_USER);
82 
83 		if (stat != IDMAP_SUCCESS)
84 			return (stat);
85 
86 		/* Owner SID */
87 		id = token->tkn_owner;
88 		sim->sim_id = &id->i_id;
89 		stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
90 		    id->i_sidattr.sid, SMB_IDMAP_USER);
91 
92 		if (stat != IDMAP_SUCCESS)
93 			return (stat);
94 	}
95 
96 	/* Primary Group SID */
97 	id = token->tkn_primary_grp;
98 	sim->sim_id = &id->i_id;
99 	stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
100 	    id->i_sidattr.sid, SMB_IDMAP_GROUP);
101 
102 	if (stat != IDMAP_SUCCESS)
103 		return (stat);
104 
105 	/* Other Windows Group SIDs */
106 	for (i = 0; i < token->tkn_win_grps->wg_count; i++, sim++) {
107 		id = &token->tkn_win_grps->wg_groups[i];
108 		sim->sim_id = &id->i_id;
109 		stat = smb_idmap_batch_getid(sib->sib_idmaph, sim,
110 		    id->i_sidattr.sid, SMB_IDMAP_GROUP);
111 
112 		if (stat != IDMAP_SUCCESS)
113 			break;
114 	}
115 
116 	return (stat);
117 }
118 
119 /*
120  * smb_token_sids2ids
121  *
122  * This will map all the SIDs of the access token to UIDs/GIDs.
123  *
124  * Returns 0 upon success.  Otherwise, returns -1.
125  */
126 static int
127 smb_token_sids2ids(smb_token_t *token)
128 {
129 	idmap_stat stat;
130 	int nmaps, retries = 0;
131 	smb_idmap_batch_t sib;
132 
133 	/*
134 	 * Number of idmap lookups: user SID, owner SID, primary group SID,
135 	 * and all Windows group SIDs
136 	 */
137 	if (token->tkn_flags & SMB_ATF_ANON)
138 		/*
139 		 * Don't include user and owner SID, they're Anonymous
140 		 */
141 		nmaps = 1;
142 	else
143 		nmaps = 3;
144 
145 	nmaps += token->tkn_win_grps->wg_count;
146 
147 	do {
148 		stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);
149 		if (stat != IDMAP_SUCCESS)
150 			return (-1);
151 
152 		stat = smb_token_idmap(token, &sib);
153 		if (stat != IDMAP_SUCCESS) {
154 			smb_idmap_batch_destroy(&sib);
155 			return (-1);
156 		}
157 
158 		stat = smb_idmap_batch_getmappings(&sib);
159 		smb_idmap_batch_destroy(&sib);
160 		if (stat == IDMAP_ERR_RPC_HANDLE)
161 			if (smb_idmap_restart() < 0)
162 				break;
163 	} while (stat == IDMAP_ERR_RPC_HANDLE && retries++ < 3);
164 
165 	return (stat == IDMAP_SUCCESS ? 0 : -1);
166 }
167 
168 /*
169  * smb_token_create_pxgrps
170  *
171  * Setup the POSIX group membership of the access token if the given UID is
172  * a POSIX UID (non-ephemeral). Both the user's primary group and
173  * supplementary groups will be added to the POSIX group array of the access
174  * token.
175  */
176 static smb_posix_grps_t *
177 smb_token_create_pxgrps(uid_t uid)
178 {
179 	struct passwd *pwd;
180 	smb_posix_grps_t *pgrps;
181 	int ngroups_max, num;
182 	gid_t *gids;
183 
184 	if ((ngroups_max = sysconf(_SC_NGROUPS_MAX)) < 0) {
185 		syslog(LOG_ERR, "smb_logon: failed to get _SC_NGROUPS_MAX");
186 		return (NULL);
187 	}
188 
189 	pwd = getpwuid(uid);
190 	if (pwd == NULL) {
191 		pgrps = malloc(sizeof (smb_posix_grps_t));
192 		if (pgrps == NULL)
193 			return (NULL);
194 
195 		pgrps->pg_ngrps = 0;
196 		return (pgrps);
197 	}
198 
199 	if (pwd->pw_name == NULL) {
200 		pgrps = malloc(sizeof (smb_posix_grps_t));
201 		if (pgrps == NULL)
202 			return (NULL);
203 
204 		pgrps->pg_ngrps = 1;
205 		pgrps->pg_grps[0] = pwd->pw_gid;
206 		return (pgrps);
207 	}
208 
209 	gids = (gid_t *)malloc(ngroups_max * sizeof (gid_t));
210 	if (gids == NULL) {
211 		return (NULL);
212 	}
213 	bzero(gids, ngroups_max * sizeof (gid_t));
214 
215 	gids[0] = pwd->pw_gid;
216 
217 	/*
218 	 * Setup the groups starting at index 1 (the last arg)
219 	 * of gids array.
220 	 */
221 	num = _getgroupsbymember(pwd->pw_name, gids, ngroups_max, 1);
222 
223 	if (num == -1) {
224 		syslog(LOG_ERR, "smb_logon: unable "
225 		    "to get user's supplementary groups");
226 		num = 1;
227 	}
228 
229 	pgrps = (smb_posix_grps_t *)malloc(SMB_POSIX_GRPS_SIZE(num));
230 	if (pgrps) {
231 		pgrps->pg_ngrps = num;
232 		bcopy(gids, pgrps->pg_grps, num * sizeof (gid_t));
233 	}
234 
235 	free(gids);
236 	return (pgrps);
237 }
238 
239 /*
240  * smb_token_destroy
241  *
242  * Release all of the memory associated with a token structure. Ensure
243  * that the token has been unlinked before calling.
244  */
245 void
246 smb_token_destroy(smb_token_t *token)
247 {
248 	smb_win_grps_t *groups;
249 	int i;
250 
251 	if (token == NULL)
252 		return;
253 
254 	if (token->tkn_user) {
255 		free(token->tkn_user->i_sidattr.sid);
256 		free(token->tkn_user);
257 	}
258 
259 	if (token->tkn_owner) {
260 		free(token->tkn_owner->i_sidattr.sid);
261 		free(token->tkn_owner);
262 	}
263 
264 	if (token->tkn_primary_grp) {
265 		free(token->tkn_primary_grp->i_sidattr.sid);
266 		free(token->tkn_primary_grp);
267 	}
268 
269 	if ((groups = token->tkn_win_grps) != NULL) {
270 		for (i = 0; i < groups->wg_count; ++i)
271 			free(groups->wg_groups[i].i_sidattr.sid);
272 		free(groups);
273 	}
274 
275 	smb_privset_free(token->tkn_privileges);
276 
277 	free(token->tkn_posix_grps);
278 	free(token->tkn_account_name);
279 	free(token->tkn_domain_name);
280 	free(token->tkn_session_key);
281 
282 	free(token);
283 }
284 
285 static smb_id_t *
286 smb_token_create_id(smb_sid_t *sid)
287 {
288 	smb_id_t *id;
289 
290 	if ((id = malloc(sizeof (smb_id_t))) == NULL)
291 		return (NULL);
292 
293 	id->i_id = (uid_t)-1;
294 	id->i_sidattr.attrs = 7;
295 	id->i_sidattr.sid = smb_sid_dup(sid);
296 
297 	if (id->i_sidattr.sid == NULL) {
298 		free(id);
299 		id = NULL;
300 	}
301 
302 	return (id);
303 }
304 
305 /*
306  * Token owner should be set to local Administrators group
307  * in two cases:
308  *   1. The logged on user is a member of Domain Admins group
309  *   2. he/she is a member of local Administrators group
310  */
311 static smb_id_t *
312 smb_token_create_owner(smb_userinfo_t *user_info)
313 {
314 #ifdef SMB_SUPPORT_GROUP_OWNER
315 	smb_sid_t *owner_sid;
316 	smb_wka_t *wka;
317 
318 	if (user_info->flags & SMB_UINFO_FLAG_ADMIN) {
319 		wka = smb_wka_lookup("Administrators");
320 		assert(wka);
321 		owner_sid = wka->wka_binsid;
322 	} else {
323 		owner_sid = user_info->user_sid;
324 	}
325 
326 	return (smb_token_create_id(owner_sid));
327 #endif
328 	return (smb_token_create_id(user_info->user_sid));
329 }
330 
331 static smb_privset_t *
332 smb_token_create_privs(smb_userinfo_t *user_info)
333 {
334 	smb_privset_t *privs;
335 	smb_giter_t gi;
336 	smb_group_t grp;
337 	int rc;
338 
339 	privs = smb_privset_new();
340 	if (privs == NULL)
341 		return (NULL);
342 
343 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
344 		smb_privset_free(privs);
345 		return (NULL);
346 	}
347 
348 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
349 		if (smb_lgrp_is_member(&grp, user_info->user_sid)) {
350 			smb_privset_merge(privs, grp.sg_privs);
351 		}
352 		smb_lgrp_free(&grp);
353 	}
354 	smb_lgrp_iterclose(&gi);
355 
356 	if (user_info->flags & SMB_UINFO_FLAG_ADMIN) {
357 		rc = smb_lgrp_getbyname("Administrators", &grp);
358 		if (rc == SMB_LGRP_SUCCESS) {
359 			smb_privset_merge(privs, grp.sg_privs);
360 			smb_lgrp_free(&grp);
361 		}
362 
363 		/*
364 		 * This privilege is required to view/edit SACL
365 		 */
366 		smb_privset_enable(privs, SE_SECURITY_LUID);
367 	}
368 
369 	return (privs);
370 }
371 
372 static void
373 smb_token_set_flags(smb_token_t *token, smb_userinfo_t *user_info)
374 {
375 	smb_wka_t *wka;
376 
377 	if (user_info->flags & SMB_UINFO_FLAG_ANON) {
378 		token->tkn_flags |= SMB_ATF_ANON;
379 		return;
380 	}
381 
382 	if (user_info->rid == DOMAIN_USER_RID_GUEST) {
383 		token->tkn_flags |= SMB_ATF_GUEST;
384 		return;
385 	}
386 
387 	wka = smb_wka_lookup("Administrators");
388 	if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
389 		token->tkn_flags |= SMB_ATF_ADMIN;
390 
391 	wka = smb_wka_lookup("Power Users");
392 	if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
393 		token->tkn_flags |= SMB_ATF_POWERUSER;
394 
395 	wka = smb_wka_lookup("Backup Operators");
396 	if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
397 		token->tkn_flags |= SMB_ATF_BACKUPOP;
398 
399 }
400 
401 /*
402  * smb_token_create
403  *
404  * Build an access token based on the given user information (user_info).
405  *
406  * If everything is successful, a pointer to an access token is
407  * returned. Otherwise a null pointer is returned.
408  */
409 static smb_token_t *
410 smb_token_create(smb_userinfo_t *user_info)
411 {
412 	smb_token_t *token;
413 
414 	if (user_info->sid_name_use != SidTypeUser)
415 		return (NULL);
416 
417 	token = (smb_token_t *)malloc(sizeof (smb_token_t));
418 	if (token == NULL) {
419 		syslog(LOG_ERR, "smb_token_create: resource shortage");
420 		return (NULL);
421 	}
422 	bzero(token, sizeof (smb_token_t));
423 
424 	/* User */
425 	token->tkn_user = smb_token_create_id(user_info->user_sid);
426 	if (token->tkn_user == NULL) {
427 		smb_token_destroy(token);
428 		return (NULL);
429 	}
430 
431 	/* Owner */
432 	token->tkn_owner = smb_token_create_owner(user_info);
433 	if (token->tkn_owner == NULL) {
434 		smb_token_destroy(token);
435 		return (NULL);
436 	}
437 
438 	/* Primary Group */
439 	token->tkn_primary_grp = smb_token_create_id(user_info->pgrp_sid);
440 	if (token->tkn_primary_grp == NULL) {
441 		smb_token_destroy(token);
442 		return (NULL);
443 	}
444 
445 	/* Privileges */
446 	token->tkn_privileges = smb_token_create_privs(user_info);
447 	if (token->tkn_privileges == NULL) {
448 		smb_token_destroy(token);
449 		return (NULL);
450 	}
451 
452 	/* Windows Groups */
453 	token->tkn_win_grps = smb_token_create_wingrps(user_info);
454 
455 	smb_token_set_flags(token, user_info);
456 
457 	/*
458 	 * IMPORTANT
459 	 *
460 	 * This function has to be called after all the SIDs in the
461 	 * token are setup (i.e. user, owner, primary and supplementary
462 	 * groups) and before setting up Solaris groups.
463 	 */
464 	if (smb_token_sids2ids(token) != 0) {
465 		syslog(LOG_ERR, "%s\\%s: idmap failed",
466 		    (user_info->domain_name) ? user_info->domain_name : "",
467 		    (user_info->name) ? user_info->name : "");
468 		smb_token_destroy(token);
469 		return (NULL);
470 	}
471 
472 	/* Solaris Groups */
473 	token->tkn_posix_grps = smb_token_create_pxgrps(token->tkn_user->i_id);
474 
475 	if (user_info->session_key) {
476 		token->tkn_session_key = malloc(sizeof (smb_session_key_t));
477 		if (token->tkn_session_key == NULL) {
478 			smb_token_destroy(token);
479 			return (NULL);
480 		}
481 
482 		(void) memcpy(token->tkn_session_key,
483 		    user_info->session_key, sizeof (smb_session_key_t));
484 	}
485 
486 	token->tkn_account_name = strdup(user_info->name);
487 	token->tkn_domain_name = strdup(user_info->domain_name);
488 
489 	if (!smb_token_is_valid(token)) {
490 		smb_token_destroy(token);
491 		return (NULL);
492 	}
493 
494 	return (token);
495 }
496 
497 /*
498  * smb_token_create_wingrps
499  *
500  * This private function supports smb_token_create() by mapping the group
501  * information in the user_info structure to the form required in an
502  * access token. The main difference is that the user_info contains
503  * RIDs while and access token contains full SIDs. Memory allocated
504  * here will be deallocated as part of smb_token_destroy().
505  *
506  * If everything is successful, a pointer to a smb_win_grps_t
507  * structure is returned. Otherwise a null pointer is returned.
508  */
509 static smb_win_grps_t *
510 smb_token_create_wingrps(smb_userinfo_t *user_info)
511 {
512 	static char *wk_grps[] =
513 		{"Authenticated Users", "NETWORK", "Administrators"};
514 	smb_win_grps_t *tkn_grps;
515 	smb_sid_attrs_t *dlg_grps;
516 	smb_rid_attrs_t *g_grps;
517 	smb_sid_attrs_t *grp;
518 	smb_sid_t *builtin_sid;
519 	smb_giter_t gi;
520 	smb_group_t lgrp;
521 	uint32_t n_gg, n_lg, n_dlg, n_wg;
522 	uint32_t i, j;
523 	int size, count;
524 
525 	if (user_info == NULL)
526 		return (NULL);
527 
528 	n_gg = user_info->n_groups;		/* Global Groups */
529 	n_dlg = user_info->n_other_grps;	/* Domain Local Groups */
530 
531 	/* Local Groups */
532 	(void) smb_lgrp_numbymember(user_info->user_sid, (int *)&n_lg);
533 
534 	/* Well known Groups */
535 	if ((user_info->flags & SMB_UINFO_FLAG_ADMIN) == SMB_UINFO_FLAG_DADMIN)
536 		/* if user is a domain admin but not a local admin */
537 		n_wg = 3;
538 	else if (user_info->flags & SMB_UINFO_FLAG_ANON)
539 		n_wg = 0;
540 	else
541 		n_wg = 2;
542 
543 	count = n_gg + n_dlg + n_lg + n_wg;
544 	size = sizeof (smb_win_grps_t) + (count * sizeof (smb_id_t));
545 
546 	if ((tkn_grps = malloc(size)) == NULL)
547 		return (NULL);
548 	bzero(tkn_grps, size);
549 
550 	/* Add global groups */
551 	g_grps = user_info->groups;
552 	for (i = 0; i < n_gg; i++) {
553 		grp = &tkn_grps->wg_groups[i].i_sidattr;
554 		grp->sid = smb_sid_splice(user_info->domain_sid, g_grps[i].rid);
555 		if (grp->sid == NULL)
556 			break;
557 		grp->attrs = g_grps[i].attributes;
558 	}
559 
560 	if (n_gg == 0) {
561 		/*
562 		 * if there's no global group should add the
563 		 * primary group.
564 		 */
565 		grp = &tkn_grps->wg_groups[i].i_sidattr;
566 		grp->sid = smb_sid_dup(user_info->pgrp_sid);
567 		if (grp->sid != NULL) {
568 			grp->attrs = 0x7;
569 			i++;
570 		}
571 	}
572 
573 	/* Add domain local groups */
574 	dlg_grps = user_info->other_grps;
575 	for (j = 0; j < n_dlg; j++, i++) {
576 		grp = &tkn_grps->wg_groups[i].i_sidattr;
577 		grp->sid = smb_sid_dup(dlg_grps[j].sid);
578 		if (grp->sid == NULL)
579 			break;
580 		grp->attrs = dlg_grps[j].attrs;
581 	}
582 
583 	/* Add local groups */
584 	if (n_lg && (smb_lgrp_iteropen(&gi) == SMB_LGRP_SUCCESS)) {
585 		j = 0;
586 		while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
587 			if ((j < n_lg) &&
588 			    smb_lgrp_is_member(&lgrp, user_info->user_sid)) {
589 				grp = &tkn_grps->wg_groups[i].i_sidattr;
590 				grp->sid = smb_sid_dup(lgrp.sg_id.gs_sid);
591 				if (grp->sid == NULL) {
592 					smb_lgrp_free(&lgrp);
593 					break;
594 				}
595 				grp->attrs = lgrp.sg_attr;
596 				i++;
597 				j++;
598 			}
599 			smb_lgrp_free(&lgrp);
600 		}
601 		smb_lgrp_iterclose(&gi);
602 	}
603 
604 	/* Add well known groups */
605 	for (j = 0; j < n_wg; j++, i++) {
606 		builtin_sid = smb_wka_lookup_name(wk_grps[j], NULL);
607 		if (builtin_sid == NULL)
608 			break;
609 		tkn_grps->wg_groups[i].i_sidattr.sid = builtin_sid;
610 		tkn_grps->wg_groups[i].i_sidattr.attrs = 0x7;
611 	}
612 
613 	tkn_grps->wg_count = i;
614 	return (tkn_grps);
615 }
616 
617 /*
618  * smb_logon
619  *
620  * Performs user authentication and creates a token if the
621  * authentication is successful.
622  *
623  * Returns pointer to the created token.
624  */
625 smb_token_t *
626 smb_logon(netr_client_t *clnt)
627 {
628 	smb_token_t *token = NULL;
629 	smb_userinfo_t *uinfo;
630 	uint32_t status;
631 
632 	if ((uinfo = mlsvc_alloc_user_info()) == 0)
633 		return (NULL);
634 
635 	switch (clnt->flags) {
636 	case NETR_CFLG_DOMAIN:
637 		/* Pass through authentication with DC */
638 		status = smb_logon_domain(clnt, uinfo);
639 		break;
640 
641 	case NETR_CFLG_LOCAL:
642 		/* Local authentication */
643 		status = smb_logon_local(clnt, uinfo);
644 		break;
645 
646 	case NETR_CFLG_ANON:
647 		/* Anonymous user; no authentication */
648 		status = smb_logon_none(clnt, uinfo);
649 		break;
650 
651 	default:
652 		status = NT_STATUS_INVALID_PARAMETER;
653 		break;
654 	}
655 
656 	if (status == NT_STATUS_SUCCESS)
657 		token = smb_token_create(uinfo);
658 
659 	mlsvc_free_user_info(uinfo);
660 	return (token);
661 }
662 
663 /*
664  * smb_logon_domain
665  *
666  * Performs pass through authentication with PDC.
667  */
668 static uint32_t
669 smb_logon_domain(netr_client_t *clnt, smb_userinfo_t *uinfo)
670 {
671 	uint32_t status;
672 
673 	if ((status = netlogon_logon(clnt, uinfo)) != 0) {
674 		if (status == NT_STATUS_CANT_ACCESS_DOMAIN_INFO) {
675 			if ((status = netlogon_logon(clnt, uinfo)) != 0) {
676 				syslog(LOG_INFO, "SmbLogon[%s\\%s]: %s",
677 				    clnt->domain, clnt->username,
678 				    xlate_nt_status(status));
679 				return (status);
680 			}
681 		}
682 	}
683 
684 	return (status);
685 }
686 
687 /*
688  * smb_logon_local
689  *
690  * Check to see if connected user has an entry in the local
691  * smbpasswd database. If it has, tries both LM hash and NT
692  * hash with user's password(s) to authenticate the user.
693  */
694 static uint32_t
695 smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo)
696 {
697 	smb_passwd_t smbpw;
698 	boolean_t lm_ok, nt_ok;
699 	uint32_t status;
700 
701 	if (smb_pwd_getpasswd(clnt->username, &smbpw) == NULL) {
702 		/*
703 		 * If user doesn't have entry either in smbpasswd
704 		 * or passwd it's considered as an invalid user.
705 		 */
706 		status = NT_STATUS_NO_SUCH_USER;
707 		syslog(LOG_NOTICE, "SmbLogon[%s\\%s]: %s",
708 		    clnt->domain, clnt->username,
709 		    xlate_nt_status(status));
710 		return (status);
711 	}
712 	if (smbpw.pw_flags & SMB_PWF_DISABLE)
713 		return (NT_STATUS_ACCOUNT_DISABLED);
714 
715 	nt_ok = lm_ok = B_FALSE;
716 	if ((smbpw.pw_flags & SMB_PWF_LM) &&
717 	    (clnt->lm_password.lm_password_len != 0)) {
718 		lm_ok = smb_auth_validate_lm(
719 		    clnt->challenge_key.challenge_key_val,
720 		    clnt->challenge_key.challenge_key_len,
721 		    &smbpw,
722 		    clnt->lm_password.lm_password_val,
723 		    clnt->lm_password.lm_password_len,
724 		    clnt->domain,
725 		    clnt->username);
726 		uinfo->session_key = NULL;
727 	}
728 
729 	if (!lm_ok && (clnt->nt_password.nt_password_len != 0)) {
730 		if ((uinfo->session_key =
731 		    malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
732 			return (NT_STATUS_NO_MEMORY);
733 		nt_ok = smb_auth_validate_nt(
734 		    clnt->challenge_key.challenge_key_val,
735 		    clnt->challenge_key.challenge_key_len,
736 		    &smbpw,
737 		    clnt->nt_password.nt_password_val,
738 		    clnt->nt_password.nt_password_len,
739 		    clnt->domain,
740 		    clnt->username,
741 		    (uchar_t *)uinfo->session_key);
742 	}
743 
744 	if (!nt_ok && !lm_ok) {
745 		status = NT_STATUS_WRONG_PASSWORD;
746 		syslog(LOG_NOTICE, "SmbLogon[%s\\%s]: %s",
747 		    clnt->domain, clnt->username,
748 		    xlate_nt_status(status));
749 		return (status);
750 	}
751 
752 	status = smb_setup_luinfo(uinfo, clnt, smbpw.pw_uid);
753 	return (status);
754 }
755 
756 /*
757  * smb_logon_none
758  *
759  * Setup user information for anonymous user.
760  * No authentication is required.
761  */
762 static uint32_t
763 smb_logon_none(netr_client_t *clnt, smb_userinfo_t *uinfo)
764 {
765 	return (smb_setup_luinfo(uinfo, clnt, (uid_t)-1));
766 }
767 
768 /*
769  * smb_setup_luinfo
770  *
771  * Setup local user information based on the client information and
772  * user's record in the local password file.
773  */
774 static uint32_t
775 smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid)
776 {
777 	idmap_stat stat;
778 	smb_idmap_batch_t sib;
779 	smb_idmap_t *umap, *gmap;
780 	smb_group_t grp;
781 	struct passwd pw;
782 	char pwbuf[1024];
783 	char nbname[NETBIOS_NAME_SZ];
784 
785 	(void) smb_getnetbiosname(nbname, sizeof (nbname));
786 	lui->sid_name_use = SidTypeUser;
787 	lui->domain_sid = smb_sid_dup(nt_domain_local_sid());
788 	lui->name = strdup(clnt->username);
789 	lui->domain_name = strdup(nbname);
790 	lui->n_groups = 0;
791 	lui->groups = NULL;
792 	lui->n_other_grps = 0;
793 	lui->other_grps = NULL;
794 	lui->flags = 0;
795 
796 	if (lui->name == NULL || lui->domain_name == NULL ||
797 	    lui->domain_sid == NULL)
798 		return (NT_STATUS_INVALID_PARAMETER);
799 
800 	if (clnt->flags & NETR_CFLG_ANON) {
801 		lui->user_sid = smb_wka_lookup_name("Anonymous", NULL);
802 		lui->pgrp_sid = smb_wka_lookup_name("Anonymous", NULL);
803 		lui->flags = SMB_UINFO_FLAG_ANON;
804 
805 		if (lui->user_sid == NULL || lui->pgrp_sid == NULL)
806 			return (NT_STATUS_NO_MEMORY);
807 
808 		return (NT_STATUS_SUCCESS);
809 	}
810 
811 	if (getpwuid_r(uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
812 		return (NT_STATUS_NO_SUCH_USER);
813 
814 	/* Get the SID for user's uid & gid */
815 	stat = smb_idmap_batch_create(&sib, 2, SMB_IDMAP_ID2SID);
816 	if (stat != IDMAP_SUCCESS) {
817 		return (NT_STATUS_INTERNAL_ERROR);
818 	}
819 
820 	umap = &sib.sib_maps[0];
821 	stat = smb_idmap_batch_getsid(sib.sib_idmaph, umap, pw.pw_uid,
822 	    SMB_IDMAP_USER);
823 
824 	if (stat != IDMAP_SUCCESS) {
825 		smb_idmap_batch_destroy(&sib);
826 		return (NT_STATUS_INTERNAL_ERROR);
827 	}
828 
829 	gmap = &sib.sib_maps[1];
830 	stat = smb_idmap_batch_getsid(sib.sib_idmaph, gmap, pw.pw_gid,
831 	    SMB_IDMAP_GROUP);
832 
833 	if (stat != IDMAP_SUCCESS) {
834 		smb_idmap_batch_destroy(&sib);
835 		return (NT_STATUS_INTERNAL_ERROR);
836 	}
837 
838 	stat = smb_idmap_batch_getmappings(&sib);
839 
840 	if (stat != IDMAP_SUCCESS) {
841 		return (NT_STATUS_INTERNAL_ERROR);
842 	}
843 
844 	lui->rid = umap->sim_rid;
845 	lui->user_sid = smb_sid_dup(umap->sim_sid);
846 
847 	lui->primary_group_rid = gmap->sim_rid;
848 	lui->pgrp_sid = smb_sid_dup(gmap->sim_sid);
849 
850 	smb_idmap_batch_destroy(&sib);
851 
852 	if ((lui->user_sid == NULL) || (lui->pgrp_sid == NULL))
853 		return (NT_STATUS_NO_MEMORY);
854 
855 	if (smb_lgrp_getbyname("Administrators", &grp) == SMB_LGRP_SUCCESS) {
856 		if (smb_lgrp_is_member(&grp, lui->user_sid))
857 			lui->flags = SMB_UINFO_FLAG_LADMIN;
858 		smb_lgrp_free(&grp);
859 	}
860 
861 	return (NT_STATUS_SUCCESS);
862 }
863 
864 /*
865  * smb_token_is_valid
866  *
867  * check to see if specified fields of the given access
868  * token are valid.
869  * Returns 1 if all of them are valid; otherwise 0.
870  */
871 static int
872 smb_token_is_valid(smb_token_t *token)
873 {
874 	int valid;
875 
876 	valid = (token->tkn_user != 0) &&
877 	    (token->tkn_user->i_sidattr.sid != 0) &&
878 	    (token->tkn_privileges != 0) &&
879 	    (token->tkn_win_grps != 0) &&
880 	    (token->tkn_owner != 0) &&
881 	    (token->tkn_owner->i_sidattr.sid != 0) &&
882 	    (token->tkn_primary_grp != 0) &&
883 	    (token->tkn_primary_grp->i_sidattr.sid != 0);
884 
885 	return (valid);
886 }
887 
888 /*
889  * smb_token_user_sid
890  *
891  * Return a pointer to the user SID in the specified token. A null
892  * pointer indicates an error.
893  */
894 static smb_sid_t *
895 smb_token_user_sid(smb_token_t *token)
896 {
897 	if (token && token->tkn_user)
898 		return ((token)->tkn_user->i_sidattr.sid);
899 
900 	return (NULL);
901 }
902 
903 /*
904  * smb_token_group_sid
905  *
906  * Return a pointer to the group SID as indicated by the iterator.
907  * Setting the iterator to 0 before calling this function will return
908  * the first group, which will always be the primary group. The
909  * iterator will be incremented before returning the SID so that this
910  * function can be used to cycle through the groups. The caller can
911  * adjust the iterator as required between calls to obtain any specific
912  * group.
913  *
914  * On success a pointer to the appropriate group SID will be returned.
915  * Otherwise a null pointer will be returned.
916  */
917 static smb_sid_t *
918 smb_token_group_sid(smb_token_t *token, int *iterator)
919 {
920 	smb_win_grps_t *groups;
921 	int index;
922 
923 	if (token == NULL || iterator == NULL) {
924 		return (NULL);
925 	}
926 
927 	if ((groups = token->tkn_win_grps) == NULL) {
928 		return (NULL);
929 	}
930 
931 	index = *iterator;
932 
933 	if (index < 0 || index >= groups->wg_count) {
934 		return (NULL);
935 	}
936 
937 	++(*iterator);
938 	return (groups->wg_groups[index].i_sidattr.sid);
939 }
940 
941 /*
942  * smb_token_is_member
943  *
944  * This function will determine whether or not the specified SID is a
945  * member of a token. The user SID and all group SIDs are tested.
946  * Returns 1 if the SID is a member of the token. Otherwise returns 0.
947  */
948 static int
949 smb_token_is_member(smb_token_t *token, smb_sid_t *sid)
950 {
951 	smb_sid_t *tsid;
952 	int iterator = 0;
953 
954 	tsid = smb_token_user_sid(token);
955 	while (tsid) {
956 		if (smb_sid_cmp(tsid, sid))
957 			return (1);
958 
959 		tsid = smb_token_group_sid(token, &iterator);
960 	}
961 
962 	return (0);
963 }
964 
965 /*
966  * smb_token_log
967  *
968  * Diagnostic routine to write the contents of a token to the log.
969  */
970 void
971 smb_token_log(smb_token_t *token)
972 {
973 	smb_win_grps_t *w_grps;
974 	smb_posix_grps_t *x_grps;
975 	smb_sid_attrs_t *grp;
976 	char sidstr[SMB_SID_STRSZ];
977 	int i;
978 
979 	if (token == NULL)
980 		return;
981 
982 	syslog(LOG_DEBUG, "Token for %s\\%s",
983 	    (token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-",
984 	    (token->tkn_account_name) ? token->tkn_account_name : "-NULL-");
985 
986 	syslog(LOG_DEBUG, "   User->Attr: %d",
987 	    token->tkn_user->i_sidattr.attrs);
988 	smb_sid_tostr((smb_sid_t *)token->tkn_user->i_sidattr.sid, sidstr);
989 	syslog(LOG_DEBUG, "   User->Sid: %s (id=%u)",
990 	    sidstr, token->tkn_user->i_id);
991 
992 	smb_sid_tostr((smb_sid_t *)token->tkn_owner->i_sidattr.sid, sidstr);
993 	syslog(LOG_DEBUG, "   Ownr->Sid: %s (id=%u)",
994 	    sidstr, token->tkn_owner->i_id);
995 
996 	smb_sid_tostr((smb_sid_t *)token->tkn_primary_grp->i_sidattr.sid,
997 	    sidstr);
998 	syslog(LOG_DEBUG, "   PGrp->Sid: %s (id=%u)",
999 	    sidstr, token->tkn_primary_grp->i_id);
1000 
1001 	w_grps = token->tkn_win_grps;
1002 	if (w_grps) {
1003 		syslog(LOG_DEBUG, "   Windows groups: %d",
1004 		    w_grps->wg_count);
1005 
1006 		for (i = 0; i < w_grps->wg_count; ++i) {
1007 			grp = &w_grps->wg_groups[i].i_sidattr;
1008 			syslog(LOG_DEBUG,
1009 			    "    Grp[%d].Attr:%d", i, grp->attrs);
1010 			if (w_grps->wg_groups[i].i_sidattr.sid) {
1011 				smb_sid_tostr((smb_sid_t *)grp->sid, sidstr);
1012 				syslog(LOG_DEBUG,
1013 				    "    Grp[%d].Sid: %s (id=%u)", i, sidstr,
1014 				    w_grps->wg_groups[i].i_id);
1015 			}
1016 		}
1017 	}
1018 	else
1019 		syslog(LOG_DEBUG, "   No Windows groups");
1020 
1021 	x_grps = token->tkn_posix_grps;
1022 	if (x_grps) {
1023 		syslog(LOG_DEBUG, "   Solaris groups: %d",
1024 		    x_grps->pg_ngrps);
1025 		for (i = 0; i < x_grps->pg_ngrps; i++)
1026 			syslog(LOG_DEBUG, "    %u",
1027 			    x_grps->pg_grps[i]);
1028 	}
1029 	else
1030 		syslog(LOG_DEBUG, "   No Solaris groups");
1031 
1032 	if (token->tkn_privileges)
1033 		smb_privset_log(token->tkn_privileges);
1034 	else
1035 		syslog(LOG_DEBUG, "   No privileges");
1036 }
1037