xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw /*
29*5331Samw  * Utility functions to support the RPC interface library.
30*5331Samw  */
31*5331Samw 
32*5331Samw #include <stdio.h>
33*5331Samw #include <stdarg.h>
34*5331Samw #include <strings.h>
35*5331Samw #include <unistd.h>
36*5331Samw #include <netdb.h>
37*5331Samw #include <stdlib.h>
38*5331Samw #include <pwd.h>
39*5331Samw #include <grp.h>
40*5331Samw 
41*5331Samw #include <sys/time.h>
42*5331Samw #include <sys/systm.h>
43*5331Samw 
44*5331Samw #include <smbsrv/libsmb.h>
45*5331Samw #include <smbsrv/libsmbrdr.h>
46*5331Samw #include <smbsrv/libsmbns.h>
47*5331Samw #include <smbsrv/libmlsvc.h>
48*5331Samw 
49*5331Samw #include <smbsrv/smbinfo.h>
50*5331Samw #include <smbsrv/ntsid.h>
51*5331Samw #include <smbsrv/lsalib.h>
52*5331Samw #include <smbsrv/samlib.h>
53*5331Samw #include <smbsrv/mlsvc_util.h>
54*5331Samw #include <smbsrv/mlsvc.h>
55*5331Samw 
56*5331Samw extern int netr_open(char *, char *, mlsvc_handle_t *);
57*5331Samw extern int netr_close(mlsvc_handle_t *);
58*5331Samw extern DWORD netlogon_auth(char *, mlsvc_handle_t *, DWORD);
59*5331Samw extern int mlsvc_user_getauth(char *, char *, smb_auth_info_t *);
60*5331Samw 
61*5331Samw static int mlsvc_lookup_local_name(char *name, nt_sid_t **sid);
62*5331Samw static int mlsvc_lookup_nt_name(char *name, nt_sid_t **sid);
63*5331Samw static int mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize);
64*5331Samw 
65*5331Samw /*
66*5331Samw  * Compare the supplied domain name with the local hostname.
67*5331Samw  * We need to deal with both server names and fully-qualified
68*5331Samw  * domain names.
69*5331Samw  *
70*5331Samw  * Returns:
71*5331Samw  *	0	The specified domain is not the local domain,
72*5331Samw  *	1	The Specified domain is the local domain.
73*5331Samw  *	-1	Invalid parameter or unable to get the local
74*5331Samw  *		system information.
75*5331Samw  */
76*5331Samw int
77*5331Samw mlsvc_is_local_domain(const char *domain)
78*5331Samw {
79*5331Samw 	char hostname[MAXHOSTNAMELEN];
80*5331Samw 	uint32_t mode;
81*5331Samw 	int rc;
82*5331Samw 
83*5331Samw 	if (strchr(domain, '.') != NULL)
84*5331Samw 		rc = smb_getfqhostname(hostname, MAXHOSTNAMELEN);
85*5331Samw 	else
86*5331Samw 		rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1);
87*5331Samw 
88*5331Samw 	if (rc != 0)
89*5331Samw 		return (-1);
90*5331Samw 
91*5331Samw 	rc = strcasecmp(domain, hostname);
92*5331Samw 	mode = smb_get_security_mode();
93*5331Samw 
94*5331Samw 	if ((rc == 0) || (mode == SMB_SECMODE_WORKGRP))
95*5331Samw 		return (1);
96*5331Samw 
97*5331Samw 	return (0);
98*5331Samw }
99*5331Samw 
100*5331Samw /*
101*5331Samw  * mlsvc_lookup_name
102*5331Samw  *
103*5331Samw  * Lookup a name in the specified domain and translate it to a SID.
104*5331Samw  * If the name is in the NT domain, it may refer to a user, group or
105*5331Samw  * alias. Otherwise it must refer to a UNIX username. The memory for
106*5331Samw  * the sid is allocated using malloc so the caller should call free
107*5331Samw  * when it is no longer required.
108*5331Samw  *
109*5331Samw  * On success, 0 will be returned and sid will point to a local domain
110*5331Samw  * user SID. Otherwise -1 will be returned.
111*5331Samw  */
112*5331Samw int
113*5331Samw mlsvc_lookup_name(char *domain, char *name, nt_sid_t **sid)
114*5331Samw {
115*5331Samw 	if (domain == NULL || name == NULL || sid == NULL)
116*5331Samw 		return (-1);
117*5331Samw 
118*5331Samw 	if (mlsvc_is_local_domain(domain) == 1)
119*5331Samw 		return (mlsvc_lookup_local_name(name, sid));
120*5331Samw 	else
121*5331Samw 		return (mlsvc_lookup_nt_name(name, sid));
122*5331Samw }
123*5331Samw 
124*5331Samw /*
125*5331Samw  * mlsvc_lookup_local_name
126*5331Samw  *
127*5331Samw  * Lookup a name in the local password file and translate it to a SID.
128*5331Samw  * The name must refer to a user. This is a private function intended
129*5331Samw  * to support mlsvc_lookup_name so it doesn't perform any parameter
130*5331Samw  * validation. The memory for the sid is allocated using malloc so the
131*5331Samw  * caller must call free when it is no longer required.
132*5331Samw  *
133*5331Samw  * On success, 0 will be returned and sid will point to a local domain
134*5331Samw  * user SID. Otherwise -1 will be returned.
135*5331Samw  */
136*5331Samw static int
137*5331Samw mlsvc_lookup_local_name(char *name, nt_sid_t **sid)
138*5331Samw {
139*5331Samw 	struct passwd *pw;
140*5331Samw 	nt_sid_t *domain_sid;
141*5331Samw 
142*5331Samw 	if ((pw = getpwnam(name)) == NULL)
143*5331Samw 		return (-1);
144*5331Samw 
145*5331Samw 	if ((domain_sid = nt_domain_local_sid()) == NULL)
146*5331Samw 		return (-1);
147*5331Samw 
148*5331Samw 	*sid = nt_sid_splice(domain_sid, pw->pw_uid);
149*5331Samw 	return (0);
150*5331Samw }
151*5331Samw 
152*5331Samw /*
153*5331Samw  * mlsvc_lookup_nt_name
154*5331Samw  *
155*5331Samw  * Lookup a name in the specified NT domain and translate it to a SID.
156*5331Samw  * The name may refer to a user, group or alias. This is a private
157*5331Samw  * function intended to support mlsvc_lookup_name so it doesn't do any
158*5331Samw  * parameter validation. The memory for the sid is allocated using
159*5331Samw  * malloc so the caller should call free when it is no longer required.
160*5331Samw  *
161*5331Samw  * On success, 0 will be returned and sid will point to an NT domain
162*5331Samw  * user SID. Otherwise -1 will be returned.
163*5331Samw  */
164*5331Samw static int
165*5331Samw mlsvc_lookup_nt_name(char *name, nt_sid_t **sid)
166*5331Samw {
167*5331Samw 	smb_userinfo_t *user_info;
168*5331Samw 
169*5331Samw 	if ((user_info = mlsvc_alloc_user_info()) == NULL)
170*5331Samw 		return (-1);
171*5331Samw 
172*5331Samw 	if (lsa_lookup_name(0, 0, name, user_info) != 0)
173*5331Samw 		return (-1);
174*5331Samw 
175*5331Samw 	*sid = nt_sid_splice(user_info->domain_sid, user_info->rid);
176*5331Samw 	mlsvc_free_user_info(user_info);
177*5331Samw 	return (0);
178*5331Samw }
179*5331Samw 
180*5331Samw /*
181*5331Samw  * mlsvc_lookup_sid
182*5331Samw  *
183*5331Samw  * Lookup a SID and translate it to a name. The name returned may refer
184*5331Samw  * to a domain, user, group or alias dependent on the SID. On success 0
185*5331Samw  * will be returned. Otherwise -1 will be returned.
186*5331Samw  */
187*5331Samw int
188*5331Samw mlsvc_lookup_sid(nt_sid_t *sid, char *buf, int bufsize)
189*5331Samw {
190*5331Samw 	struct passwd *pw;
191*5331Samw 	struct group *gr;
192*5331Samw 	nt_group_t *grp;
193*5331Samw 	DWORD rid;
194*5331Samw 
195*5331Samw 	if (sid == NULL || buf == NULL)
196*5331Samw 		return (-1);
197*5331Samw 
198*5331Samw 	if (nt_sid_is_local(sid)) {
199*5331Samw 		(void) nt_sid_get_rid(sid, &rid);
200*5331Samw 
201*5331Samw 		switch (SAM_RID_TYPE(rid)) {
202*5331Samw 		case SAM_RT_NT_UID:
203*5331Samw 			break;
204*5331Samw 
205*5331Samw 		case SAM_RT_NT_GID:
206*5331Samw 			if ((grp = nt_groups_lookup_rid(rid)) == NULL)
207*5331Samw 				return (-1);
208*5331Samw 
209*5331Samw 			(void) strlcpy(buf, grp->name, bufsize);
210*5331Samw 			break;
211*5331Samw 
212*5331Samw 		case SAM_RT_UNIX_UID:
213*5331Samw 			if ((pw = getpwuid(SAM_DECODE_RID(rid))) == NULL)
214*5331Samw 				return (-1);
215*5331Samw 
216*5331Samw 			(void) strlcpy(buf, pw->pw_name, bufsize);
217*5331Samw 			break;
218*5331Samw 
219*5331Samw 		case SAM_RT_UNIX_GID:
220*5331Samw 			if ((gr = getgrgid(SAM_DECODE_RID(rid))) == NULL)
221*5331Samw 				return (-1);
222*5331Samw 
223*5331Samw 			(void) strlcpy(buf, gr->gr_name, bufsize);
224*5331Samw 			break;
225*5331Samw 		}
226*5331Samw 
227*5331Samw 		return (0);
228*5331Samw 	}
229*5331Samw 
230*5331Samw 	return (mlsvc_lookup_nt_sid(sid, buf, bufsize));
231*5331Samw }
232*5331Samw 
233*5331Samw /*
234*5331Samw  * mlsvc_lookup_nt_sid
235*5331Samw  *
236*5331Samw  * Lookup an NT SID and translate it to a name. This is a private
237*5331Samw  * function intended to support mlsvc_lookup_sid so it doesn't do any
238*5331Samw  * parameter validation. The input account_name specifies the logon/
239*5331Samw  * session to be used for the lookup. It doesn't need to have any
240*5331Samw  * association with the SID being looked up. The name returned may
241*5331Samw  * refer to a domain, user, group or alias dependent on the SID.
242*5331Samw  *
243*5331Samw  * On success the name will be copied into buf and 0 will be returned.
244*5331Samw  * Otherwise -1 will be returned.
245*5331Samw  */
246*5331Samw static int
247*5331Samw mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize)
248*5331Samw {
249*5331Samw 	smb_userinfo_t *user_info;
250*5331Samw 	int rc;
251*5331Samw 
252*5331Samw 	if ((user_info = mlsvc_alloc_user_info()) == NULL)
253*5331Samw 		return (-1);
254*5331Samw 
255*5331Samw 	if ((rc = lsa_lookup_sid(sid, user_info)) == 0)
256*5331Samw 		(void) strlcpy(buf, user_info->name, bufsize);
257*5331Samw 
258*5331Samw 	mlsvc_free_user_info(user_info);
259*5331Samw 	return (rc);
260*5331Samw }
261*5331Samw 
262*5331Samw /*
263*5331Samw  * mlsvc_alloc_user_info
264*5331Samw  *
265*5331Samw  * Allocate a user_info structure and set the contents to zero. A
266*5331Samw  * pointer to the user_info structure is returned.
267*5331Samw  */
268*5331Samw smb_userinfo_t *
269*5331Samw mlsvc_alloc_user_info(void)
270*5331Samw {
271*5331Samw 	smb_userinfo_t *user_info;
272*5331Samw 
273*5331Samw 	user_info = (smb_userinfo_t *)malloc(sizeof (smb_userinfo_t));
274*5331Samw 	if (user_info == NULL)
275*5331Samw 		return (NULL);
276*5331Samw 
277*5331Samw 	bzero(user_info, sizeof (smb_userinfo_t));
278*5331Samw 	return (user_info);
279*5331Samw }
280*5331Samw 
281*5331Samw /*
282*5331Samw  * mlsvc_free_user_info
283*5331Samw  *
284*5331Samw  * Free a user_info structure. This function ensures that the contents
285*5331Samw  * of the user_info are freed as well as the user_info itself.
286*5331Samw  */
287*5331Samw void
288*5331Samw mlsvc_free_user_info(smb_userinfo_t *user_info)
289*5331Samw {
290*5331Samw 	if (user_info) {
291*5331Samw 		mlsvc_release_user_info(user_info);
292*5331Samw 		free(user_info);
293*5331Samw 	}
294*5331Samw }
295*5331Samw 
296*5331Samw /*
297*5331Samw  * mlsvc_release_user_info
298*5331Samw  *
299*5331Samw  * Release the contents of a user_info structure and zero out the
300*5331Samw  * elements but do not free the user_info structure itself. This
301*5331Samw  * function cleans out the structure so that it can be reused without
302*5331Samw  * worrying about stale contents.
303*5331Samw  */
304*5331Samw void
305*5331Samw mlsvc_release_user_info(smb_userinfo_t *user_info)
306*5331Samw {
307*5331Samw 	int i;
308*5331Samw 
309*5331Samw 	if (user_info == NULL)
310*5331Samw 		return;
311*5331Samw 
312*5331Samw 	free(user_info->name);
313*5331Samw 	free(user_info->domain_sid);
314*5331Samw 	free(user_info->domain_name);
315*5331Samw 	free(user_info->groups);
316*5331Samw 
317*5331Samw 	if (user_info->n_other_grps) {
318*5331Samw 		for (i = 0; i < user_info->n_other_grps; i++)
319*5331Samw 			free(user_info->other_grps[i].sid);
320*5331Samw 
321*5331Samw 		free(user_info->other_grps);
322*5331Samw 	}
323*5331Samw 
324*5331Samw 	free(user_info->user_sid);
325*5331Samw 	free(user_info->pgrp_sid);
326*5331Samw 	bzero(user_info, sizeof (smb_userinfo_t));
327*5331Samw }
328*5331Samw 
329*5331Samw /*
330*5331Samw  * mlsvc_setadmin_user_info
331*5331Samw  *
332*5331Samw  * Determines if the given user is the domain Administrator or a
333*5331Samw  * member of Domain Admins or Administrators group and set the
334*5331Samw  * user_info->flags accordingly.
335*5331Samw  */
336*5331Samw void
337*5331Samw mlsvc_setadmin_user_info(smb_userinfo_t *user_info)
338*5331Samw {
339*5331Samw 	nt_domain_t *domain;
340*5331Samw 	nt_group_t *grp;
341*5331Samw 	int i;
342*5331Samw 
343*5331Samw 	if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL)
344*5331Samw 		return;
345*5331Samw 
346*5331Samw 	if (!nt_sid_is_equal((nt_sid_t *)user_info->domain_sid, domain->sid))
347*5331Samw 		return;
348*5331Samw 
349*5331Samw 	if (user_info->rid == DOMAIN_USER_RID_ADMIN)
350*5331Samw 		user_info->flags |= SMB_UINFO_FLAG_DADMIN;
351*5331Samw 	else if (user_info->primary_group_rid == DOMAIN_GROUP_RID_ADMINS)
352*5331Samw 		user_info->flags |= SMB_UINFO_FLAG_DADMIN;
353*5331Samw 	else {
354*5331Samw 		for (i = 0; i < user_info->n_groups; i++)
355*5331Samw 			if (user_info->groups[i].rid == DOMAIN_GROUP_RID_ADMINS)
356*5331Samw 				user_info->flags |= SMB_UINFO_FLAG_DADMIN;
357*5331Samw 	}
358*5331Samw 
359*5331Samw 	grp = nt_group_getinfo("Administrators", RWLOCK_READER);
360*5331Samw 	if (grp) {
361*5331Samw 		i = nt_group_is_member(grp, user_info->user_sid);
362*5331Samw 		nt_group_putinfo(grp);
363*5331Samw 		if (i)
364*5331Samw 			user_info->flags |= SMB_UINFO_FLAG_LADMIN;
365*5331Samw 	}
366*5331Samw }
367*5331Samw 
368*5331Samw /*
369*5331Samw  * mlsvc_string_save
370*5331Samw  *
371*5331Samw  * This is a convenience function to prepare strings for an RPC call.
372*5331Samw  * An ms_string_t is set up with the appropriate lengths and str is
373*5331Samw  * set up to point to a copy of the original string on the heap. The
374*5331Samw  * macro MLRPC_HEAP_STRSAVE is an alias for mlrpc_heap_strsave, which
375*5331Samw  * extends the heap and copies the string into the new area.
376*5331Samw  */
377*5331Samw int
378*5331Samw mlsvc_string_save(ms_string_t *ms, char *str, struct mlrpc_xaction *mxa)
379*5331Samw {
380*5331Samw 	int length;
381*5331Samw 	char *p;
382*5331Samw 
383*5331Samw 	if (ms == NULL || str == NULL || mxa == NULL)
384*5331Samw 		return (0);
385*5331Samw 
386*5331Samw 	/*
387*5331Samw 	 * Windows NT expects the name length to exclude the
388*5331Samw 	 * terminating wchar null but doesn't care whether or
389*5331Samw 	 * not the allosize includes it. Windows 2000 insists
390*5331Samw 	 * that both the length and the allosize include the
391*5331Samw 	 * wchar null.
392*5331Samw 	 */
393*5331Samw 	length = mts_wcequiv_strlen(str);
394*5331Samw 	ms->allosize = length + sizeof (mts_wchar_t);
395*5331Samw 
396*5331Samw 	if (mxa->context->user_ctx->du_native_os == NATIVE_OS_WIN2000)
397*5331Samw 		ms->length = ms->allosize;
398*5331Samw 	else
399*5331Samw 		ms->length = length;
400*5331Samw 
401*5331Samw 	if ((p = MLRPC_HEAP_STRSAVE(mxa, str)) == NULL) {
402*5331Samw 		return (0);
403*5331Samw 	}
404*5331Samw 
405*5331Samw 	ms->str = (LPTSTR)p;
406*5331Samw 	return (1);
407*5331Samw }
408*5331Samw 
409*5331Samw /*
410*5331Samw  * mlsvc_sid_save
411*5331Samw  *
412*5331Samw  * Expand the heap and copy the sid into the new area.
413*5331Samw  * Returns a pointer to the copy of the sid on the heap.
414*5331Samw  */
415*5331Samw nt_sid_t *
416*5331Samw mlsvc_sid_save(nt_sid_t *sid, struct mlrpc_xaction *mxa)
417*5331Samw {
418*5331Samw 	nt_sid_t *heap_sid;
419*5331Samw 	unsigned size;
420*5331Samw 
421*5331Samw 	if (sid == NULL)
422*5331Samw 		return (NULL);
423*5331Samw 
424*5331Samw 	size = nt_sid_length(sid);
425*5331Samw 
426*5331Samw 	if ((heap_sid = (nt_sid_t *)MLRPC_HEAP_MALLOC(mxa, size)) == NULL)
427*5331Samw 		return (0);
428*5331Samw 
429*5331Samw 	bcopy(sid, heap_sid, size);
430*5331Samw 	return (heap_sid);
431*5331Samw }
432*5331Samw 
433*5331Samw /*
434*5331Samw  * mlsvc_is_null_handle
435*5331Samw  *
436*5331Samw  * Check a handle against a null handle. Returns 1 if the handle is
437*5331Samw  * null. Otherwise returns 0.
438*5331Samw  */
439*5331Samw int
440*5331Samw mlsvc_is_null_handle(mlsvc_handle_t *handle)
441*5331Samw {
442*5331Samw 	static ms_handle_t zero_handle;
443*5331Samw 
444*5331Samw 	if (handle == NULL || handle->context == NULL)
445*5331Samw 		return (1);
446*5331Samw 
447*5331Samw 	if (!memcmp(&handle->handle, &zero_handle, sizeof (ms_handle_t)))
448*5331Samw 		return (1);
449*5331Samw 
450*5331Samw 	return (0);
451*5331Samw }
452*5331Samw 
453*5331Samw /*
454*5331Samw  * mlsvc_validate_user
455*5331Samw  *
456*5331Samw  * Returns NT status codes.
457*5331Samw  */
458*5331Samw DWORD
459*5331Samw mlsvc_validate_user(char *server, char *domain, char *plain_user,
460*5331Samw     char *plain_text)
461*5331Samw {
462*5331Samw 	smb_auth_info_t auth;
463*5331Samw 	smb_ntdomain_t *di;
464*5331Samw 	int erc;
465*5331Samw 	DWORD status;
466*5331Samw 	mlsvc_handle_t netr_handle;
467*5331Samw 	char machine_passwd[MLSVC_MACHINE_ACCT_PASSWD_MAX];
468*5331Samw 
469*5331Samw 	machine_passwd[0] = '\0';
470*5331Samw 
471*5331Samw 	/*
472*5331Samw 	 * Ensure that the domain name is uppercase.
473*5331Samw 	 */
474*5331Samw 	(void) utf8_strupr(domain);
475*5331Samw 
476*5331Samw 	/*
477*5331Samw 	 * There is no point continuing if the domain information is
478*5331Samw 	 * not available. Wait for up to 10 seconds and then give up.
479*5331Samw 	 */
480*5331Samw 	if ((di = smb_getdomaininfo(10)) == 0) {
481*5331Samw 		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
482*5331Samw 		return (status);
483*5331Samw 	}
484*5331Samw 
485*5331Samw 	if (strcasecmp(domain, di->domain) != 0) {
486*5331Samw 		status = NT_STATUS_INVALID_PARAMETER;
487*5331Samw 		return (status);
488*5331Samw 	}
489*5331Samw 
490*5331Samw 	erc = mlsvc_user_logon(server, domain, plain_user, plain_text);
491*5331Samw 
492*5331Samw 	if (erc == AUTH_USER_GRANT) {
493*5331Samw 		int isenabled;
494*5331Samw 
495*5331Samw 		smb_config_rdlock();
496*5331Samw 		isenabled = smb_config_getyorn(SMB_CI_ADS_ENABLE);
497*5331Samw 		smb_config_unlock();
498*5331Samw 		if (isenabled) {
499*5331Samw 			if (adjoin(machine_passwd,
500*5331Samw 			    sizeof (machine_passwd)) == ADJOIN_SUCCESS) {
501*5331Samw 				status = NT_STATUS_SUCCESS;
502*5331Samw 			} else {
503*5331Samw 				status = NT_STATUS_UNSUCCESSFUL;
504*5331Samw 			}
505*5331Samw 		} else {
506*5331Samw 			/*
507*5331Samw 			 * Ensure that we don't have an old account in
508*5331Samw 			 * this domain. There's no need to check the
509*5331Samw 			 * return status.
510*5331Samw 			 */
511*5331Samw 			(void) sam_remove_trust_account(server, domain);
512*5331Samw 
513*5331Samw 			if (mlsvc_user_getauth(server, plain_user, &auth)
514*5331Samw 			    != 0) {
515*5331Samw 				status = NT_STATUS_INVALID_PARAMETER;
516*5331Samw 				return (status);
517*5331Samw 			}
518*5331Samw 
519*5331Samw 			status = sam_create_trust_account(server, domain,
520*5331Samw 			    &auth);
521*5331Samw 			if (status == NT_STATUS_SUCCESS) {
522*5331Samw 				(void) smb_gethostname(machine_passwd,
523*5331Samw 				    sizeof (machine_passwd), 0);
524*5331Samw 				(void) utf8_strlwr(machine_passwd);
525*5331Samw 			}
526*5331Samw 		}
527*5331Samw 
528*5331Samw 		if (status == NT_STATUS_SUCCESS) {
529*5331Samw 			smb_config_wrlock();
530*5331Samw 			if (smb_config_set(SMB_CI_MACHINE_PASSWD,
531*5331Samw 			    machine_passwd) != 0) {
532*5331Samw 				smb_config_unlock();
533*5331Samw 				return (NT_STATUS_UNSUCCESSFUL);
534*5331Samw 			}
535*5331Samw 			smb_config_unlock();
536*5331Samw 
537*5331Samw 			/*
538*5331Samw 			 * If we successfully create a trust account, we mark
539*5331Samw 			 * ourselves as a domain member in the environment so
540*5331Samw 			 * that we use the SAMLOGON version of the NETLOGON
541*5331Samw 			 * PDC location protocol.
542*5331Samw 			 */
543*5331Samw 			smb_set_domain_member(1);
544*5331Samw 
545*5331Samw 			if (netr_open(server, domain, &netr_handle) == 0) {
546*5331Samw 				status = netlogon_auth(server, &netr_handle,
547*5331Samw 				    NETR_FLG_INIT);
548*5331Samw 				(void) netr_close(&netr_handle);
549*5331Samw 			} else {
550*5331Samw 				status = NT_STATUS_OPEN_FAILED;
551*5331Samw 			}
552*5331Samw 		}
553*5331Samw 	} else {
554*5331Samw 		status = NT_STATUS_LOGON_FAILURE;
555*5331Samw 	}
556*5331Samw 
557*5331Samw 	return (status);
558*5331Samw }
559*5331Samw 
560*5331Samw /*ARGSUSED*/
561*5331Samw void
562*5331Samw nt_group_ht_lock(krwmode_t locktype)
563*5331Samw {
564*5331Samw }
565*5331Samw 
566*5331Samw void
567*5331Samw nt_group_ht_unlock(void)
568*5331Samw {
569*5331Samw }
570*5331Samw 
571*5331Samw int
572*5331Samw nt_group_num_groups(void)
573*5331Samw {
574*5331Samw 	return (0);
575*5331Samw }
576*5331Samw 
577*5331Samw /*ARGSUSED*/
578*5331Samw uint32_t
579*5331Samw nt_group_add(char *gname, char *comment)
580*5331Samw {
581*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
582*5331Samw }
583*5331Samw 
584*5331Samw /*ARGSUSED*/
585*5331Samw uint32_t
586*5331Samw nt_group_modify(char *gname, char *new_gname, char *comment)
587*5331Samw {
588*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
589*5331Samw }
590*5331Samw 
591*5331Samw /*ARGSUSED*/
592*5331Samw uint32_t
593*5331Samw nt_group_delete(char *gname)
594*5331Samw {
595*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
596*5331Samw }
597*5331Samw 
598*5331Samw /*ARGSUSED*/
599*5331Samw nt_group_t *
600*5331Samw nt_group_getinfo(char *gname, krwmode_t locktype)
601*5331Samw {
602*5331Samw 	return (NULL);
603*5331Samw }
604*5331Samw 
605*5331Samw /*ARGSUSED*/
606*5331Samw void
607*5331Samw nt_group_putinfo(nt_group_t *grp)
608*5331Samw {
609*5331Samw }
610*5331Samw 
611*5331Samw /*ARGSUSED*/
612*5331Samw int
613*5331Samw nt_group_getpriv(nt_group_t *grp, uint32_t priv_id)
614*5331Samw {
615*5331Samw 	return (SE_PRIVILEGE_DISABLED);
616*5331Samw }
617*5331Samw 
618*5331Samw /*ARGSUSED*/
619*5331Samw uint32_t
620*5331Samw nt_group_setpriv(nt_group_t *grp, uint32_t priv_id, uint32_t new_attr)
621*5331Samw {
622*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
623*5331Samw }
624*5331Samw 
625*5331Samw /*ARGSUSED*/
626*5331Samw int
627*5331Samw nt_group_is_member(nt_group_t *grp, nt_sid_t *sid)
628*5331Samw {
629*5331Samw 	return (0);
630*5331Samw }
631*5331Samw 
632*5331Samw /*ARGSUSED*/
633*5331Samw uint32_t
634*5331Samw nt_group_add_member(nt_group_t *grp, nt_sid_t *msid, uint16_t sid_name_use,
635*5331Samw     char *account)
636*5331Samw {
637*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
638*5331Samw }
639*5331Samw 
640*5331Samw /*ARGSUSED*/
641*5331Samw uint32_t
642*5331Samw nt_group_del_member(nt_group_t *grp, void *key, int keytype)
643*5331Samw {
644*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
645*5331Samw }
646*5331Samw 
647*5331Samw /*ARGSUSED*/
648*5331Samw int
649*5331Samw nt_group_num_members(nt_group_t *grp)
650*5331Samw {
651*5331Samw 	return (0);
652*5331Samw }
653*5331Samw 
654*5331Samw nt_group_iterator_t *
655*5331Samw nt_group_open_iterator(void)
656*5331Samw {
657*5331Samw 	return (NULL);
658*5331Samw }
659*5331Samw 
660*5331Samw /*ARGSUSED*/
661*5331Samw void
662*5331Samw nt_group_close_iterator(nt_group_iterator_t *gi)
663*5331Samw {
664*5331Samw }
665*5331Samw 
666*5331Samw /*ARGSUSED*/
667*5331Samw nt_group_t *
668*5331Samw nt_group_iterate(nt_group_iterator_t *gi)
669*5331Samw {
670*5331Samw 	return (NULL);
671*5331Samw }
672*5331Samw 
673*5331Samw int
674*5331Samw nt_group_cache_size(void)
675*5331Samw {
676*5331Samw 	return (0);
677*5331Samw }
678*5331Samw 
679*5331Samw uint32_t
680*5331Samw sam_init(void)
681*5331Samw {
682*5331Samw 	return (NT_STATUS_SUCCESS);
683*5331Samw }
684*5331Samw 
685*5331Samw /*ARGSUSED*/
686*5331Samw uint32_t
687*5331Samw nt_group_add_member_byname(char *gname, char *account)
688*5331Samw {
689*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
690*5331Samw }
691*5331Samw 
692*5331Samw /*ARGSUSED*/
693*5331Samw uint32_t
694*5331Samw nt_group_del_member_byname(nt_group_t *grp, char *member_name)
695*5331Samw {
696*5331Samw 	return (NT_STATUS_NOT_SUPPORTED);
697*5331Samw }
698*5331Samw 
699*5331Samw /*ARGSUSED*/
700*5331Samw void
701*5331Samw nt_group_add_groupprivs(nt_group_t *grp, smb_privset_t *priv)
702*5331Samw {
703*5331Samw }
704*5331Samw 
705*5331Samw /*ARGSUSED*/
706*5331Samw uint32_t
707*5331Samw nt_groups_member_privs(nt_sid_t *sid, smb_privset_t *priv)
708*5331Samw {
709*5331Samw 	return (NT_STATUS_SUCCESS);
710*5331Samw }
711*5331Samw 
712*5331Samw /*ARGSUSED*/
713*5331Samw int
714*5331Samw nt_groups_member_ngroups(nt_sid_t *sid)
715*5331Samw {
716*5331Samw 	return (0);
717*5331Samw }
718*5331Samw 
719*5331Samw /*ARGSUSED*/
720*5331Samw uint32_t
721*5331Samw nt_groups_member_groups(nt_sid_t *sid, smb_id_t *grps, int ngrps)
722*5331Samw {
723*5331Samw 	return (NT_STATUS_SUCCESS);
724*5331Samw }
725*5331Samw 
726*5331Samw /*ARGSUSED*/
727*5331Samw nt_group_t *
728*5331Samw nt_groups_lookup_rid(uint32_t rid)
729*5331Samw {
730*5331Samw 	return (NULL);
731*5331Samw }
732*5331Samw 
733*5331Samw /*ARGSUSED*/
734*5331Samw int
735*5331Samw nt_groups_count(int cnt_opt)
736*5331Samw {
737*5331Samw 	return (0);
738*5331Samw }
739*5331Samw 
740*5331Samw /*ARGSUSED*/
741*5331Samw int
742*5331Samw nt_group_member_list(int offset, nt_group_t *grp,
743*5331Samw     ntgrp_member_list_t *rmembers)
744*5331Samw {
745*5331Samw 	return (0);
746*5331Samw }
747*5331Samw 
748*5331Samw /*ARGSUSED*/
749*5331Samw void
750*5331Samw nt_group_list(int offset, char *pattern, ntgrp_list_t *list)
751*5331Samw {
752*5331Samw }
753