xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (revision 12065:0e89d02a32ea)
111337SWilliam.Krier@Sun.COM /*
211337SWilliam.Krier@Sun.COM  * CDDL HEADER START
311337SWilliam.Krier@Sun.COM  *
411337SWilliam.Krier@Sun.COM  * The contents of this file are subject to the terms of the
511337SWilliam.Krier@Sun.COM  * Common Development and Distribution License (the "License").
611337SWilliam.Krier@Sun.COM  * You may not use this file except in compliance with the License.
711337SWilliam.Krier@Sun.COM  *
811337SWilliam.Krier@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911337SWilliam.Krier@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011337SWilliam.Krier@Sun.COM  * See the License for the specific language governing permissions
1111337SWilliam.Krier@Sun.COM  * and limitations under the License.
1211337SWilliam.Krier@Sun.COM  *
1311337SWilliam.Krier@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411337SWilliam.Krier@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511337SWilliam.Krier@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611337SWilliam.Krier@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711337SWilliam.Krier@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811337SWilliam.Krier@Sun.COM  *
1911337SWilliam.Krier@Sun.COM  * CDDL HEADER END
2011337SWilliam.Krier@Sun.COM  */
2111337SWilliam.Krier@Sun.COM /*
22*12065SKeyur.Desai@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2311337SWilliam.Krier@Sun.COM  */
2411337SWilliam.Krier@Sun.COM 
2511337SWilliam.Krier@Sun.COM /*
2611337SWilliam.Krier@Sun.COM  * Security Accounts Manager RPC (SAMR) server-side interface.
2711337SWilliam.Krier@Sun.COM  *
2811337SWilliam.Krier@Sun.COM  * The SAM is a hierarchical database:
2911337SWilliam.Krier@Sun.COM  * - If you want to talk to the SAM you need a SAM handle.
3011337SWilliam.Krier@Sun.COM  * - If you want to work with a domain, use the SAM handle.
3111337SWilliam.Krier@Sun.COM  *   to obtain a domain handle.
3211337SWilliam.Krier@Sun.COM  * - Use domain handles to obtain user handles etc.
3311337SWilliam.Krier@Sun.COM  */
3411337SWilliam.Krier@Sun.COM 
3511337SWilliam.Krier@Sun.COM #include <strings.h>
3611337SWilliam.Krier@Sun.COM #include <unistd.h>
3711337SWilliam.Krier@Sun.COM #include <netdb.h>
3811337SWilliam.Krier@Sun.COM #include <assert.h>
39*12065SKeyur.Desai@Sun.COM #include <grp.h>
4011337SWilliam.Krier@Sun.COM #include <smbsrv/libsmb.h>
4111337SWilliam.Krier@Sun.COM #include <smbsrv/libmlrpc.h>
4211337SWilliam.Krier@Sun.COM #include <smbsrv/libmlsvc.h>
4311337SWilliam.Krier@Sun.COM #include <smbsrv/ntstatus.h>
4411337SWilliam.Krier@Sun.COM #include <smbsrv/nterror.h>
4511337SWilliam.Krier@Sun.COM #include <smbsrv/smbinfo.h>
4611337SWilliam.Krier@Sun.COM #include <smbsrv/nmpipes.h>
4711337SWilliam.Krier@Sun.COM #include <smbsrv/ndl/samrpc.ndl>
4811337SWilliam.Krier@Sun.COM #include <samlib.h>
4911337SWilliam.Krier@Sun.COM 
5011337SWilliam.Krier@Sun.COM /*
5111337SWilliam.Krier@Sun.COM  * The keys associated with the various handles dispensed by the SAMR
5211337SWilliam.Krier@Sun.COM  * server.  These keys can be used to validate client activity.
5311337SWilliam.Krier@Sun.COM  * These values are never passed over the wire so security shouldn't
5411337SWilliam.Krier@Sun.COM  * be an issue.
5511337SWilliam.Krier@Sun.COM  */
5611337SWilliam.Krier@Sun.COM typedef enum {
5711337SWilliam.Krier@Sun.COM 	SAMR_KEY_NULL = 0,
5811337SWilliam.Krier@Sun.COM 	SAMR_KEY_CONNECT,
5911337SWilliam.Krier@Sun.COM 	SAMR_KEY_DOMAIN,
6011337SWilliam.Krier@Sun.COM 	SAMR_KEY_USER,
6111337SWilliam.Krier@Sun.COM 	SAMR_KEY_GROUP,
6211337SWilliam.Krier@Sun.COM 	SAMR_KEY_ALIAS
6311337SWilliam.Krier@Sun.COM } samr_key_t;
6411337SWilliam.Krier@Sun.COM 
6511337SWilliam.Krier@Sun.COM typedef struct samr_keydata {
6611337SWilliam.Krier@Sun.COM 	samr_key_t kd_key;
6711337SWilliam.Krier@Sun.COM 	smb_domain_type_t kd_type;
6811337SWilliam.Krier@Sun.COM 	DWORD kd_rid;
6911337SWilliam.Krier@Sun.COM } samr_keydata_t;
7011337SWilliam.Krier@Sun.COM 
7111337SWilliam.Krier@Sun.COM /*
7211337SWilliam.Krier@Sun.COM  * DomainDisplayUser	All user objects (or those derived from user) with
7311337SWilliam.Krier@Sun.COM  * 			userAccountControl containing the UF_NORMAL_ACCOUNT bit.
7411337SWilliam.Krier@Sun.COM  *
7511337SWilliam.Krier@Sun.COM  * DomainDisplayMachine	All user objects (or those derived from user) with
7611337SWilliam.Krier@Sun.COM  * 			userAccountControl containing the
7711337SWilliam.Krier@Sun.COM  * 			UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
7811337SWilliam.Krier@Sun.COM  * 			bit.
7911337SWilliam.Krier@Sun.COM  *
8011337SWilliam.Krier@Sun.COM  * DomainDisplayGroup	All group objects (or those derived from group) with
8111337SWilliam.Krier@Sun.COM  * 			groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
8211337SWilliam.Krier@Sun.COM  * 			GROUP_TYPE_SECURITY_ACCOUNT.
8311337SWilliam.Krier@Sun.COM  *
8411337SWilliam.Krier@Sun.COM  * DomainDisplayOemUser	Same as DomainDisplayUser with OEM strings
8511337SWilliam.Krier@Sun.COM  *
8611337SWilliam.Krier@Sun.COM  * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
8711337SWilliam.Krier@Sun.COM  */
8811337SWilliam.Krier@Sun.COM typedef enum {
8911337SWilliam.Krier@Sun.COM 	DomainDisplayUser = 1,
9011337SWilliam.Krier@Sun.COM 	DomainDisplayMachine,
9111337SWilliam.Krier@Sun.COM 	DomainDispalyGroup,
9211337SWilliam.Krier@Sun.COM 	DomainDisplayOemUser,
9311337SWilliam.Krier@Sun.COM 	DomainDisplayOemGroup
9411337SWilliam.Krier@Sun.COM } samr_displvl_t;
9511337SWilliam.Krier@Sun.COM 
9611337SWilliam.Krier@Sun.COM #define	SAMR_VALID_DISPLEVEL(lvl) \
9711337SWilliam.Krier@Sun.COM 	(((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
9811337SWilliam.Krier@Sun.COM 
9911337SWilliam.Krier@Sun.COM #define	SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
10011337SWilliam.Krier@Sun.COM 
10111337SWilliam.Krier@Sun.COM static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
10211337SWilliam.Krier@Sun.COM     DWORD);
10311337SWilliam.Krier@Sun.COM static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
10411337SWilliam.Krier@Sun.COM static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
10511337SWilliam.Krier@Sun.COM static int samr_call_stub(ndr_xa_t *mxa);
10611337SWilliam.Krier@Sun.COM static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
10711337SWilliam.Krier@Sun.COM     ndr_xa_t *);
10811337SWilliam.Krier@Sun.COM 
10911337SWilliam.Krier@Sun.COM static ndr_stub_table_t samr_stub_table[];
11011337SWilliam.Krier@Sun.COM 
11111337SWilliam.Krier@Sun.COM static ndr_service_t samr_service = {
11211337SWilliam.Krier@Sun.COM 	"SAMR",				/* name */
11311337SWilliam.Krier@Sun.COM 	"Security Accounts Manager",	/* desc */
11411337SWilliam.Krier@Sun.COM 	"\\samr",			/* endpoint */
11511337SWilliam.Krier@Sun.COM 	PIPE_LSASS,			/* sec_addr_port */
11611337SWilliam.Krier@Sun.COM 	"12345778-1234-abcd-ef00-0123456789ac", 1,	/* abstract */
11711337SWilliam.Krier@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
11811337SWilliam.Krier@Sun.COM 	0,				/* no bind_instance_size */
11911337SWilliam.Krier@Sun.COM 	NULL,				/* no bind_req() */
12011337SWilliam.Krier@Sun.COM 	NULL,				/* no unbind_and_close() */
12111337SWilliam.Krier@Sun.COM 	samr_call_stub,			/* call_stub() */
12211337SWilliam.Krier@Sun.COM 	&TYPEINFO(samr_interface),	/* interface ti */
12311337SWilliam.Krier@Sun.COM 	samr_stub_table			/* stub_table */
12411337SWilliam.Krier@Sun.COM };
12511337SWilliam.Krier@Sun.COM 
12611337SWilliam.Krier@Sun.COM /*
12711337SWilliam.Krier@Sun.COM  * samr_initialize
12811337SWilliam.Krier@Sun.COM  *
12911337SWilliam.Krier@Sun.COM  * This function registers the SAM RPC interface with the RPC runtime
13011337SWilliam.Krier@Sun.COM  * library. It must be called in order to use either the client side
13111337SWilliam.Krier@Sun.COM  * or the server side functions.
13211337SWilliam.Krier@Sun.COM  */
13311337SWilliam.Krier@Sun.COM void
13411337SWilliam.Krier@Sun.COM samr_initialize(void)
13511337SWilliam.Krier@Sun.COM {
13611337SWilliam.Krier@Sun.COM 	(void) ndr_svc_register(&samr_service);
13711337SWilliam.Krier@Sun.COM }
13811337SWilliam.Krier@Sun.COM 
13911337SWilliam.Krier@Sun.COM /*
14011337SWilliam.Krier@Sun.COM  * Custom call_stub to set the stream string policy.
14111337SWilliam.Krier@Sun.COM  */
14211337SWilliam.Krier@Sun.COM static int
14311337SWilliam.Krier@Sun.COM samr_call_stub(ndr_xa_t *mxa)
14411337SWilliam.Krier@Sun.COM {
14511337SWilliam.Krier@Sun.COM 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
14611337SWilliam.Krier@Sun.COM 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
14711337SWilliam.Krier@Sun.COM 
14811337SWilliam.Krier@Sun.COM 	return (ndr_generic_call_stub(mxa));
14911337SWilliam.Krier@Sun.COM }
15011337SWilliam.Krier@Sun.COM 
15111337SWilliam.Krier@Sun.COM /*
15211337SWilliam.Krier@Sun.COM  * Handle allocation wrapper to setup the local context.
15311337SWilliam.Krier@Sun.COM  */
15411337SWilliam.Krier@Sun.COM static ndr_hdid_t *
15511337SWilliam.Krier@Sun.COM samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
15611337SWilliam.Krier@Sun.COM     DWORD rid)
15711337SWilliam.Krier@Sun.COM {
15811963SAfshin.Ardakani@Sun.COM 	ndr_handle_t	*hd;
15911963SAfshin.Ardakani@Sun.COM 	ndr_hdid_t	*id;
16011963SAfshin.Ardakani@Sun.COM 	samr_keydata_t	*data;
16111337SWilliam.Krier@Sun.COM 
16211337SWilliam.Krier@Sun.COM 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
16311337SWilliam.Krier@Sun.COM 		return (NULL);
16411337SWilliam.Krier@Sun.COM 
16511337SWilliam.Krier@Sun.COM 	data->kd_key = key;
16611337SWilliam.Krier@Sun.COM 	data->kd_type = domain_type;
16711337SWilliam.Krier@Sun.COM 	data->kd_rid = rid;
16811337SWilliam.Krier@Sun.COM 
16911963SAfshin.Ardakani@Sun.COM 	if ((id = ndr_hdalloc(mxa, data)) == NULL) {
17011963SAfshin.Ardakani@Sun.COM 		free(data);
17111963SAfshin.Ardakani@Sun.COM 		return (NULL);
17211963SAfshin.Ardakani@Sun.COM 	}
17311963SAfshin.Ardakani@Sun.COM 
17411963SAfshin.Ardakani@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
17511963SAfshin.Ardakani@Sun.COM 		hd->nh_data_free = free;
17611963SAfshin.Ardakani@Sun.COM 
17711963SAfshin.Ardakani@Sun.COM 	return (id);
17811337SWilliam.Krier@Sun.COM }
17911337SWilliam.Krier@Sun.COM 
18011337SWilliam.Krier@Sun.COM /*
18111337SWilliam.Krier@Sun.COM  * Handle deallocation wrapper to free the local context.
18211337SWilliam.Krier@Sun.COM  */
18311337SWilliam.Krier@Sun.COM static void
18411337SWilliam.Krier@Sun.COM samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
18511337SWilliam.Krier@Sun.COM {
18611337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
18711337SWilliam.Krier@Sun.COM 
18811337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
18911337SWilliam.Krier@Sun.COM 		free(hd->nh_data);
19011963SAfshin.Ardakani@Sun.COM 		hd->nh_data = NULL;
19111337SWilliam.Krier@Sun.COM 		ndr_hdfree(mxa, id);
19211337SWilliam.Krier@Sun.COM 	}
19311337SWilliam.Krier@Sun.COM }
19411337SWilliam.Krier@Sun.COM 
19511337SWilliam.Krier@Sun.COM /*
19611337SWilliam.Krier@Sun.COM  * Handle lookup wrapper to validate the local context.
19711337SWilliam.Krier@Sun.COM  */
19811337SWilliam.Krier@Sun.COM static ndr_handle_t *
19911337SWilliam.Krier@Sun.COM samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
20011337SWilliam.Krier@Sun.COM {
20111337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
20211337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
20311337SWilliam.Krier@Sun.COM 
20411337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
20511337SWilliam.Krier@Sun.COM 		return (NULL);
20611337SWilliam.Krier@Sun.COM 
20711337SWilliam.Krier@Sun.COM 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
20811337SWilliam.Krier@Sun.COM 		return (NULL);
20911337SWilliam.Krier@Sun.COM 
21011337SWilliam.Krier@Sun.COM 	if (data->kd_key != key)
21111337SWilliam.Krier@Sun.COM 		return (NULL);
21211337SWilliam.Krier@Sun.COM 
21311337SWilliam.Krier@Sun.COM 	return (hd);
21411337SWilliam.Krier@Sun.COM }
21511337SWilliam.Krier@Sun.COM 
21611337SWilliam.Krier@Sun.COM /*
21711337SWilliam.Krier@Sun.COM  * samr_s_ConnectAnon
21811337SWilliam.Krier@Sun.COM  *
21911337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database. We don't
22011337SWilliam.Krier@Sun.COM  * support any form of update request and our database doesn't
22111337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in
22211337SWilliam.Krier@Sun.COM  * doing any access access checking here.
22311337SWilliam.Krier@Sun.COM  *
22411337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
22511337SWilliam.Krier@Sun.COM  */
22611337SWilliam.Krier@Sun.COM static int
22711337SWilliam.Krier@Sun.COM samr_s_ConnectAnon(void *arg, ndr_xa_t *mxa)
22811337SWilliam.Krier@Sun.COM {
22911337SWilliam.Krier@Sun.COM 	struct samr_ConnectAnon *param = arg;
23011337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
23111337SWilliam.Krier@Sun.COM 
23211337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
23311337SWilliam.Krier@Sun.COM 	if (id) {
23411337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
23511337SWilliam.Krier@Sun.COM 		param->status = 0;
23611337SWilliam.Krier@Sun.COM 	} else {
23711337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
23811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
23911337SWilliam.Krier@Sun.COM 	}
24011337SWilliam.Krier@Sun.COM 
24111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
24211337SWilliam.Krier@Sun.COM }
24311337SWilliam.Krier@Sun.COM 
24411337SWilliam.Krier@Sun.COM /*
24511337SWilliam.Krier@Sun.COM  * samr_s_CloseHandle
24611337SWilliam.Krier@Sun.COM  *
24711337SWilliam.Krier@Sun.COM  * Close the SAM interface specified by the handle.
24811337SWilliam.Krier@Sun.COM  * Free the handle and zero out the result handle for the client.
24911337SWilliam.Krier@Sun.COM  */
25011337SWilliam.Krier@Sun.COM static int
25111337SWilliam.Krier@Sun.COM samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
25211337SWilliam.Krier@Sun.COM {
25311337SWilliam.Krier@Sun.COM 	struct samr_CloseHandle *param = arg;
25411337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
25511337SWilliam.Krier@Sun.COM 
25611337SWilliam.Krier@Sun.COM 	samr_hdfree(mxa, id);
25711337SWilliam.Krier@Sun.COM 
25811337SWilliam.Krier@Sun.COM 	bzero(&param->result_handle, sizeof (samr_handle_t));
25911337SWilliam.Krier@Sun.COM 	param->status = 0;
26011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
26111337SWilliam.Krier@Sun.COM }
26211337SWilliam.Krier@Sun.COM 
26311337SWilliam.Krier@Sun.COM /*
26411337SWilliam.Krier@Sun.COM  * samr_s_LookupDomain
26511337SWilliam.Krier@Sun.COM  *
26611337SWilliam.Krier@Sun.COM  * This is a request to map a domain name to a domain SID. We can map
26711337SWilliam.Krier@Sun.COM  * the primary domain name, our local domain name (hostname) and the
26811337SWilliam.Krier@Sun.COM  * builtin domain names to the appropriate SID. Anything else will be
26911337SWilliam.Krier@Sun.COM  * rejected.
27011337SWilliam.Krier@Sun.COM  */
27111337SWilliam.Krier@Sun.COM static int
27211337SWilliam.Krier@Sun.COM samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
27311337SWilliam.Krier@Sun.COM {
27411337SWilliam.Krier@Sun.COM 	struct samr_LookupDomain *param = arg;
27511337SWilliam.Krier@Sun.COM 	char *domain_name;
27611337SWilliam.Krier@Sun.COM 	smb_domain_t di;
27711337SWilliam.Krier@Sun.COM 
27811337SWilliam.Krier@Sun.COM 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
27911337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
28011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
28111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
28211337SWilliam.Krier@Sun.COM 	}
28311337SWilliam.Krier@Sun.COM 
28411337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_name(domain_name, &di)) {
28511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
28611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
28711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
28811337SWilliam.Krier@Sun.COM 	}
28911337SWilliam.Krier@Sun.COM 
29011337SWilliam.Krier@Sun.COM 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
29111337SWilliam.Krier@Sun.COM 	if (param->sid == NULL) {
29211337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
29311337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
29411337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
29511337SWilliam.Krier@Sun.COM 	}
29611337SWilliam.Krier@Sun.COM 
29711337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
29811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
29911337SWilliam.Krier@Sun.COM }
30011337SWilliam.Krier@Sun.COM 
30111337SWilliam.Krier@Sun.COM /*
30211337SWilliam.Krier@Sun.COM  * samr_s_EnumLocalDomains
30311337SWilliam.Krier@Sun.COM  *
30411337SWilliam.Krier@Sun.COM  * This is a request for the local domains supported by this server.
30511337SWilliam.Krier@Sun.COM  * All we do here is validate the handle and set the status. The real
30611337SWilliam.Krier@Sun.COM  * work is done in samr_s_enum_local_domains.
30711337SWilliam.Krier@Sun.COM  */
30811337SWilliam.Krier@Sun.COM static int
30911337SWilliam.Krier@Sun.COM samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
31011337SWilliam.Krier@Sun.COM {
31111337SWilliam.Krier@Sun.COM 	struct samr_EnumLocalDomain *param = arg;
31211337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
31311337SWilliam.Krier@Sun.COM 	DWORD status;
31411337SWilliam.Krier@Sun.COM 
31511337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
31611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
31711337SWilliam.Krier@Sun.COM 	else
31811337SWilliam.Krier@Sun.COM 		status = samr_s_enum_local_domains(param, mxa);
31911337SWilliam.Krier@Sun.COM 
32011337SWilliam.Krier@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
32111337SWilliam.Krier@Sun.COM 		param->enum_context = param->info->entries_read;
32211337SWilliam.Krier@Sun.COM 		param->total_entries = param->info->entries_read;
32311337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
32411337SWilliam.Krier@Sun.COM 	} else {
32511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumLocalDomain));
32611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
32711337SWilliam.Krier@Sun.COM 	}
32811337SWilliam.Krier@Sun.COM 
32911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
33011337SWilliam.Krier@Sun.COM }
33111337SWilliam.Krier@Sun.COM 
33211337SWilliam.Krier@Sun.COM 
33311337SWilliam.Krier@Sun.COM /*
33411337SWilliam.Krier@Sun.COM  * samr_s_enum_local_domains
33511337SWilliam.Krier@Sun.COM  *
33611337SWilliam.Krier@Sun.COM  * This function should only be called via samr_s_EnumLocalDomains to
33711337SWilliam.Krier@Sun.COM  * ensure that the appropriate validation is performed. We will answer
33811337SWilliam.Krier@Sun.COM  * queries about two domains: the local domain, synonymous with the
33911337SWilliam.Krier@Sun.COM  * local hostname, and the BUILTIN domain. So we return these two
34011337SWilliam.Krier@Sun.COM  * strings.
34111337SWilliam.Krier@Sun.COM  *
34211337SWilliam.Krier@Sun.COM  * Returns NT status values.
34311337SWilliam.Krier@Sun.COM  */
34411337SWilliam.Krier@Sun.COM static DWORD
34511337SWilliam.Krier@Sun.COM samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
34611337SWilliam.Krier@Sun.COM     ndr_xa_t *mxa)
34711337SWilliam.Krier@Sun.COM {
34811337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainInfo *info;
34911337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainEntry *entry;
35011337SWilliam.Krier@Sun.COM 	char *hostname;
35111337SWilliam.Krier@Sun.COM 
35211337SWilliam.Krier@Sun.COM 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
35311337SWilliam.Krier@Sun.COM 	if (hostname == NULL)
35411337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
35511337SWilliam.Krier@Sun.COM 
35611337SWilliam.Krier@Sun.COM 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
35711337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
35811337SWilliam.Krier@Sun.COM 
35911337SWilliam.Krier@Sun.COM 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
36011337SWilliam.Krier@Sun.COM 	if (entry == NULL)
36111337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
36211337SWilliam.Krier@Sun.COM 
36311337SWilliam.Krier@Sun.COM 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
36411337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
36511337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
36611337SWilliam.Krier@Sun.COM 
36711337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
36811337SWilliam.Krier@Sun.COM 	if (info == NULL)
36911337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
37011337SWilliam.Krier@Sun.COM 
37111337SWilliam.Krier@Sun.COM 	info->entries_read = 2;
37211337SWilliam.Krier@Sun.COM 	info->entry = entry;
37311337SWilliam.Krier@Sun.COM 	param->info = info;
37411337SWilliam.Krier@Sun.COM 	return (NT_STATUS_SUCCESS);
37511337SWilliam.Krier@Sun.COM }
37611337SWilliam.Krier@Sun.COM 
37711337SWilliam.Krier@Sun.COM /*
37811337SWilliam.Krier@Sun.COM  * samr_s_OpenDomain
37911337SWilliam.Krier@Sun.COM  *
38011337SWilliam.Krier@Sun.COM  * This is a request to open a domain within the local SAM database.
38111337SWilliam.Krier@Sun.COM  * The caller must supply a valid connect handle.
38211337SWilliam.Krier@Sun.COM  * We return a handle to be used to access objects within this domain.
38311337SWilliam.Krier@Sun.COM  */
38411337SWilliam.Krier@Sun.COM static int
38511337SWilliam.Krier@Sun.COM samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
38611337SWilliam.Krier@Sun.COM {
38711337SWilliam.Krier@Sun.COM 	struct samr_OpenDomain *param = arg;
38811337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
38911337SWilliam.Krier@Sun.COM 	smb_domain_t domain;
39011337SWilliam.Krier@Sun.COM 
39111337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
39211337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
39311337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
39411337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
39511337SWilliam.Krier@Sun.COM 	}
39611337SWilliam.Krier@Sun.COM 
39711337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
39811337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
39911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
40011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
40111337SWilliam.Krier@Sun.COM 	}
40211337SWilliam.Krier@Sun.COM 
40311337SWilliam.Krier@Sun.COM 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
40411337SWilliam.Krier@Sun.COM 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
40511337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
40611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
40711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
40811337SWilliam.Krier@Sun.COM 	}
40911337SWilliam.Krier@Sun.COM 
41011337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
41111337SWilliam.Krier@Sun.COM 	if (id) {
41211337SWilliam.Krier@Sun.COM 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
41311337SWilliam.Krier@Sun.COM 		param->status = 0;
41411337SWilliam.Krier@Sun.COM 	} else {
41511337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
41611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
41711337SWilliam.Krier@Sun.COM 	}
41811337SWilliam.Krier@Sun.COM 
41911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
42011337SWilliam.Krier@Sun.COM }
42111337SWilliam.Krier@Sun.COM 
42211337SWilliam.Krier@Sun.COM /*
42311337SWilliam.Krier@Sun.COM  * samr_s_QueryDomainInfo
42411337SWilliam.Krier@Sun.COM  *
42511337SWilliam.Krier@Sun.COM  * The caller should pass a domain handle.
42611337SWilliam.Krier@Sun.COM  *
42711337SWilliam.Krier@Sun.COM  * Windows 95 Server Manager sends requests for levels 6 and 7 when
42811337SWilliam.Krier@Sun.COM  * the services menu item is selected. Level 2 is basically for getting
42911337SWilliam.Krier@Sun.COM  * number of users, groups, and aliases in a domain.
43011337SWilliam.Krier@Sun.COM  * We have no information on what the various information levels mean.
43111337SWilliam.Krier@Sun.COM  */
43211337SWilliam.Krier@Sun.COM static int
43311337SWilliam.Krier@Sun.COM samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
43411337SWilliam.Krier@Sun.COM {
43511337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfo *param = arg;
43611337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfoRes *info;
43711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
43811337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
43911337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
44011337SWilliam.Krier@Sun.COM 	char *domain;
44111337SWilliam.Krier@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
44211337SWilliam.Krier@Sun.COM 	int alias_cnt, user_cnt;
44311337SWilliam.Krier@Sun.COM 	int rc = 0;
44411337SWilliam.Krier@Sun.COM 
44511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
44611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
44711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
44811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
44911337SWilliam.Krier@Sun.COM 	}
45011337SWilliam.Krier@Sun.COM 
45111337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
45211337SWilliam.Krier@Sun.COM 	if (info == NULL) {
45311337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
45411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
45511337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
45611337SWilliam.Krier@Sun.COM 	}
45711337SWilliam.Krier@Sun.COM 	info->switch_value = param->info_level;
45811337SWilliam.Krier@Sun.COM 	param->info = info;
45911337SWilliam.Krier@Sun.COM 
46011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
46111337SWilliam.Krier@Sun.COM 
46211337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
46311337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
46411337SWilliam.Krier@Sun.COM 		domain = "BUILTIN";
46511337SWilliam.Krier@Sun.COM 		user_cnt = 0;
46611337SWilliam.Krier@Sun.COM 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
46711337SWilliam.Krier@Sun.COM 		break;
46811337SWilliam.Krier@Sun.COM 
46911337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
47011337SWilliam.Krier@Sun.COM 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
47111337SWilliam.Krier@Sun.COM 		if (rc == 0) {
47211337SWilliam.Krier@Sun.COM 			domain = hostname;
47311337SWilliam.Krier@Sun.COM 			user_cnt = smb_sam_usr_cnt();
47411337SWilliam.Krier@Sun.COM 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
47511337SWilliam.Krier@Sun.COM 		}
47611337SWilliam.Krier@Sun.COM 		break;
47711337SWilliam.Krier@Sun.COM 
47811337SWilliam.Krier@Sun.COM 	default:
47911337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
48011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
48111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
48211337SWilliam.Krier@Sun.COM 	}
48311337SWilliam.Krier@Sun.COM 
48411337SWilliam.Krier@Sun.COM 	if (rc != 0) {
48511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
48611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
48711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
48811337SWilliam.Krier@Sun.COM 	}
48911337SWilliam.Krier@Sun.COM 
49011337SWilliam.Krier@Sun.COM 	switch (param->info_level) {
49111337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_6:
49211337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown1 = 0x00000000;
49311337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown2 = 0x00147FB0;
49411337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown3 = 0x00000000;
49511337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown4 = 0x00000000;
49611337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown5 = 0x00000000;
49711337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
49811337SWilliam.Krier@Sun.COM 		break;
49911337SWilliam.Krier@Sun.COM 
50011337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_7:
50111337SWilliam.Krier@Sun.COM 		info->ru.info7.unknown1 = 0x00000003;
50211337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
50311337SWilliam.Krier@Sun.COM 		break;
50411337SWilliam.Krier@Sun.COM 
50511337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_2:
50611337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown1 = 0x00000000;
50711337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown2 = 0x80000000;
50811337SWilliam.Krier@Sun.COM 
50911337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
51011337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s1));
51111337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, domain,
51211337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.domain));
51311337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
51411337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s2));
51511337SWilliam.Krier@Sun.COM 
51611337SWilliam.Krier@Sun.COM 		info->ru.info2.sequence_num = 0x0000002B;
51711337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown3 = 0x00000000;
51811337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown4 = 0x00000001;
51911337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown5 = 0x00000003;
52011337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown6 = 0x00000001;
52111337SWilliam.Krier@Sun.COM 		info->ru.info2.num_users = user_cnt;
52211337SWilliam.Krier@Sun.COM 		info->ru.info2.num_groups = 0;
52311337SWilliam.Krier@Sun.COM 		info->ru.info2.num_aliases = alias_cnt;
52411337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
52511337SWilliam.Krier@Sun.COM 		break;
52611337SWilliam.Krier@Sun.COM 
52711337SWilliam.Krier@Sun.COM 	default:
52811337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
52911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
53011337SWilliam.Krier@Sun.COM 	};
53111337SWilliam.Krier@Sun.COM 
53211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
53311337SWilliam.Krier@Sun.COM }
53411337SWilliam.Krier@Sun.COM 
53511337SWilliam.Krier@Sun.COM /*
53611447Samw@Sun.COM  * QueryInfoDomain2: Identical to QueryDomainInfo.
53711447Samw@Sun.COM  */
53811447Samw@Sun.COM static int
53911447Samw@Sun.COM samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
54011447Samw@Sun.COM {
54111447Samw@Sun.COM 	return (samr_s_QueryDomainInfo(arg, mxa));
54211447Samw@Sun.COM }
54311447Samw@Sun.COM 
54411447Samw@Sun.COM /*
54511337SWilliam.Krier@Sun.COM  * Looks up the given name in the specified domain which could
54611337SWilliam.Krier@Sun.COM  * be either the built-in or local domain.
54711337SWilliam.Krier@Sun.COM  *
54811337SWilliam.Krier@Sun.COM  * CAVEAT: this function should be able to handle a list of
54911337SWilliam.Krier@Sun.COM  * names but currently it can only handle one name at a time.
55011337SWilliam.Krier@Sun.COM  */
55111337SWilliam.Krier@Sun.COM static int
55211337SWilliam.Krier@Sun.COM samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
55311337SWilliam.Krier@Sun.COM {
55411337SWilliam.Krier@Sun.COM 	struct samr_LookupNames *param = arg;
55511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
55611337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
55711337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
55811337SWilliam.Krier@Sun.COM 	smb_account_t account;
55911337SWilliam.Krier@Sun.COM 	smb_wka_t *wka;
56011337SWilliam.Krier@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
56111337SWilliam.Krier@Sun.COM 
56211337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
56311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
56411337SWilliam.Krier@Sun.COM 
56511337SWilliam.Krier@Sun.COM 	if (param->n_entry != 1)
56611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
56711337SWilliam.Krier@Sun.COM 
56811337SWilliam.Krier@Sun.COM 	if (param->name.str == NULL) {
56911337SWilliam.Krier@Sun.COM 		/*
57011337SWilliam.Krier@Sun.COM 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
57111337SWilliam.Krier@Sun.COM 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
57211337SWilliam.Krier@Sun.COM 		 */
57311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NONE_MAPPED;
57411337SWilliam.Krier@Sun.COM 	}
57511337SWilliam.Krier@Sun.COM 
57611337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
57711337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
57811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
57911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
58011337SWilliam.Krier@Sun.COM 	}
58111337SWilliam.Krier@Sun.COM 
58211337SWilliam.Krier@Sun.COM 	param->rids.rid = NDR_NEW(mxa, DWORD);
58311337SWilliam.Krier@Sun.COM 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
58411337SWilliam.Krier@Sun.COM 
58511337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
58611337SWilliam.Krier@Sun.COM 
58711337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
58811337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
58911447Samw@Sun.COM 		wka = smb_wka_lookup_builtin((char *)param->name.str);
59011337SWilliam.Krier@Sun.COM 		if (wka != NULL) {
59111337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
59211337SWilliam.Krier@Sun.COM 			(void) smb_sid_getrid(wka->wka_binsid,
59311337SWilliam.Krier@Sun.COM 			    &param->rids.rid[0]);
59411337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
59511337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = wka->wka_type;
59611337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
59711337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
59811337SWilliam.Krier@Sun.COM 		}
59911337SWilliam.Krier@Sun.COM 		break;
60011337SWilliam.Krier@Sun.COM 
60111337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
60211337SWilliam.Krier@Sun.COM 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
60311337SWilliam.Krier@Sun.COM 		    SidTypeUnknown, &account);
60411337SWilliam.Krier@Sun.COM 		if (status == NT_STATUS_SUCCESS) {
60511337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
60611337SWilliam.Krier@Sun.COM 			param->rids.rid[0] = account.a_rid;
60711337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
60811337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = account.a_type;
60911337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
61011337SWilliam.Krier@Sun.COM 			smb_account_free(&account);
61111337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
61211337SWilliam.Krier@Sun.COM 		}
61311337SWilliam.Krier@Sun.COM 		break;
61411337SWilliam.Krier@Sun.COM 
61511337SWilliam.Krier@Sun.COM 	default:
61611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
61711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
61811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
61911337SWilliam.Krier@Sun.COM 	}
62011337SWilliam.Krier@Sun.COM 
62111337SWilliam.Krier@Sun.COM 	param->rids.n_entry = 0;
62211337SWilliam.Krier@Sun.COM 	param->rid_types.n_entry = 0;
62311337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
62411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
62511337SWilliam.Krier@Sun.COM }
62611337SWilliam.Krier@Sun.COM 
62711337SWilliam.Krier@Sun.COM /*
62811337SWilliam.Krier@Sun.COM  * samr_s_OpenUser
62911337SWilliam.Krier@Sun.COM  *
63011337SWilliam.Krier@Sun.COM  * This is a request to open a user within a specified domain in the
63111337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
63211337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The user is
63311337SWilliam.Krier@Sun.COM  * specified by the rid in the request.
63411337SWilliam.Krier@Sun.COM  */
63511337SWilliam.Krier@Sun.COM static int
63611337SWilliam.Krier@Sun.COM samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
63711337SWilliam.Krier@Sun.COM {
63811337SWilliam.Krier@Sun.COM 	struct samr_OpenUser *param = arg;
63911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
64011337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
64111337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
64211337SWilliam.Krier@Sun.COM 
64311337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
64411337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
64511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
64611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
64711337SWilliam.Krier@Sun.COM 	}
64811337SWilliam.Krier@Sun.COM 
64911337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
65011337SWilliam.Krier@Sun.COM 
65111337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
65211337SWilliam.Krier@Sun.COM 	if (id == NULL) {
65311337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
65411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
65511337SWilliam.Krier@Sun.COM 	} else {
65611337SWilliam.Krier@Sun.COM 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
65711337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
65811337SWilliam.Krier@Sun.COM 	}
65911337SWilliam.Krier@Sun.COM 
66011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
66111337SWilliam.Krier@Sun.COM }
66211337SWilliam.Krier@Sun.COM 
66311337SWilliam.Krier@Sun.COM /*
66411337SWilliam.Krier@Sun.COM  * samr_s_DeleteUser
66511337SWilliam.Krier@Sun.COM  *
66611337SWilliam.Krier@Sun.COM  * Request to delete a user within a specified domain in the local
66711337SWilliam.Krier@Sun.COM  * SAM database.  The caller should supply a valid user handle.
66811337SWilliam.Krier@Sun.COM  */
66911337SWilliam.Krier@Sun.COM /*ARGSUSED*/
67011337SWilliam.Krier@Sun.COM static int
67111337SWilliam.Krier@Sun.COM samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
67211337SWilliam.Krier@Sun.COM {
67311337SWilliam.Krier@Sun.COM 	struct samr_DeleteUser *param = arg;
67411337SWilliam.Krier@Sun.COM 
67511337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_DeleteUser));
67611337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
67711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
67811337SWilliam.Krier@Sun.COM }
67911337SWilliam.Krier@Sun.COM 
68011337SWilliam.Krier@Sun.COM /*
68111337SWilliam.Krier@Sun.COM  * samr_s_QueryUserInfo
68211337SWilliam.Krier@Sun.COM  *
68311337SWilliam.Krier@Sun.COM  * Returns:
68411337SWilliam.Krier@Sun.COM  * NT_STATUS_SUCCESS
68511337SWilliam.Krier@Sun.COM  * NT_STATUS_ACCESS_DENIED
68611337SWilliam.Krier@Sun.COM  * NT_STATUS_INVALID_INFO_CLASS
68711337SWilliam.Krier@Sun.COM  */
68811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
68911337SWilliam.Krier@Sun.COM static int
69011337SWilliam.Krier@Sun.COM samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
69111337SWilliam.Krier@Sun.COM {
69211337SWilliam.Krier@Sun.COM 	static uint16_t			owf_buf[8];
69311337SWilliam.Krier@Sun.COM 	static uint8_t			hour_buf[SAMR_SET_USER_HOURS_SZ];
69411337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo	*param = arg;
69511337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo21	*all_info;
69611337SWilliam.Krier@Sun.COM 	ndr_hdid_t			*id;
69711337SWilliam.Krier@Sun.COM 	ndr_handle_t			*hd;
69811337SWilliam.Krier@Sun.COM 	samr_keydata_t			*data;
69911337SWilliam.Krier@Sun.COM 	smb_domain_t			di;
70011337SWilliam.Krier@Sun.COM 	smb_account_t			account;
70111337SWilliam.Krier@Sun.COM 	smb_sid_t			*sid;
70211337SWilliam.Krier@Sun.COM 	uint32_t			status;
70311337SWilliam.Krier@Sun.COM 
70411337SWilliam.Krier@Sun.COM 	id = (ndr_hdid_t *)&param->user_handle;
70511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
70611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
70711337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
70811337SWilliam.Krier@Sun.COM 	}
70911337SWilliam.Krier@Sun.COM 
71011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
71111337SWilliam.Krier@Sun.COM 
71211337SWilliam.Krier@Sun.COM 	if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
71311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
71411337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
71511337SWilliam.Krier@Sun.COM 	}
71611337SWilliam.Krier@Sun.COM 
71711337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
71811337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
71911337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
72011337SWilliam.Krier@Sun.COM 	}
72111337SWilliam.Krier@Sun.COM 
72211337SWilliam.Krier@Sun.COM 	if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
72311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
72411337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
72511337SWilliam.Krier@Sun.COM 	}
72611337SWilliam.Krier@Sun.COM 
72711337SWilliam.Krier@Sun.COM 	if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
72811337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
72911337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
73011337SWilliam.Krier@Sun.COM 	}
73111337SWilliam.Krier@Sun.COM 
73211337SWilliam.Krier@Sun.COM 	all_info = &param->ru.info21;
73311337SWilliam.Krier@Sun.COM 	bzero(all_info, sizeof (struct samr_QueryUserInfo21));
73411337SWilliam.Krier@Sun.COM 
73511337SWilliam.Krier@Sun.COM 	all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
73611337SWilliam.Krier@Sun.COM 
73711337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, account.a_name,
73811337SWilliam.Krier@Sun.COM 	    (ndr_mstring_t *)&all_info->UserName);
73911337SWilliam.Krier@Sun.COM 	all_info->UserId = data->kd_rid;
74011337SWilliam.Krier@Sun.COM 
74111337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.length = 16;
74211337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.maxlen = 16;
74311337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.buf = owf_buf;
74411337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.length = 16;
74511337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.maxlen = 16;
74611337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.buf = owf_buf;
74711337SWilliam.Krier@Sun.COM 	all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
74811337SWilliam.Krier@Sun.COM 	all_info->LogonHours.hours = hour_buf;
74911337SWilliam.Krier@Sun.COM 
75011337SWilliam.Krier@Sun.COM 	param->address = 1;
75111337SWilliam.Krier@Sun.COM 	param->switch_index = SAMR_QUERY_USER_ALL_INFO;
75211337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
75311963SAfshin.Ardakani@Sun.COM 	smb_account_free(&account);
75411963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sid);
75511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
75611337SWilliam.Krier@Sun.COM 
75711337SWilliam.Krier@Sun.COM QueryUserInfoError:
75811963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sid);
75911337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserInfo));
76011337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
76111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
76211337SWilliam.Krier@Sun.COM }
76311337SWilliam.Krier@Sun.COM 
76411337SWilliam.Krier@Sun.COM /*
76511337SWilliam.Krier@Sun.COM  * samr_s_QueryUserGroups
76611337SWilliam.Krier@Sun.COM  *
76711337SWilliam.Krier@Sun.COM  * Request the list of groups of which a user is a member.
76811337SWilliam.Krier@Sun.COM  * The user is identified from the handle, which contains an
76911337SWilliam.Krier@Sun.COM  * rid in the discriminator field. Note that this is a local user.
77011337SWilliam.Krier@Sun.COM  */
77111337SWilliam.Krier@Sun.COM static int
77211337SWilliam.Krier@Sun.COM samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
77311337SWilliam.Krier@Sun.COM {
77411337SWilliam.Krier@Sun.COM 	struct samr_QueryUserGroups *param = arg;
77511337SWilliam.Krier@Sun.COM 	struct samr_UserGroupInfo *info;
77611337SWilliam.Krier@Sun.COM 	struct samr_UserGroups *group;
77711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
77811337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
77911337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
78011337SWilliam.Krier@Sun.COM 	smb_sid_t *user_sid = NULL;
78111337SWilliam.Krier@Sun.COM 	smb_group_t grp;
78211337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
78311337SWilliam.Krier@Sun.COM 	smb_domain_t di;
78411337SWilliam.Krier@Sun.COM 	uint32_t status;
78511337SWilliam.Krier@Sun.COM 	int size;
78611337SWilliam.Krier@Sun.COM 	int ngrp_max;
78711337SWilliam.Krier@Sun.COM 
78811337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
78911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
79011337SWilliam.Krier@Sun.COM 		goto query_error;
79111337SWilliam.Krier@Sun.COM 	}
79211337SWilliam.Krier@Sun.COM 
79311337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
79411337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
79511337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
79611337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
79711337SWilliam.Krier@Sun.COM 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
79811337SWilliam.Krier@Sun.COM 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
79911337SWilliam.Krier@Sun.COM 			goto query_error;
80011337SWilliam.Krier@Sun.COM 		}
80111337SWilliam.Krier@Sun.COM 		break;
80211337SWilliam.Krier@Sun.COM 	default:
80311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
80411337SWilliam.Krier@Sun.COM 		goto query_error;
80511337SWilliam.Krier@Sun.COM 	}
80611337SWilliam.Krier@Sun.COM 
80711337SWilliam.Krier@Sun.COM 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
80811337SWilliam.Krier@Sun.COM 	if (user_sid == NULL) {
80911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
81011337SWilliam.Krier@Sun.COM 		goto query_error;
81111337SWilliam.Krier@Sun.COM 	}
81211337SWilliam.Krier@Sun.COM 
81311337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
81411337SWilliam.Krier@Sun.COM 	if (info == NULL) {
81511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
81611337SWilliam.Krier@Sun.COM 		goto query_error;
81711337SWilliam.Krier@Sun.COM 	}
81811337SWilliam.Krier@Sun.COM 	bzero(info, sizeof (struct samr_UserGroupInfo));
81911337SWilliam.Krier@Sun.COM 
82011337SWilliam.Krier@Sun.COM 	size = 32 * 1024;
82111337SWilliam.Krier@Sun.COM 	info->groups = NDR_MALLOC(mxa, size);
82211337SWilliam.Krier@Sun.COM 	if (info->groups == NULL) {
82311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
82411337SWilliam.Krier@Sun.COM 		goto query_error;
82511337SWilliam.Krier@Sun.COM 	}
82611337SWilliam.Krier@Sun.COM 	ngrp_max = size / sizeof (struct samr_UserGroups);
82711337SWilliam.Krier@Sun.COM 
82811337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
82911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INTERNAL_ERROR;
83011337SWilliam.Krier@Sun.COM 		goto query_error;
83111337SWilliam.Krier@Sun.COM 	}
83211337SWilliam.Krier@Sun.COM 
83311337SWilliam.Krier@Sun.COM 	info->n_entry = 0;
83411337SWilliam.Krier@Sun.COM 	group = info->groups;
83511337SWilliam.Krier@Sun.COM 	while ((info->n_entry < ngrp_max) &&
83611337SWilliam.Krier@Sun.COM 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
83711337SWilliam.Krier@Sun.COM 		if (smb_lgrp_is_member(&grp, user_sid)) {
83811337SWilliam.Krier@Sun.COM 			group->rid = grp.sg_rid;
83911337SWilliam.Krier@Sun.COM 			group->attr = grp.sg_attr;
84011337SWilliam.Krier@Sun.COM 			group++;
84111337SWilliam.Krier@Sun.COM 			info->n_entry++;
84211337SWilliam.Krier@Sun.COM 		}
84311337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
84411337SWilliam.Krier@Sun.COM 	}
84511337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
84611337SWilliam.Krier@Sun.COM 
84711337SWilliam.Krier@Sun.COM 	free(user_sid);
84811337SWilliam.Krier@Sun.COM 	param->info = info;
84911337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
85011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
85111337SWilliam.Krier@Sun.COM 
85211337SWilliam.Krier@Sun.COM query_error:
85311337SWilliam.Krier@Sun.COM 	free(user_sid);
85411337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserGroups));
85511337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
85611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
85711337SWilliam.Krier@Sun.COM }
85811337SWilliam.Krier@Sun.COM 
85911337SWilliam.Krier@Sun.COM /*
86011337SWilliam.Krier@Sun.COM  * samr_s_OpenGroup
86111337SWilliam.Krier@Sun.COM  *
86211337SWilliam.Krier@Sun.COM  * This is a request to open a group within the specified domain in the
86311337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
86411337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The group is
86511337SWilliam.Krier@Sun.COM  * specified by the rid in the request. If this is a local RID it
86611337SWilliam.Krier@Sun.COM  * should already be encoded with type information.
86711337SWilliam.Krier@Sun.COM  *
86811337SWilliam.Krier@Sun.COM  * We return a handle to be used to access information about this group.
86911337SWilliam.Krier@Sun.COM  */
87011337SWilliam.Krier@Sun.COM static int
87111337SWilliam.Krier@Sun.COM samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
87211337SWilliam.Krier@Sun.COM {
87311337SWilliam.Krier@Sun.COM 	struct samr_OpenGroup *param = arg;
87411337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
87511337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
87611337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
87711337SWilliam.Krier@Sun.COM 
87811337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
87911337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
88011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
88111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
88211337SWilliam.Krier@Sun.COM 	}
88311337SWilliam.Krier@Sun.COM 
88411337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
88511337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
88611337SWilliam.Krier@Sun.COM 
88711337SWilliam.Krier@Sun.COM 	if (id) {
88811337SWilliam.Krier@Sun.COM 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
88911337SWilliam.Krier@Sun.COM 		param->status = 0;
89011337SWilliam.Krier@Sun.COM 	} else {
89111337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
89211337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
89311337SWilliam.Krier@Sun.COM 	}
89411337SWilliam.Krier@Sun.COM 
89511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
89611337SWilliam.Krier@Sun.COM }
89711337SWilliam.Krier@Sun.COM 
89811337SWilliam.Krier@Sun.COM /*
899*12065SKeyur.Desai@Sun.COM  * samr_s_AddAliasMember
900*12065SKeyur.Desai@Sun.COM  *
901*12065SKeyur.Desai@Sun.COM  * Add a member to a local SAM group.
902*12065SKeyur.Desai@Sun.COM  * The caller must supply a valid group handle.
903*12065SKeyur.Desai@Sun.COM  * The member is specified by the sid in the request.
904*12065SKeyur.Desai@Sun.COM  */
905*12065SKeyur.Desai@Sun.COM static int
906*12065SKeyur.Desai@Sun.COM samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa)
907*12065SKeyur.Desai@Sun.COM {
908*12065SKeyur.Desai@Sun.COM 	struct samr_AddAliasMember *param = arg;
909*12065SKeyur.Desai@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
910*12065SKeyur.Desai@Sun.COM 	ndr_handle_t *hd;
911*12065SKeyur.Desai@Sun.COM 	samr_keydata_t *data;
912*12065SKeyur.Desai@Sun.COM 	smb_group_t grp;
913*12065SKeyur.Desai@Sun.COM 	uint32_t rc;
914*12065SKeyur.Desai@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
915*12065SKeyur.Desai@Sun.COM 
916*12065SKeyur.Desai@Sun.COM 	if (param->sid == NULL) {
917*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_AddAliasMember));
918*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
919*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
920*12065SKeyur.Desai@Sun.COM 	}
921*12065SKeyur.Desai@Sun.COM 
922*12065SKeyur.Desai@Sun.COM 	if (!ndr_is_admin(mxa)) {
923*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_AddAliasMember));
924*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
925*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
926*12065SKeyur.Desai@Sun.COM 	}
927*12065SKeyur.Desai@Sun.COM 
928*12065SKeyur.Desai@Sun.COM 
929*12065SKeyur.Desai@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
930*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_AddAliasMember));
931*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
932*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
933*12065SKeyur.Desai@Sun.COM 	}
934*12065SKeyur.Desai@Sun.COM 
935*12065SKeyur.Desai@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
936*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
937*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
938*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_AddAliasMember));
939*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
940*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
941*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
942*12065SKeyur.Desai@Sun.COM 	}
943*12065SKeyur.Desai@Sun.COM 
944*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_add_member(grp.sg_name,
945*12065SKeyur.Desai@Sun.COM 	    (smb_sid_t *)param->sid, SidTypeUser);
946*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
947*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_AddAliasMember));
948*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
949*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
950*12065SKeyur.Desai@Sun.COM 	}
951*12065SKeyur.Desai@Sun.COM 	smb_lgrp_free(&grp);
952*12065SKeyur.Desai@Sun.COM 
953*12065SKeyur.Desai@Sun.COM 	param->status = status;
954*12065SKeyur.Desai@Sun.COM 	return (NDR_DRC_OK);
955*12065SKeyur.Desai@Sun.COM }
956*12065SKeyur.Desai@Sun.COM 
957*12065SKeyur.Desai@Sun.COM /*
958*12065SKeyur.Desai@Sun.COM  * samr_s_DeleteAliasMember
959*12065SKeyur.Desai@Sun.COM  *
960*12065SKeyur.Desai@Sun.COM  * Delete a member from a local SAM group.
961*12065SKeyur.Desai@Sun.COM  * The caller must supply a valid group handle.
962*12065SKeyur.Desai@Sun.COM  * The member is specified by the sid in the request.
963*12065SKeyur.Desai@Sun.COM  */
964*12065SKeyur.Desai@Sun.COM static int
965*12065SKeyur.Desai@Sun.COM samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa)
966*12065SKeyur.Desai@Sun.COM {
967*12065SKeyur.Desai@Sun.COM 	struct samr_DeleteAliasMember *param = arg;
968*12065SKeyur.Desai@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
969*12065SKeyur.Desai@Sun.COM 	ndr_handle_t *hd;
970*12065SKeyur.Desai@Sun.COM 	samr_keydata_t *data;
971*12065SKeyur.Desai@Sun.COM 	smb_group_t grp;
972*12065SKeyur.Desai@Sun.COM 	uint32_t rc;
973*12065SKeyur.Desai@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
974*12065SKeyur.Desai@Sun.COM 
975*12065SKeyur.Desai@Sun.COM 	if (param->sid == NULL) {
976*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteAliasMember));
977*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
978*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
979*12065SKeyur.Desai@Sun.COM 	}
980*12065SKeyur.Desai@Sun.COM 
981*12065SKeyur.Desai@Sun.COM 	if (!ndr_is_admin(mxa)) {
982*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteAliasMember));
983*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
984*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
985*12065SKeyur.Desai@Sun.COM 	}
986*12065SKeyur.Desai@Sun.COM 
987*12065SKeyur.Desai@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
988*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteAliasMember));
989*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
990*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
991*12065SKeyur.Desai@Sun.COM 	}
992*12065SKeyur.Desai@Sun.COM 
993*12065SKeyur.Desai@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
994*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
995*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
996*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteAliasMember));
997*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
998*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
999*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1000*12065SKeyur.Desai@Sun.COM 	}
1001*12065SKeyur.Desai@Sun.COM 
1002*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_del_member(grp.sg_name,
1003*12065SKeyur.Desai@Sun.COM 	    (smb_sid_t *)param->sid, SidTypeUser);
1004*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
1005*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1006*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
1007*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
1008*12065SKeyur.Desai@Sun.COM 	}
1009*12065SKeyur.Desai@Sun.COM 	smb_lgrp_free(&grp);
1010*12065SKeyur.Desai@Sun.COM 
1011*12065SKeyur.Desai@Sun.COM 	param->status = status;
1012*12065SKeyur.Desai@Sun.COM 	return (NDR_DRC_OK);
1013*12065SKeyur.Desai@Sun.COM }
1014*12065SKeyur.Desai@Sun.COM 
1015*12065SKeyur.Desai@Sun.COM /*
1016*12065SKeyur.Desai@Sun.COM  * samr_s_ListAliasMembers
1017*12065SKeyur.Desai@Sun.COM  *
1018*12065SKeyur.Desai@Sun.COM  * List members from a local SAM group.
1019*12065SKeyur.Desai@Sun.COM  * The caller must supply a valid group handle.
1020*12065SKeyur.Desai@Sun.COM  * A list of user SIDs in the specified group is returned to the caller.
1021*12065SKeyur.Desai@Sun.COM  */
1022*12065SKeyur.Desai@Sun.COM static int
1023*12065SKeyur.Desai@Sun.COM samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa)
1024*12065SKeyur.Desai@Sun.COM {
1025*12065SKeyur.Desai@Sun.COM 	struct samr_ListAliasMembers *param = arg;
1026*12065SKeyur.Desai@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1027*12065SKeyur.Desai@Sun.COM 	ndr_handle_t *hd;
1028*12065SKeyur.Desai@Sun.COM 	samr_keydata_t *data;
1029*12065SKeyur.Desai@Sun.COM 	smb_group_t grp;
1030*12065SKeyur.Desai@Sun.COM 	smb_gsid_t *members;
1031*12065SKeyur.Desai@Sun.COM 	struct samr_SidInfo info;
1032*12065SKeyur.Desai@Sun.COM 	struct samr_SidList *user;
1033*12065SKeyur.Desai@Sun.COM 	uint32_t num = 0, size;
1034*12065SKeyur.Desai@Sun.COM 	int i;
1035*12065SKeyur.Desai@Sun.COM 	uint32_t rc;
1036*12065SKeyur.Desai@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
1037*12065SKeyur.Desai@Sun.COM 
1038*12065SKeyur.Desai@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1039*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_ListAliasMembers));
1040*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1041*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1042*12065SKeyur.Desai@Sun.COM 	}
1043*12065SKeyur.Desai@Sun.COM 
1044*12065SKeyur.Desai@Sun.COM 	bzero(&info, sizeof (struct samr_SidInfo));
1045*12065SKeyur.Desai@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1046*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1047*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
1048*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_ListAliasMembers));
1049*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
1050*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
1051*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1052*12065SKeyur.Desai@Sun.COM 	}
1053*12065SKeyur.Desai@Sun.COM 
1054*12065SKeyur.Desai@Sun.COM 	num = grp.sg_nmembers;
1055*12065SKeyur.Desai@Sun.COM 	members = grp.sg_members;
1056*12065SKeyur.Desai@Sun.COM 	size = num * sizeof (struct samr_SidList);
1057*12065SKeyur.Desai@Sun.COM 	info.sidlist = NDR_MALLOC(mxa, size);
1058*12065SKeyur.Desai@Sun.COM 	if (info.sidlist == NULL) {
1059*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_ListAliasMembers));
1060*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1061*12065SKeyur.Desai@Sun.COM 		smb_lgrp_free(&grp);
1062*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1063*12065SKeyur.Desai@Sun.COM 	}
1064*12065SKeyur.Desai@Sun.COM 
1065*12065SKeyur.Desai@Sun.COM 	info.n_entry = num;
1066*12065SKeyur.Desai@Sun.COM 	user = info.sidlist;
1067*12065SKeyur.Desai@Sun.COM 	for (i = 0; i < num; i++) {
1068*12065SKeyur.Desai@Sun.COM 		user->sid = (struct samr_sid *)NDR_SIDDUP(mxa,
1069*12065SKeyur.Desai@Sun.COM 		    members[i].gs_sid);
1070*12065SKeyur.Desai@Sun.COM 		if (user->sid == NULL) {
1071*12065SKeyur.Desai@Sun.COM 			bzero(param, sizeof (struct samr_ListAliasMembers));
1072*12065SKeyur.Desai@Sun.COM 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1073*12065SKeyur.Desai@Sun.COM 			smb_lgrp_free(&grp);
1074*12065SKeyur.Desai@Sun.COM 			return (NDR_DRC_OK);
1075*12065SKeyur.Desai@Sun.COM 		}
1076*12065SKeyur.Desai@Sun.COM 		user++;
1077*12065SKeyur.Desai@Sun.COM 	}
1078*12065SKeyur.Desai@Sun.COM 	smb_lgrp_free(&grp);
1079*12065SKeyur.Desai@Sun.COM 
1080*12065SKeyur.Desai@Sun.COM 	param->info = info;
1081*12065SKeyur.Desai@Sun.COM 	param->status = status;
1082*12065SKeyur.Desai@Sun.COM 	return (NDR_DRC_OK);
1083*12065SKeyur.Desai@Sun.COM }
1084*12065SKeyur.Desai@Sun.COM 
1085*12065SKeyur.Desai@Sun.COM /*
108611337SWilliam.Krier@Sun.COM  * samr_s_Connect
108711337SWilliam.Krier@Sun.COM  *
108811337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database.
108911337SWilliam.Krier@Sun.COM  * We don't support any form of update request and our database doesn't
109011337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in doing
109111337SWilliam.Krier@Sun.COM  * any access access checking here.
109211337SWilliam.Krier@Sun.COM  *
109311337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
109411337SWilliam.Krier@Sun.COM  */
109511337SWilliam.Krier@Sun.COM static int
109611337SWilliam.Krier@Sun.COM samr_s_Connect(void *arg, ndr_xa_t *mxa)
109711337SWilliam.Krier@Sun.COM {
109811337SWilliam.Krier@Sun.COM 	struct samr_Connect *param = arg;
109911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
110011337SWilliam.Krier@Sun.COM 
110111337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
110211337SWilliam.Krier@Sun.COM 	if (id) {
110311337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
110411337SWilliam.Krier@Sun.COM 		param->status = 0;
110511337SWilliam.Krier@Sun.COM 	} else {
110611337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
110711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
110811337SWilliam.Krier@Sun.COM 	}
110911337SWilliam.Krier@Sun.COM 
111011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
111111337SWilliam.Krier@Sun.COM }
111211337SWilliam.Krier@Sun.COM 
111311337SWilliam.Krier@Sun.COM /*
111411337SWilliam.Krier@Sun.COM  * samr_s_GetUserPwInfo
111511337SWilliam.Krier@Sun.COM  *
111611447Samw@Sun.COM  * Request for a user's password policy information.
111711337SWilliam.Krier@Sun.COM  */
111811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
111911337SWilliam.Krier@Sun.COM static int
112011337SWilliam.Krier@Sun.COM samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
112111337SWilliam.Krier@Sun.COM {
112211447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
112311447Samw@Sun.COM 	struct samr_GetUserPwInfo	*param = arg;
112411337SWilliam.Krier@Sun.COM 
112511447Samw@Sun.COM 	param->pwinfo = &pwinfo;
112611447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
112711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
112811337SWilliam.Krier@Sun.COM }
112911337SWilliam.Krier@Sun.COM 
113011337SWilliam.Krier@Sun.COM /*
113111337SWilliam.Krier@Sun.COM  * samr_s_CreateUser
113211337SWilliam.Krier@Sun.COM  */
113311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
113411337SWilliam.Krier@Sun.COM static int
113511337SWilliam.Krier@Sun.COM samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
113611337SWilliam.Krier@Sun.COM {
113711337SWilliam.Krier@Sun.COM 	struct samr_CreateUser *param = arg;
113811337SWilliam.Krier@Sun.COM 
113911337SWilliam.Krier@Sun.COM 	bzero(&param->user_handle, sizeof (samr_handle_t));
114011337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
114111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
114211337SWilliam.Krier@Sun.COM }
114311337SWilliam.Krier@Sun.COM 
114411337SWilliam.Krier@Sun.COM /*
114511337SWilliam.Krier@Sun.COM  * samr_s_ChangeUserPasswd
114611337SWilliam.Krier@Sun.COM  */
114711337SWilliam.Krier@Sun.COM /*ARGSUSED*/
114811337SWilliam.Krier@Sun.COM static int
114911337SWilliam.Krier@Sun.COM samr_s_ChangeUserPasswd(void *arg, ndr_xa_t *mxa)
115011337SWilliam.Krier@Sun.COM {
115111337SWilliam.Krier@Sun.COM 	struct samr_ChangeUserPasswd *param = arg;
115211337SWilliam.Krier@Sun.COM 
115311337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_ChangeUserPasswd));
115411337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
115511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
115611337SWilliam.Krier@Sun.COM }
115711337SWilliam.Krier@Sun.COM 
115811337SWilliam.Krier@Sun.COM /*
115911337SWilliam.Krier@Sun.COM  * samr_s_GetDomainPwInfo
116011447Samw@Sun.COM  *
116111447Samw@Sun.COM  * Request for the domain password policy information.
116211337SWilliam.Krier@Sun.COM  */
116311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
116411337SWilliam.Krier@Sun.COM static int
116511337SWilliam.Krier@Sun.COM samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
116611337SWilliam.Krier@Sun.COM {
116711447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
116811447Samw@Sun.COM 	struct samr_GetDomainPwInfo	*param = arg;
116911337SWilliam.Krier@Sun.COM 
117011447Samw@Sun.COM 	param->pwinfo = &pwinfo;
117111447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
117211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
117311337SWilliam.Krier@Sun.COM }
117411337SWilliam.Krier@Sun.COM 
117511337SWilliam.Krier@Sun.COM /*
117611337SWilliam.Krier@Sun.COM  * samr_s_SetUserInfo
117711337SWilliam.Krier@Sun.COM  */
117811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
117911337SWilliam.Krier@Sun.COM static int
118011337SWilliam.Krier@Sun.COM samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
118111337SWilliam.Krier@Sun.COM {
118211337SWilliam.Krier@Sun.COM 	struct samr_SetUserInfo *param = arg;
118311337SWilliam.Krier@Sun.COM 
118411337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_SetUserInfo));
118511337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
118611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
118711337SWilliam.Krier@Sun.COM }
118811337SWilliam.Krier@Sun.COM 
118911337SWilliam.Krier@Sun.COM /*
119011337SWilliam.Krier@Sun.COM  * samr_s_QueryDispInfo
119111337SWilliam.Krier@Sun.COM  *
119211337SWilliam.Krier@Sun.COM  * This function currently return local users' information only.
119311337SWilliam.Krier@Sun.COM  * This RPC is called repeatedly until all the users info are
119411337SWilliam.Krier@Sun.COM  * retrieved.
119511337SWilliam.Krier@Sun.COM  *
119611337SWilliam.Krier@Sun.COM  * The total count and the returned count are returned as total size
119711337SWilliam.Krier@Sun.COM  * and returned size.  The client doesn't seem to care.
119811337SWilliam.Krier@Sun.COM  */
119911337SWilliam.Krier@Sun.COM static int
120011337SWilliam.Krier@Sun.COM samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
120111337SWilliam.Krier@Sun.COM {
120211337SWilliam.Krier@Sun.COM 	struct samr_QueryDispInfo *param = arg;
120311337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
120411337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
120511337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
120611337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
120711337SWilliam.Krier@Sun.COM 	struct user_acct_info *user;
120811337SWilliam.Krier@Sun.COM 	smb_pwditer_t pwi;
120911337SWilliam.Krier@Sun.COM 	smb_luser_t *uinfo;
121011337SWilliam.Krier@Sun.COM 	int num_users;
121111337SWilliam.Krier@Sun.COM 	int start_idx;
121211337SWilliam.Krier@Sun.COM 	int max_retcnt, retcnt;
121311337SWilliam.Krier@Sun.COM 	int skip;
121411337SWilliam.Krier@Sun.COM 
121511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
121611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
121711337SWilliam.Krier@Sun.COM 		goto error;
121811337SWilliam.Krier@Sun.COM 	}
121911337SWilliam.Krier@Sun.COM 
122011337SWilliam.Krier@Sun.COM 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
122111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
122211337SWilliam.Krier@Sun.COM 		goto error;
122311337SWilliam.Krier@Sun.COM 	}
122411337SWilliam.Krier@Sun.COM 
122511337SWilliam.Krier@Sun.COM 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
122611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NOT_IMPLEMENTED;
122711337SWilliam.Krier@Sun.COM 		goto error;
122811337SWilliam.Krier@Sun.COM 	}
122911337SWilliam.Krier@Sun.COM 
123011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
123111337SWilliam.Krier@Sun.COM 
123211337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
123311337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
123411337SWilliam.Krier@Sun.COM 		goto no_info;
123511337SWilliam.Krier@Sun.COM 
123611337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
123711337SWilliam.Krier@Sun.COM 		num_users = smb_sam_usr_cnt();
123811337SWilliam.Krier@Sun.COM 		start_idx = param->start_idx;
123911337SWilliam.Krier@Sun.COM 		if ((num_users == 0) || (start_idx >= num_users))
124011337SWilliam.Krier@Sun.COM 			goto no_info;
124111337SWilliam.Krier@Sun.COM 
124211337SWilliam.Krier@Sun.COM 		max_retcnt = num_users - start_idx;
124311337SWilliam.Krier@Sun.COM 		if (max_retcnt > param->max_entries)
124411337SWilliam.Krier@Sun.COM 			max_retcnt = param->max_entries;
124511337SWilliam.Krier@Sun.COM 		param->users.acct = NDR_MALLOC(mxa,
124611337SWilliam.Krier@Sun.COM 		    max_retcnt * sizeof (struct user_acct_info));
124711337SWilliam.Krier@Sun.COM 		user = param->users.acct;
124811337SWilliam.Krier@Sun.COM 		if (user == NULL) {
124911337SWilliam.Krier@Sun.COM 			status = NT_STATUS_NO_MEMORY;
125011337SWilliam.Krier@Sun.COM 			goto error;
125111337SWilliam.Krier@Sun.COM 		}
125211337SWilliam.Krier@Sun.COM 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
125311337SWilliam.Krier@Sun.COM 
125411337SWilliam.Krier@Sun.COM 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
125511337SWilliam.Krier@Sun.COM 			goto no_info;
125611337SWilliam.Krier@Sun.COM 
125711337SWilliam.Krier@Sun.COM 		skip = retcnt = 0;
125811337SWilliam.Krier@Sun.COM 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
125911337SWilliam.Krier@Sun.COM 			if (skip++ < start_idx)
126011337SWilliam.Krier@Sun.COM 				continue;
126111337SWilliam.Krier@Sun.COM 
126211337SWilliam.Krier@Sun.COM 			if (retcnt++ >= max_retcnt)
126311337SWilliam.Krier@Sun.COM 				break;
126411337SWilliam.Krier@Sun.COM 
126511337SWilliam.Krier@Sun.COM 			assert(uinfo->su_name != NULL);
126611337SWilliam.Krier@Sun.COM 
126711337SWilliam.Krier@Sun.COM 			user->index = start_idx + retcnt;
126811337SWilliam.Krier@Sun.COM 			user->rid = uinfo->su_rid;
126911337SWilliam.Krier@Sun.COM 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
127011337SWilliam.Krier@Sun.COM 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
127111337SWilliam.Krier@Sun.COM 				user->ctrl |= ACF_DISABLED;
127211337SWilliam.Krier@Sun.COM 			if (NDR_MSTRING(mxa, uinfo->su_name,
127311337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->name) == -1) {
127411337SWilliam.Krier@Sun.COM 				smb_pwd_iterclose(&pwi);
127511337SWilliam.Krier@Sun.COM 				status = NT_STATUS_NO_MEMORY;
127611337SWilliam.Krier@Sun.COM 				goto error;
127711337SWilliam.Krier@Sun.COM 			}
127811337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
127911337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->fullname);
128011337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
128111337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->desc);
128211337SWilliam.Krier@Sun.COM 			user++;
128311337SWilliam.Krier@Sun.COM 		}
128411337SWilliam.Krier@Sun.COM 		smb_pwd_iterclose(&pwi);
128511337SWilliam.Krier@Sun.COM 
128611337SWilliam.Krier@Sun.COM 		if (retcnt >= max_retcnt) {
128711337SWilliam.Krier@Sun.COM 			retcnt = max_retcnt;
128811337SWilliam.Krier@Sun.COM 			param->status = status;
128911337SWilliam.Krier@Sun.COM 		} else {
129011337SWilliam.Krier@Sun.COM 			param->status = ERROR_MORE_ENTRIES;
129111337SWilliam.Krier@Sun.COM 		}
129211337SWilliam.Krier@Sun.COM 
129311337SWilliam.Krier@Sun.COM 		param->users.total_size = num_users;
129411337SWilliam.Krier@Sun.COM 		param->users.returned_size = retcnt;
129511337SWilliam.Krier@Sun.COM 		param->users.switch_value = param->level;
129611337SWilliam.Krier@Sun.COM 		param->users.count = retcnt;
129711337SWilliam.Krier@Sun.COM 
129811337SWilliam.Krier@Sun.COM 		break;
129911337SWilliam.Krier@Sun.COM 
130011337SWilliam.Krier@Sun.COM 	default:
130111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
130211337SWilliam.Krier@Sun.COM 		goto error;
130311337SWilliam.Krier@Sun.COM 	}
130411337SWilliam.Krier@Sun.COM 
130511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
130611337SWilliam.Krier@Sun.COM 
130711337SWilliam.Krier@Sun.COM no_info:
130811337SWilliam.Krier@Sun.COM 	param->users.total_size = 0;
130911337SWilliam.Krier@Sun.COM 	param->users.returned_size = 0;
131011337SWilliam.Krier@Sun.COM 	param->users.switch_value = param->level;
131111337SWilliam.Krier@Sun.COM 	param->users.count = 0;
131211337SWilliam.Krier@Sun.COM 	param->users.acct = NULL;
131311337SWilliam.Krier@Sun.COM 	param->status = status;
131411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
131511337SWilliam.Krier@Sun.COM 
131611337SWilliam.Krier@Sun.COM error:
131711337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryDispInfo));
131811337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
131911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
132011337SWilliam.Krier@Sun.COM }
132111337SWilliam.Krier@Sun.COM 
132211337SWilliam.Krier@Sun.COM /*
132311337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainGroups
132411337SWilliam.Krier@Sun.COM  *
132511337SWilliam.Krier@Sun.COM  *
132611337SWilliam.Krier@Sun.COM  * This function is supposed to return local group information.
132711337SWilliam.Krier@Sun.COM  * As we don't support local users, this function dosen't send
132811337SWilliam.Krier@Sun.COM  * back any information.
132911337SWilliam.Krier@Sun.COM  *
133011337SWilliam.Krier@Sun.COM  * Added template that returns information for a domain group as None.
133111337SWilliam.Krier@Sun.COM  * All information is hard-coded from packet captures.
133211337SWilliam.Krier@Sun.COM  */
133311337SWilliam.Krier@Sun.COM static int
133411337SWilliam.Krier@Sun.COM samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
133511337SWilliam.Krier@Sun.COM {
133611337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainGroups *param = arg;
133711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
133811337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
133911337SWilliam.Krier@Sun.COM 
134011337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
134111337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
134211337SWilliam.Krier@Sun.COM 
134311337SWilliam.Krier@Sun.COM 	param->total_size = 0;
134411337SWilliam.Krier@Sun.COM 	param->returned_size = 0;
134511337SWilliam.Krier@Sun.COM 	param->switch_value = 3;
134611337SWilliam.Krier@Sun.COM 	param->count = 0;
134711337SWilliam.Krier@Sun.COM 	param->groups = 0;
134811337SWilliam.Krier@Sun.COM 	param->status = status;
134911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
135011337SWilliam.Krier@Sun.COM 
135111337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_GROUPS
135211337SWilliam.Krier@Sun.COM 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
135311337SWilliam.Krier@Sun.COM 		param->total_size = 0;
135411337SWilliam.Krier@Sun.COM 		param->returned_size = 0;
135511337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
135611337SWilliam.Krier@Sun.COM 		param->count = 0;
135711337SWilliam.Krier@Sun.COM 		param->groups = 0;
135811337SWilliam.Krier@Sun.COM 	} else {
135911337SWilliam.Krier@Sun.COM 		param->total_size = 64;
136011337SWilliam.Krier@Sun.COM 		param->returned_size = 64;
136111337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
136211337SWilliam.Krier@Sun.COM 		param->count = 1;
136311337SWilliam.Krier@Sun.COM 		param->groups = (struct group_disp_info *)NDR_MALLOC(
136411337SWilliam.Krier@Sun.COM 		    mxa, sizeof (struct group_disp_info));
136511337SWilliam.Krier@Sun.COM 
136611337SWilliam.Krier@Sun.COM 		param->groups->count = 1;
136711337SWilliam.Krier@Sun.COM 		param->groups->acct[0].index = 1;
136811337SWilliam.Krier@Sun.COM 		param->groups->acct[0].rid = 513;
136911337SWilliam.Krier@Sun.COM 		param->groups->acct[0].ctrl = 0x7;
137011337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "None",
137111337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].name);
137211337SWilliam.Krier@Sun.COM 
137311337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "Ordinary users",
137411337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
137511337SWilliam.Krier@Sun.COM 	}
137611337SWilliam.Krier@Sun.COM 
137711337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
137811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
137911337SWilliam.Krier@Sun.COM #endif
138011337SWilliam.Krier@Sun.COM }
138111337SWilliam.Krier@Sun.COM 
138211337SWilliam.Krier@Sun.COM /*
138311337SWilliam.Krier@Sun.COM  * samr_s_OpenAlias
138411337SWilliam.Krier@Sun.COM  *
138511337SWilliam.Krier@Sun.COM  * Lookup for requested alias, if it exists return a handle
138611337SWilliam.Krier@Sun.COM  * for that alias. The alias domain sid should match with
138711337SWilliam.Krier@Sun.COM  * the passed domain handle.
138811337SWilliam.Krier@Sun.COM  */
138911337SWilliam.Krier@Sun.COM static int
139011337SWilliam.Krier@Sun.COM samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
139111337SWilliam.Krier@Sun.COM {
139211337SWilliam.Krier@Sun.COM 	struct samr_OpenAlias *param = arg;
139311447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
139411447Samw@Sun.COM 	ndr_handle_t	*hd;
139511447Samw@Sun.COM 	samr_keydata_t	*data;
139611963SAfshin.Ardakani@Sun.COM 	smb_domain_type_t gd_type;
139711447Samw@Sun.COM 	smb_sid_t	*sid;
139811447Samw@Sun.COM 	smb_wka_t	*wka;
139911447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
140011447Samw@Sun.COM 	uint32_t	rid;
140111447Samw@Sun.COM 	uint32_t	status;
140211447Samw@Sun.COM 	int		rc;
140311337SWilliam.Krier@Sun.COM 
140411337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
140511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
140611337SWilliam.Krier@Sun.COM 		goto open_alias_err;
140711337SWilliam.Krier@Sun.COM 	}
140811337SWilliam.Krier@Sun.COM 
1409*12065SKeyur.Desai@Sun.COM 	if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
141011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
141111337SWilliam.Krier@Sun.COM 		goto open_alias_err;
141211337SWilliam.Krier@Sun.COM 	}
141311337SWilliam.Krier@Sun.COM 
141411337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
141511963SAfshin.Ardakani@Sun.COM 	gd_type = (smb_domain_type_t)data->kd_type;
141611447Samw@Sun.COM 	rid = param->rid;
141711447Samw@Sun.COM 
141811447Samw@Sun.COM 	switch (gd_type) {
141911963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_BUILTIN:
142011447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
142111447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
142211447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
142311447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
142411447Samw@Sun.COM 			goto open_alias_err;
142511447Samw@Sun.COM 		}
142611447Samw@Sun.COM 
142711447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
142811447Samw@Sun.COM 		smb_sid_free(sid);
142911447Samw@Sun.COM 
143011447Samw@Sun.COM 		if (wka == NULL) {
143111447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
143211447Samw@Sun.COM 			goto open_alias_err;
143311447Samw@Sun.COM 		}
143411447Samw@Sun.COM 		break;
143511447Samw@Sun.COM 
143611963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_LOCAL:
143711447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
143811447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
143911447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
144011447Samw@Sun.COM 			goto open_alias_err;
144111447Samw@Sun.COM 		}
144211447Samw@Sun.COM 		break;
144311447Samw@Sun.COM 
144411447Samw@Sun.COM 	default:
144511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
144611337SWilliam.Krier@Sun.COM 		goto open_alias_err;
144711337SWilliam.Krier@Sun.COM 	}
144811337SWilliam.Krier@Sun.COM 
144911337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
145011337SWilliam.Krier@Sun.COM 	if (id) {
145111337SWilliam.Krier@Sun.COM 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
145211337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
145311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
145411337SWilliam.Krier@Sun.COM 	}
145511337SWilliam.Krier@Sun.COM 
145611337SWilliam.Krier@Sun.COM 	status = NT_STATUS_NO_MEMORY;
145711337SWilliam.Krier@Sun.COM 
145811337SWilliam.Krier@Sun.COM open_alias_err:
145911337SWilliam.Krier@Sun.COM 	bzero(&param->alias_handle, sizeof (samr_handle_t));
146011337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
146111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
146211337SWilliam.Krier@Sun.COM }
146311337SWilliam.Krier@Sun.COM 
146411337SWilliam.Krier@Sun.COM /*
146511337SWilliam.Krier@Sun.COM  * samr_s_CreateDomainAlias
146611337SWilliam.Krier@Sun.COM  *
1467*12065SKeyur.Desai@Sun.COM  * Create a local group in the security accounts manager (SAM) database.
1468*12065SKeyur.Desai@Sun.COM  * A local SAM group can only be added if a Solaris group already exists
1469*12065SKeyur.Desai@Sun.COM  * with the same name.  On success, a valid group handle is returned.
1470*12065SKeyur.Desai@Sun.COM  *
1471*12065SKeyur.Desai@Sun.COM  * The caller must have administrator rights to execute this function.
147211337SWilliam.Krier@Sun.COM  */
147311337SWilliam.Krier@Sun.COM static int
147411337SWilliam.Krier@Sun.COM samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
147511337SWilliam.Krier@Sun.COM {
147611337SWilliam.Krier@Sun.COM 	struct samr_CreateDomainAlias *param = arg;
147711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1478*12065SKeyur.Desai@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
1479*12065SKeyur.Desai@Sun.COM 	smb_group_t grp;
1480*12065SKeyur.Desai@Sun.COM 	uint32_t rc;
1481*12065SKeyur.Desai@Sun.COM 	char *gname;
148211337SWilliam.Krier@Sun.COM 
1483*12065SKeyur.Desai@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
148411337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_CreateDomainAlias));
148511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
148611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
148711337SWilliam.Krier@Sun.COM 	}
148811337SWilliam.Krier@Sun.COM 
1489*12065SKeyur.Desai@Sun.COM 	gname = (char *)param->alias_name.str;
1490*12065SKeyur.Desai@Sun.COM 	if (gname == NULL) {
1491*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1492*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1493*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1494*12065SKeyur.Desai@Sun.COM 	}
149511337SWilliam.Krier@Sun.COM 
1496*12065SKeyur.Desai@Sun.COM 	if ((!ndr_is_admin(mxa)) ||
1497*12065SKeyur.Desai@Sun.COM 	    ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) {
1498*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1499*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1500*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1501*12065SKeyur.Desai@Sun.COM 	}
150211337SWilliam.Krier@Sun.COM 
1503*12065SKeyur.Desai@Sun.COM 	if (getgrnam(gname) == NULL) {
1504*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1505*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1506*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
150711337SWilliam.Krier@Sun.COM 	}
150811337SWilliam.Krier@Sun.COM 
1509*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_add(gname, "");
1510*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
1511*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1512*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
1513*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
1514*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
151511337SWilliam.Krier@Sun.COM 	}
151611337SWilliam.Krier@Sun.COM 
1517*12065SKeyur.Desai@Sun.COM 	rc = smb_lgrp_getbyname((char *)gname, &grp);
1518*12065SKeyur.Desai@Sun.COM 	if (rc != SMB_LGRP_SUCCESS) {
1519*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1520*12065SKeyur.Desai@Sun.COM 		status = smb_lgrp_err_to_ntstatus(rc);
1521*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(status);
1522*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1523*12065SKeyur.Desai@Sun.COM 	}
152411337SWilliam.Krier@Sun.COM 
1525*12065SKeyur.Desai@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid);
1526*12065SKeyur.Desai@Sun.COM 	smb_lgrp_free(&grp);
1527*12065SKeyur.Desai@Sun.COM 	if (id) {
1528*12065SKeyur.Desai@Sun.COM 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1529*12065SKeyur.Desai@Sun.COM 		param->status = status;
1530*12065SKeyur.Desai@Sun.COM 	} else {
1531*12065SKeyur.Desai@Sun.COM 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1532*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1533*12065SKeyur.Desai@Sun.COM 	}
153411337SWilliam.Krier@Sun.COM 
153511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
153611337SWilliam.Krier@Sun.COM }
153711337SWilliam.Krier@Sun.COM 
153811337SWilliam.Krier@Sun.COM /*
153911337SWilliam.Krier@Sun.COM  * samr_s_SetAliasInfo
154011337SWilliam.Krier@Sun.COM  *
154111337SWilliam.Krier@Sun.COM  * Similar to NetLocalGroupSetInfo.
154211337SWilliam.Krier@Sun.COM  */
154311337SWilliam.Krier@Sun.COM static int
154411337SWilliam.Krier@Sun.COM samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
154511337SWilliam.Krier@Sun.COM {
154611337SWilliam.Krier@Sun.COM 	struct samr_SetAliasInfo *param = arg;
154711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
154811337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
154911337SWilliam.Krier@Sun.COM 
155011337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
155111337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
155211337SWilliam.Krier@Sun.COM 
155311337SWilliam.Krier@Sun.COM 	param->status = status;
155411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
155511337SWilliam.Krier@Sun.COM }
155611337SWilliam.Krier@Sun.COM 
155711337SWilliam.Krier@Sun.COM /*
155811337SWilliam.Krier@Sun.COM  * samr_s_QueryAliasInfo
155911337SWilliam.Krier@Sun.COM  *
156011337SWilliam.Krier@Sun.COM  * Retrieves information about the specified local group account
156111337SWilliam.Krier@Sun.COM  * by given handle.
156211337SWilliam.Krier@Sun.COM  */
156311337SWilliam.Krier@Sun.COM static int
156411337SWilliam.Krier@Sun.COM samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
156511337SWilliam.Krier@Sun.COM {
156611337SWilliam.Krier@Sun.COM 	struct samr_QueryAliasInfo *param = arg;
156711447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
156811447Samw@Sun.COM 	ndr_handle_t	*hd;
156911447Samw@Sun.COM 	samr_keydata_t	*data;
157011447Samw@Sun.COM 	smb_group_t	grp;
157111963SAfshin.Ardakani@Sun.COM 	smb_domain_type_t gd_type;
157211447Samw@Sun.COM 	smb_sid_t	*sid;
157311447Samw@Sun.COM 	smb_wka_t	*wka;
157411447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
157511447Samw@Sun.COM 	char		*name;
157611447Samw@Sun.COM 	char		*desc;
157711447Samw@Sun.COM 	uint32_t	rid;
157811447Samw@Sun.COM 	uint32_t	status;
157911447Samw@Sun.COM 	int		rc;
158011337SWilliam.Krier@Sun.COM 
158111337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
158211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
158311337SWilliam.Krier@Sun.COM 		goto query_alias_err;
158411337SWilliam.Krier@Sun.COM 	}
158511337SWilliam.Krier@Sun.COM 
158611337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
158711963SAfshin.Ardakani@Sun.COM 	gd_type = (smb_domain_type_t)data->kd_type;
158811447Samw@Sun.COM 	rid = data->kd_rid;
158911447Samw@Sun.COM 
159011447Samw@Sun.COM 	switch (gd_type) {
159111963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_BUILTIN:
159211447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
159311447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
159411447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
159511447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
159611447Samw@Sun.COM 			goto query_alias_err;
159711447Samw@Sun.COM 		}
159811447Samw@Sun.COM 
159911447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
160011447Samw@Sun.COM 		smb_sid_free(sid);
160111447Samw@Sun.COM 
160211447Samw@Sun.COM 		if (wka == NULL) {
160311447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
160411447Samw@Sun.COM 			goto query_alias_err;
160511447Samw@Sun.COM 		}
160611447Samw@Sun.COM 
160711447Samw@Sun.COM 		name = wka->wka_name;
160811447Samw@Sun.COM 		desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
160911447Samw@Sun.COM 		break;
161011447Samw@Sun.COM 
161111963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_LOCAL:
161211447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
161311447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
161411447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
161511447Samw@Sun.COM 			goto query_alias_err;
161611447Samw@Sun.COM 		}
161711447Samw@Sun.COM 		name = grp.sg_name;
161811447Samw@Sun.COM 		desc = grp.sg_cmnt;
161911447Samw@Sun.COM 		break;
162011447Samw@Sun.COM 
162111447Samw@Sun.COM 	default:
162211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
162311337SWilliam.Krier@Sun.COM 		goto query_alias_err;
162411337SWilliam.Krier@Sun.COM 	}
162511337SWilliam.Krier@Sun.COM 
162611337SWilliam.Krier@Sun.COM 	switch (param->level) {
162711337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_1:
162811337SWilliam.Krier@Sun.COM 		param->ru.info1.level = param->level;
162911447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, name,
163011337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.name);
163111337SWilliam.Krier@Sun.COM 
163211447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
163311337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.desc);
163411337SWilliam.Krier@Sun.COM 
163511337SWilliam.Krier@Sun.COM 		param->ru.info1.unknown = 1;
163611337SWilliam.Krier@Sun.COM 		break;
163711337SWilliam.Krier@Sun.COM 
163811337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_3:
163911337SWilliam.Krier@Sun.COM 		param->ru.info3.level = param->level;
164011447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
164111337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info3.desc);
164211337SWilliam.Krier@Sun.COM 		break;
164311337SWilliam.Krier@Sun.COM 
164411337SWilliam.Krier@Sun.COM 	default:
164511963SAfshin.Ardakani@Sun.COM 		if (gd_type == SMB_DOMAIN_LOCAL)
164611447Samw@Sun.COM 			smb_lgrp_free(&grp);
164711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
164811337SWilliam.Krier@Sun.COM 		goto query_alias_err;
164911337SWilliam.Krier@Sun.COM 	};
165011337SWilliam.Krier@Sun.COM 
165111963SAfshin.Ardakani@Sun.COM 	if (gd_type == SMB_DOMAIN_LOCAL)
165211447Samw@Sun.COM 		smb_lgrp_free(&grp);
165311337SWilliam.Krier@Sun.COM 	param->address = (DWORD)(uintptr_t)&param->ru;
165411337SWilliam.Krier@Sun.COM 	param->status = 0;
165511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
165611337SWilliam.Krier@Sun.COM 
165711337SWilliam.Krier@Sun.COM query_alias_err:
165811337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
165911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
166011337SWilliam.Krier@Sun.COM }
166111337SWilliam.Krier@Sun.COM 
166211337SWilliam.Krier@Sun.COM /*
166311337SWilliam.Krier@Sun.COM  * samr_s_DeleteDomainAlias
166411337SWilliam.Krier@Sun.COM  *
1665*12065SKeyur.Desai@Sun.COM  * Deletes a local group in the security database, which is the
1666*12065SKeyur.Desai@Sun.COM  * security accounts manager (SAM). A valid group handle is returned
1667*12065SKeyur.Desai@Sun.COM  * to the caller upon success.
166811337SWilliam.Krier@Sun.COM  *
1669*12065SKeyur.Desai@Sun.COM  * The caller must have administrator rights to execute this function.
167011337SWilliam.Krier@Sun.COM  */
167111337SWilliam.Krier@Sun.COM static int
167211337SWilliam.Krier@Sun.COM samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
167311337SWilliam.Krier@Sun.COM {
167411337SWilliam.Krier@Sun.COM 	struct samr_DeleteDomainAlias *param = arg;
167511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1676*12065SKeyur.Desai@Sun.COM 	ndr_handle_t	*hd;
1677*12065SKeyur.Desai@Sun.COM 	smb_group_t grp;
1678*12065SKeyur.Desai@Sun.COM 	samr_keydata_t	*data;
1679*12065SKeyur.Desai@Sun.COM 	smb_domain_type_t	gd_type;
1680*12065SKeyur.Desai@Sun.COM 	uint32_t	rid;
1681*12065SKeyur.Desai@Sun.COM 	uint32_t	rc;
1682*12065SKeyur.Desai@Sun.COM 	uint32_t	status = NT_STATUS_SUCCESS;
168311337SWilliam.Krier@Sun.COM 
1684*12065SKeyur.Desai@Sun.COM 	if (!ndr_is_admin(mxa)) {
1685*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1686*12065SKeyur.Desai@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1687*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_OK);
1688*12065SKeyur.Desai@Sun.COM 	}
1689*12065SKeyur.Desai@Sun.COM 
1690*12065SKeyur.Desai@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
169111337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
169211337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
169311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
169411337SWilliam.Krier@Sun.COM 	}
169511337SWilliam.Krier@Sun.COM 
1696*12065SKeyur.Desai@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1697*12065SKeyur.Desai@Sun.COM 	gd_type = (smb_domain_type_t)data->kd_type;
1698*12065SKeyur.Desai@Sun.COM 	rid = data->kd_rid;
1699*12065SKeyur.Desai@Sun.COM 
1700*12065SKeyur.Desai@Sun.COM 	switch (gd_type) {
1701*12065SKeyur.Desai@Sun.COM 	case SMB_DOMAIN_BUILTIN:
1702*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1703*12065SKeyur.Desai@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1704*12065SKeyur.Desai@Sun.COM 		break;
170511337SWilliam.Krier@Sun.COM 
1706*12065SKeyur.Desai@Sun.COM 	case SMB_DOMAIN_LOCAL:
1707*12065SKeyur.Desai@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1708*12065SKeyur.Desai@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
1709*12065SKeyur.Desai@Sun.COM 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1710*12065SKeyur.Desai@Sun.COM 			status = smb_lgrp_err_to_ntstatus(rc);
1711*12065SKeyur.Desai@Sun.COM 			status = NT_SC_ERROR(status);
1712*12065SKeyur.Desai@Sun.COM 			break;
1713*12065SKeyur.Desai@Sun.COM 		}
171411337SWilliam.Krier@Sun.COM 
1715*12065SKeyur.Desai@Sun.COM 		rc = smb_lgrp_delete(grp.sg_name);
1716*12065SKeyur.Desai@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
1717*12065SKeyur.Desai@Sun.COM 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1718*12065SKeyur.Desai@Sun.COM 			status = smb_lgrp_err_to_ntstatus(rc);
1719*12065SKeyur.Desai@Sun.COM 			status = NT_SC_ERROR(status);
1720*12065SKeyur.Desai@Sun.COM 		}
1721*12065SKeyur.Desai@Sun.COM 		smb_lgrp_free(&grp);
1722*12065SKeyur.Desai@Sun.COM 		break;
1723*12065SKeyur.Desai@Sun.COM 
1724*12065SKeyur.Desai@Sun.COM 	default:
1725*12065SKeyur.Desai@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1726*12065SKeyur.Desai@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
172711337SWilliam.Krier@Sun.COM 	}
172811337SWilliam.Krier@Sun.COM 
1729*12065SKeyur.Desai@Sun.COM 	param->status = status;
173011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
173111337SWilliam.Krier@Sun.COM }
173211337SWilliam.Krier@Sun.COM 
173311337SWilliam.Krier@Sun.COM /*
173411337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainAliases
173511337SWilliam.Krier@Sun.COM  *
173611337SWilliam.Krier@Sun.COM  * This function sends back a list which contains all local groups' name.
173711337SWilliam.Krier@Sun.COM  */
173811337SWilliam.Krier@Sun.COM static int
173911337SWilliam.Krier@Sun.COM samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
174011337SWilliam.Krier@Sun.COM {
174111337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainAliases *param = arg;
174211337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
174311337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
174411337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
174511337SWilliam.Krier@Sun.COM 	smb_group_t grp;
174611337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
174711337SWilliam.Krier@Sun.COM 	int cnt, skip, i;
174811337SWilliam.Krier@Sun.COM 	struct name_rid *info;
174911337SWilliam.Krier@Sun.COM 
175011337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
175111337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
175211337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
175311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
175411337SWilliam.Krier@Sun.COM 	}
175511337SWilliam.Krier@Sun.COM 
175611337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
175711337SWilliam.Krier@Sun.COM 
175811337SWilliam.Krier@Sun.COM 	cnt = smb_sam_grp_cnt(data->kd_type);
175911337SWilliam.Krier@Sun.COM 	if (cnt <= param->resume_handle) {
176011337SWilliam.Krier@Sun.COM 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
176111337SWilliam.Krier@Sun.COM 		    sizeof (struct aliases_info));
176211337SWilliam.Krier@Sun.COM 
176311337SWilliam.Krier@Sun.COM 		if (param->aliases == NULL) {
176411337SWilliam.Krier@Sun.COM 			bzero(param, sizeof (struct samr_EnumDomainAliases));
176511337SWilliam.Krier@Sun.COM 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
176611337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
176711337SWilliam.Krier@Sun.COM 		}
176811337SWilliam.Krier@Sun.COM 
176911337SWilliam.Krier@Sun.COM 		bzero(param->aliases, sizeof (struct aliases_info));
177011337SWilliam.Krier@Sun.COM 		param->out_resume = 0;
177111337SWilliam.Krier@Sun.COM 		param->entries = 0;
177211337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
177311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
177411337SWilliam.Krier@Sun.COM 	}
177511337SWilliam.Krier@Sun.COM 
177611337SWilliam.Krier@Sun.COM 	cnt -= param->resume_handle;
177711337SWilliam.Krier@Sun.COM 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
177811337SWilliam.Krier@Sun.COM 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
177911337SWilliam.Krier@Sun.COM 
178011337SWilliam.Krier@Sun.COM 	if (param->aliases == NULL) {
178111337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
178211337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
178311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
178411337SWilliam.Krier@Sun.COM 	}
178511337SWilliam.Krier@Sun.COM 
178611337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
178711337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
178811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
178911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
179011337SWilliam.Krier@Sun.COM 	}
179111337SWilliam.Krier@Sun.COM 
179211337SWilliam.Krier@Sun.COM 	skip = i = 0;
179311337SWilliam.Krier@Sun.COM 	info = param->aliases->info;
179411337SWilliam.Krier@Sun.COM 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
179511337SWilliam.Krier@Sun.COM 		if ((skip++ >= param->resume_handle) &&
179611337SWilliam.Krier@Sun.COM 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
179711337SWilliam.Krier@Sun.COM 			info->rid = grp.sg_rid;
179811337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, grp.sg_name,
179911337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&info->name);
180011337SWilliam.Krier@Sun.COM 
180111337SWilliam.Krier@Sun.COM 			info++;
180211337SWilliam.Krier@Sun.COM 		}
180311337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
180411337SWilliam.Krier@Sun.COM 	}
180511337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
180611337SWilliam.Krier@Sun.COM 
180711337SWilliam.Krier@Sun.COM 	param->aliases->count = i;
180811337SWilliam.Krier@Sun.COM 	param->aliases->address = i;
180911337SWilliam.Krier@Sun.COM 
181011337SWilliam.Krier@Sun.COM 	param->out_resume = i;
181111337SWilliam.Krier@Sun.COM 	param->entries = i;
181211337SWilliam.Krier@Sun.COM 	param->status = 0;
181311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
181411337SWilliam.Krier@Sun.COM }
181511337SWilliam.Krier@Sun.COM 
181611337SWilliam.Krier@Sun.COM /*
181711337SWilliam.Krier@Sun.COM  * samr_s_Connect3
181811337SWilliam.Krier@Sun.COM  */
181911337SWilliam.Krier@Sun.COM static int
182011337SWilliam.Krier@Sun.COM samr_s_Connect3(void *arg, ndr_xa_t *mxa)
182111337SWilliam.Krier@Sun.COM {
182211447Samw@Sun.COM 	struct samr_Connect3	*param = arg;
182311447Samw@Sun.COM 	ndr_hdid_t		*id;
182411337SWilliam.Krier@Sun.COM 
182511447Samw@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
182611447Samw@Sun.COM 	if (id) {
182711447Samw@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
182811447Samw@Sun.COM 		param->status = 0;
182911447Samw@Sun.COM 	} else {
183011447Samw@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
183111447Samw@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
183211447Samw@Sun.COM 	}
183311447Samw@Sun.COM 
183411447Samw@Sun.COM 	return (NDR_DRC_OK);
183511337SWilliam.Krier@Sun.COM }
183611337SWilliam.Krier@Sun.COM 
183711337SWilliam.Krier@Sun.COM /*
183811337SWilliam.Krier@Sun.COM  * samr_s_Connect4
183911337SWilliam.Krier@Sun.COM  *
184011337SWilliam.Krier@Sun.COM  * This is the connect4 form of the connect request used by Windows XP.
184111337SWilliam.Krier@Sun.COM  * Returns an RPC fault for now.
184211337SWilliam.Krier@Sun.COM  */
184311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
184411337SWilliam.Krier@Sun.COM static int
184511337SWilliam.Krier@Sun.COM samr_s_Connect4(void *arg, ndr_xa_t *mxa)
184611337SWilliam.Krier@Sun.COM {
184711337SWilliam.Krier@Sun.COM 	struct samr_Connect4 *param = arg;
184811337SWilliam.Krier@Sun.COM 
184911337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_Connect4));
185011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
185111337SWilliam.Krier@Sun.COM }
185211337SWilliam.Krier@Sun.COM 
185311337SWilliam.Krier@Sun.COM static ndr_stub_table_t samr_stub_table[] = {
185411337SWilliam.Krier@Sun.COM 	{ samr_s_ConnectAnon,		SAMR_OPNUM_ConnectAnon },
185511337SWilliam.Krier@Sun.COM 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
185611337SWilliam.Krier@Sun.COM 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
185711337SWilliam.Krier@Sun.COM 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
185811337SWilliam.Krier@Sun.COM 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
185911337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
186011447Samw@Sun.COM 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
186111337SWilliam.Krier@Sun.COM 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
186211337SWilliam.Krier@Sun.COM 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
186311337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
186411337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
186511337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
186611337SWilliam.Krier@Sun.COM 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
186711337SWilliam.Krier@Sun.COM 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
186811337SWilliam.Krier@Sun.COM 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
186911337SWilliam.Krier@Sun.COM 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
187011337SWilliam.Krier@Sun.COM 	{ samr_s_ChangeUserPasswd,	SAMR_OPNUM_ChangeUserPasswd },
187111337SWilliam.Krier@Sun.COM 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
187211337SWilliam.Krier@Sun.COM 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
187311337SWilliam.Krier@Sun.COM 	{ samr_s_Connect3,		SAMR_OPNUM_Connect3 },
187411337SWilliam.Krier@Sun.COM 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
187511337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
187611337SWilliam.Krier@Sun.COM 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
187711337SWilliam.Krier@Sun.COM 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
187811337SWilliam.Krier@Sun.COM 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
187911337SWilliam.Krier@Sun.COM 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
188011337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
188111337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
188211337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainGroups,	SAMR_OPNUM_EnumDomainGroups },
1883*12065SKeyur.Desai@Sun.COM 	{ samr_s_AddAliasMember,	SAMR_OPNUM_AddAliasMember },
1884*12065SKeyur.Desai@Sun.COM 	{ samr_s_DeleteAliasMember,	SAMR_OPNUM_DeleteAliasMember },
1885*12065SKeyur.Desai@Sun.COM 	{ samr_s_ListAliasMembers,	SAMR_OPNUM_ListAliasMembers },
188611337SWilliam.Krier@Sun.COM 	{0}
188711337SWilliam.Krier@Sun.COM };
188811337SWilliam.Krier@Sun.COM 
188911337SWilliam.Krier@Sun.COM /*
189011337SWilliam.Krier@Sun.COM  * There is a bug in the way that midl and the marshalling code handles
189111337SWilliam.Krier@Sun.COM  * unions so we need to fix some of the data offsets at runtime. The
189211337SWilliam.Krier@Sun.COM  * following macros and the fixup functions handle the corrections.
189311337SWilliam.Krier@Sun.COM  */
189411337SWilliam.Krier@Sun.COM 
189511337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
189611337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
189711337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
189811337SWilliam.Krier@Sun.COM 
189911337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
190011337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result);
190111337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryUserInfo);
190211337SWilliam.Krier@Sun.COM 
190311337SWilliam.Krier@Sun.COM void
190411337SWilliam.Krier@Sun.COM fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
190511337SWilliam.Krier@Sun.COM {
190611337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
190711337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
190811337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
190911337SWilliam.Krier@Sun.COM 
191011337SWilliam.Krier@Sun.COM 	switch (val->level) {
191111337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 1);
191211337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 3);
191311337SWilliam.Krier@Sun.COM 
191411337SWilliam.Krier@Sun.COM 		default:
191511337SWilliam.Krier@Sun.COM 			return;
191611337SWilliam.Krier@Sun.COM 	};
191711337SWilliam.Krier@Sun.COM 
191811337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
191911337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
192011337SWilliam.Krier@Sun.COM 
192111337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
192211337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
192311337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
192411337SWilliam.Krier@Sun.COM }
192511337SWilliam.Krier@Sun.COM 
192611337SWilliam.Krier@Sun.COM void
192711337SWilliam.Krier@Sun.COM fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
192811337SWilliam.Krier@Sun.COM {
192911337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
193011337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
193111337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
193211337SWilliam.Krier@Sun.COM 
193311337SWilliam.Krier@Sun.COM 	switch (val->switch_index) {
193411337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
193511337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
193611337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
193711337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
193811337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
193911337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
194011337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
194111337SWilliam.Krier@Sun.COM 
194211337SWilliam.Krier@Sun.COM 		default:
194311337SWilliam.Krier@Sun.COM 			return;
194411337SWilliam.Krier@Sun.COM 	};
194511337SWilliam.Krier@Sun.COM 
194611337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
194711337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
194811337SWilliam.Krier@Sun.COM 
194911337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
195011337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
195111337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
195211337SWilliam.Krier@Sun.COM }
195311337SWilliam.Krier@Sun.COM 
195411337SWilliam.Krier@Sun.COM /*
195511337SWilliam.Krier@Sun.COM  * As long as there is only one entry in the union, there is no need
195611337SWilliam.Krier@Sun.COM  * to patch anything.
195711337SWilliam.Krier@Sun.COM  */
195811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
195911337SWilliam.Krier@Sun.COM void
196011337SWilliam.Krier@Sun.COM fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
196111337SWilliam.Krier@Sun.COM {
196211337SWilliam.Krier@Sun.COM }
1963