xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (revision 11447:b5b2a9bd508f)
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*11447Samw@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2311337SWilliam.Krier@Sun.COM  * Use is subject to license terms.
2411337SWilliam.Krier@Sun.COM  */
2511337SWilliam.Krier@Sun.COM 
2611337SWilliam.Krier@Sun.COM /*
2711337SWilliam.Krier@Sun.COM  * Security Accounts Manager RPC (SAMR) server-side interface.
2811337SWilliam.Krier@Sun.COM  *
2911337SWilliam.Krier@Sun.COM  * The SAM is a hierarchical database:
3011337SWilliam.Krier@Sun.COM  * - If you want to talk to the SAM you need a SAM handle.
3111337SWilliam.Krier@Sun.COM  * - If you want to work with a domain, use the SAM handle.
3211337SWilliam.Krier@Sun.COM  *   to obtain a domain handle.
3311337SWilliam.Krier@Sun.COM  * - Use domain handles to obtain user handles etc.
3411337SWilliam.Krier@Sun.COM  */
3511337SWilliam.Krier@Sun.COM 
3611337SWilliam.Krier@Sun.COM #include <strings.h>
3711337SWilliam.Krier@Sun.COM #include <unistd.h>
3811337SWilliam.Krier@Sun.COM #include <netdb.h>
3911337SWilliam.Krier@Sun.COM #include <assert.h>
4011337SWilliam.Krier@Sun.COM 
4111337SWilliam.Krier@Sun.COM #include <smbsrv/libsmb.h>
4211337SWilliam.Krier@Sun.COM #include <smbsrv/libmlrpc.h>
4311337SWilliam.Krier@Sun.COM #include <smbsrv/libmlsvc.h>
4411337SWilliam.Krier@Sun.COM #include <smbsrv/ntstatus.h>
4511337SWilliam.Krier@Sun.COM #include <smbsrv/nterror.h>
4611337SWilliam.Krier@Sun.COM #include <smbsrv/smbinfo.h>
4711337SWilliam.Krier@Sun.COM #include <smbsrv/nmpipes.h>
4811337SWilliam.Krier@Sun.COM #include <smbsrv/ndl/samrpc.ndl>
4911337SWilliam.Krier@Sun.COM #include <samlib.h>
5011337SWilliam.Krier@Sun.COM 
5111337SWilliam.Krier@Sun.COM /*
5211337SWilliam.Krier@Sun.COM  * The keys associated with the various handles dispensed by the SAMR
5311337SWilliam.Krier@Sun.COM  * server.  These keys can be used to validate client activity.
5411337SWilliam.Krier@Sun.COM  * These values are never passed over the wire so security shouldn't
5511337SWilliam.Krier@Sun.COM  * be an issue.
5611337SWilliam.Krier@Sun.COM  */
5711337SWilliam.Krier@Sun.COM typedef enum {
5811337SWilliam.Krier@Sun.COM 	SAMR_KEY_NULL = 0,
5911337SWilliam.Krier@Sun.COM 	SAMR_KEY_CONNECT,
6011337SWilliam.Krier@Sun.COM 	SAMR_KEY_DOMAIN,
6111337SWilliam.Krier@Sun.COM 	SAMR_KEY_USER,
6211337SWilliam.Krier@Sun.COM 	SAMR_KEY_GROUP,
6311337SWilliam.Krier@Sun.COM 	SAMR_KEY_ALIAS
6411337SWilliam.Krier@Sun.COM } samr_key_t;
6511337SWilliam.Krier@Sun.COM 
6611337SWilliam.Krier@Sun.COM typedef struct samr_keydata {
6711337SWilliam.Krier@Sun.COM 	samr_key_t kd_key;
6811337SWilliam.Krier@Sun.COM 	smb_domain_type_t kd_type;
6911337SWilliam.Krier@Sun.COM 	DWORD kd_rid;
7011337SWilliam.Krier@Sun.COM } samr_keydata_t;
7111337SWilliam.Krier@Sun.COM 
7211337SWilliam.Krier@Sun.COM /*
7311337SWilliam.Krier@Sun.COM  * DomainDisplayUser	All user objects (or those derived from user) with
7411337SWilliam.Krier@Sun.COM  * 			userAccountControl containing the UF_NORMAL_ACCOUNT bit.
7511337SWilliam.Krier@Sun.COM  *
7611337SWilliam.Krier@Sun.COM  * DomainDisplayMachine	All user objects (or those derived from user) with
7711337SWilliam.Krier@Sun.COM  * 			userAccountControl containing the
7811337SWilliam.Krier@Sun.COM  * 			UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
7911337SWilliam.Krier@Sun.COM  * 			bit.
8011337SWilliam.Krier@Sun.COM  *
8111337SWilliam.Krier@Sun.COM  * DomainDisplayGroup	All group objects (or those derived from group) with
8211337SWilliam.Krier@Sun.COM  * 			groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
8311337SWilliam.Krier@Sun.COM  * 			GROUP_TYPE_SECURITY_ACCOUNT.
8411337SWilliam.Krier@Sun.COM  *
8511337SWilliam.Krier@Sun.COM  * DomainDisplayOemUser	Same as DomainDisplayUser with OEM strings
8611337SWilliam.Krier@Sun.COM  *
8711337SWilliam.Krier@Sun.COM  * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
8811337SWilliam.Krier@Sun.COM  */
8911337SWilliam.Krier@Sun.COM typedef enum {
9011337SWilliam.Krier@Sun.COM 	DomainDisplayUser = 1,
9111337SWilliam.Krier@Sun.COM 	DomainDisplayMachine,
9211337SWilliam.Krier@Sun.COM 	DomainDispalyGroup,
9311337SWilliam.Krier@Sun.COM 	DomainDisplayOemUser,
9411337SWilliam.Krier@Sun.COM 	DomainDisplayOemGroup
9511337SWilliam.Krier@Sun.COM } samr_displvl_t;
9611337SWilliam.Krier@Sun.COM 
9711337SWilliam.Krier@Sun.COM #define	SAMR_VALID_DISPLEVEL(lvl) \
9811337SWilliam.Krier@Sun.COM 	(((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
9911337SWilliam.Krier@Sun.COM 
10011337SWilliam.Krier@Sun.COM #define	SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
10111337SWilliam.Krier@Sun.COM 
10211337SWilliam.Krier@Sun.COM static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
10311337SWilliam.Krier@Sun.COM     DWORD);
10411337SWilliam.Krier@Sun.COM static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
10511337SWilliam.Krier@Sun.COM static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
10611337SWilliam.Krier@Sun.COM static int samr_call_stub(ndr_xa_t *mxa);
10711337SWilliam.Krier@Sun.COM static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
10811337SWilliam.Krier@Sun.COM     ndr_xa_t *);
10911337SWilliam.Krier@Sun.COM 
11011337SWilliam.Krier@Sun.COM static ndr_stub_table_t samr_stub_table[];
11111337SWilliam.Krier@Sun.COM 
11211337SWilliam.Krier@Sun.COM static ndr_service_t samr_service = {
11311337SWilliam.Krier@Sun.COM 	"SAMR",				/* name */
11411337SWilliam.Krier@Sun.COM 	"Security Accounts Manager",	/* desc */
11511337SWilliam.Krier@Sun.COM 	"\\samr",			/* endpoint */
11611337SWilliam.Krier@Sun.COM 	PIPE_LSASS,			/* sec_addr_port */
11711337SWilliam.Krier@Sun.COM 	"12345778-1234-abcd-ef00-0123456789ac", 1,	/* abstract */
11811337SWilliam.Krier@Sun.COM 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
11911337SWilliam.Krier@Sun.COM 	0,				/* no bind_instance_size */
12011337SWilliam.Krier@Sun.COM 	NULL,				/* no bind_req() */
12111337SWilliam.Krier@Sun.COM 	NULL,				/* no unbind_and_close() */
12211337SWilliam.Krier@Sun.COM 	samr_call_stub,			/* call_stub() */
12311337SWilliam.Krier@Sun.COM 	&TYPEINFO(samr_interface),	/* interface ti */
12411337SWilliam.Krier@Sun.COM 	samr_stub_table			/* stub_table */
12511337SWilliam.Krier@Sun.COM };
12611337SWilliam.Krier@Sun.COM 
12711337SWilliam.Krier@Sun.COM /*
12811337SWilliam.Krier@Sun.COM  * samr_initialize
12911337SWilliam.Krier@Sun.COM  *
13011337SWilliam.Krier@Sun.COM  * This function registers the SAM RPC interface with the RPC runtime
13111337SWilliam.Krier@Sun.COM  * library. It must be called in order to use either the client side
13211337SWilliam.Krier@Sun.COM  * or the server side functions.
13311337SWilliam.Krier@Sun.COM  */
13411337SWilliam.Krier@Sun.COM void
13511337SWilliam.Krier@Sun.COM samr_initialize(void)
13611337SWilliam.Krier@Sun.COM {
13711337SWilliam.Krier@Sun.COM 	(void) ndr_svc_register(&samr_service);
13811337SWilliam.Krier@Sun.COM }
13911337SWilliam.Krier@Sun.COM 
14011337SWilliam.Krier@Sun.COM /*
14111337SWilliam.Krier@Sun.COM  * Custom call_stub to set the stream string policy.
14211337SWilliam.Krier@Sun.COM  */
14311337SWilliam.Krier@Sun.COM static int
14411337SWilliam.Krier@Sun.COM samr_call_stub(ndr_xa_t *mxa)
14511337SWilliam.Krier@Sun.COM {
14611337SWilliam.Krier@Sun.COM 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
14711337SWilliam.Krier@Sun.COM 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
14811337SWilliam.Krier@Sun.COM 
14911337SWilliam.Krier@Sun.COM 	return (ndr_generic_call_stub(mxa));
15011337SWilliam.Krier@Sun.COM }
15111337SWilliam.Krier@Sun.COM 
15211337SWilliam.Krier@Sun.COM /*
15311337SWilliam.Krier@Sun.COM  * Handle allocation wrapper to setup the local context.
15411337SWilliam.Krier@Sun.COM  */
15511337SWilliam.Krier@Sun.COM static ndr_hdid_t *
15611337SWilliam.Krier@Sun.COM samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
15711337SWilliam.Krier@Sun.COM     DWORD rid)
15811337SWilliam.Krier@Sun.COM {
15911337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
16011337SWilliam.Krier@Sun.COM 
16111337SWilliam.Krier@Sun.COM 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
16211337SWilliam.Krier@Sun.COM 		return (NULL);
16311337SWilliam.Krier@Sun.COM 
16411337SWilliam.Krier@Sun.COM 	data->kd_key = key;
16511337SWilliam.Krier@Sun.COM 	data->kd_type = domain_type;
16611337SWilliam.Krier@Sun.COM 	data->kd_rid = rid;
16711337SWilliam.Krier@Sun.COM 
16811337SWilliam.Krier@Sun.COM 	return (ndr_hdalloc(mxa, data));
16911337SWilliam.Krier@Sun.COM }
17011337SWilliam.Krier@Sun.COM 
17111337SWilliam.Krier@Sun.COM /*
17211337SWilliam.Krier@Sun.COM  * Handle deallocation wrapper to free the local context.
17311337SWilliam.Krier@Sun.COM  */
17411337SWilliam.Krier@Sun.COM static void
17511337SWilliam.Krier@Sun.COM samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
17611337SWilliam.Krier@Sun.COM {
17711337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
17811337SWilliam.Krier@Sun.COM 
17911337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
18011337SWilliam.Krier@Sun.COM 		free(hd->nh_data);
18111337SWilliam.Krier@Sun.COM 		ndr_hdfree(mxa, id);
18211337SWilliam.Krier@Sun.COM 	}
18311337SWilliam.Krier@Sun.COM }
18411337SWilliam.Krier@Sun.COM 
18511337SWilliam.Krier@Sun.COM /*
18611337SWilliam.Krier@Sun.COM  * Handle lookup wrapper to validate the local context.
18711337SWilliam.Krier@Sun.COM  */
18811337SWilliam.Krier@Sun.COM static ndr_handle_t *
18911337SWilliam.Krier@Sun.COM samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
19011337SWilliam.Krier@Sun.COM {
19111337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
19211337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
19311337SWilliam.Krier@Sun.COM 
19411337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
19511337SWilliam.Krier@Sun.COM 		return (NULL);
19611337SWilliam.Krier@Sun.COM 
19711337SWilliam.Krier@Sun.COM 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
19811337SWilliam.Krier@Sun.COM 		return (NULL);
19911337SWilliam.Krier@Sun.COM 
20011337SWilliam.Krier@Sun.COM 	if (data->kd_key != key)
20111337SWilliam.Krier@Sun.COM 		return (NULL);
20211337SWilliam.Krier@Sun.COM 
20311337SWilliam.Krier@Sun.COM 	return (hd);
20411337SWilliam.Krier@Sun.COM }
20511337SWilliam.Krier@Sun.COM 
20611337SWilliam.Krier@Sun.COM /*
20711337SWilliam.Krier@Sun.COM  * samr_s_ConnectAnon
20811337SWilliam.Krier@Sun.COM  *
20911337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database. We don't
21011337SWilliam.Krier@Sun.COM  * support any form of update request and our database doesn't
21111337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in
21211337SWilliam.Krier@Sun.COM  * doing any access access checking here.
21311337SWilliam.Krier@Sun.COM  *
21411337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
21511337SWilliam.Krier@Sun.COM  */
21611337SWilliam.Krier@Sun.COM static int
21711337SWilliam.Krier@Sun.COM samr_s_ConnectAnon(void *arg, ndr_xa_t *mxa)
21811337SWilliam.Krier@Sun.COM {
21911337SWilliam.Krier@Sun.COM 	struct samr_ConnectAnon *param = arg;
22011337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
22111337SWilliam.Krier@Sun.COM 
22211337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
22311337SWilliam.Krier@Sun.COM 	if (id) {
22411337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
22511337SWilliam.Krier@Sun.COM 		param->status = 0;
22611337SWilliam.Krier@Sun.COM 	} else {
22711337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
22811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
22911337SWilliam.Krier@Sun.COM 	}
23011337SWilliam.Krier@Sun.COM 
23111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
23211337SWilliam.Krier@Sun.COM }
23311337SWilliam.Krier@Sun.COM 
23411337SWilliam.Krier@Sun.COM /*
23511337SWilliam.Krier@Sun.COM  * samr_s_CloseHandle
23611337SWilliam.Krier@Sun.COM  *
23711337SWilliam.Krier@Sun.COM  * Close the SAM interface specified by the handle.
23811337SWilliam.Krier@Sun.COM  * Free the handle and zero out the result handle for the client.
23911337SWilliam.Krier@Sun.COM  */
24011337SWilliam.Krier@Sun.COM static int
24111337SWilliam.Krier@Sun.COM samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
24211337SWilliam.Krier@Sun.COM {
24311337SWilliam.Krier@Sun.COM 	struct samr_CloseHandle *param = arg;
24411337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
24511337SWilliam.Krier@Sun.COM 
24611337SWilliam.Krier@Sun.COM 	samr_hdfree(mxa, id);
24711337SWilliam.Krier@Sun.COM 
24811337SWilliam.Krier@Sun.COM 	bzero(&param->result_handle, sizeof (samr_handle_t));
24911337SWilliam.Krier@Sun.COM 	param->status = 0;
25011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
25111337SWilliam.Krier@Sun.COM }
25211337SWilliam.Krier@Sun.COM 
25311337SWilliam.Krier@Sun.COM /*
25411337SWilliam.Krier@Sun.COM  * samr_s_LookupDomain
25511337SWilliam.Krier@Sun.COM  *
25611337SWilliam.Krier@Sun.COM  * This is a request to map a domain name to a domain SID. We can map
25711337SWilliam.Krier@Sun.COM  * the primary domain name, our local domain name (hostname) and the
25811337SWilliam.Krier@Sun.COM  * builtin domain names to the appropriate SID. Anything else will be
25911337SWilliam.Krier@Sun.COM  * rejected.
26011337SWilliam.Krier@Sun.COM  */
26111337SWilliam.Krier@Sun.COM static int
26211337SWilliam.Krier@Sun.COM samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
26311337SWilliam.Krier@Sun.COM {
26411337SWilliam.Krier@Sun.COM 	struct samr_LookupDomain *param = arg;
26511337SWilliam.Krier@Sun.COM 	char *domain_name;
26611337SWilliam.Krier@Sun.COM 	smb_domain_t di;
26711337SWilliam.Krier@Sun.COM 
26811337SWilliam.Krier@Sun.COM 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
26911337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
27011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
27111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
27211337SWilliam.Krier@Sun.COM 	}
27311337SWilliam.Krier@Sun.COM 
27411337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_name(domain_name, &di)) {
27511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
27611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
27711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
27811337SWilliam.Krier@Sun.COM 	}
27911337SWilliam.Krier@Sun.COM 
28011337SWilliam.Krier@Sun.COM 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
28111337SWilliam.Krier@Sun.COM 	if (param->sid == NULL) {
28211337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
28311337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
28411337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
28511337SWilliam.Krier@Sun.COM 	}
28611337SWilliam.Krier@Sun.COM 
28711337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
28811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
28911337SWilliam.Krier@Sun.COM }
29011337SWilliam.Krier@Sun.COM 
29111337SWilliam.Krier@Sun.COM /*
29211337SWilliam.Krier@Sun.COM  * samr_s_EnumLocalDomains
29311337SWilliam.Krier@Sun.COM  *
29411337SWilliam.Krier@Sun.COM  * This is a request for the local domains supported by this server.
29511337SWilliam.Krier@Sun.COM  * All we do here is validate the handle and set the status. The real
29611337SWilliam.Krier@Sun.COM  * work is done in samr_s_enum_local_domains.
29711337SWilliam.Krier@Sun.COM  */
29811337SWilliam.Krier@Sun.COM static int
29911337SWilliam.Krier@Sun.COM samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
30011337SWilliam.Krier@Sun.COM {
30111337SWilliam.Krier@Sun.COM 	struct samr_EnumLocalDomain *param = arg;
30211337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
30311337SWilliam.Krier@Sun.COM 	DWORD status;
30411337SWilliam.Krier@Sun.COM 
30511337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
30611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
30711337SWilliam.Krier@Sun.COM 	else
30811337SWilliam.Krier@Sun.COM 		status = samr_s_enum_local_domains(param, mxa);
30911337SWilliam.Krier@Sun.COM 
31011337SWilliam.Krier@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
31111337SWilliam.Krier@Sun.COM 		param->enum_context = param->info->entries_read;
31211337SWilliam.Krier@Sun.COM 		param->total_entries = param->info->entries_read;
31311337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
31411337SWilliam.Krier@Sun.COM 	} else {
31511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumLocalDomain));
31611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
31711337SWilliam.Krier@Sun.COM 	}
31811337SWilliam.Krier@Sun.COM 
31911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
32011337SWilliam.Krier@Sun.COM }
32111337SWilliam.Krier@Sun.COM 
32211337SWilliam.Krier@Sun.COM 
32311337SWilliam.Krier@Sun.COM /*
32411337SWilliam.Krier@Sun.COM  * samr_s_enum_local_domains
32511337SWilliam.Krier@Sun.COM  *
32611337SWilliam.Krier@Sun.COM  * This function should only be called via samr_s_EnumLocalDomains to
32711337SWilliam.Krier@Sun.COM  * ensure that the appropriate validation is performed. We will answer
32811337SWilliam.Krier@Sun.COM  * queries about two domains: the local domain, synonymous with the
32911337SWilliam.Krier@Sun.COM  * local hostname, and the BUILTIN domain. So we return these two
33011337SWilliam.Krier@Sun.COM  * strings.
33111337SWilliam.Krier@Sun.COM  *
33211337SWilliam.Krier@Sun.COM  * Returns NT status values.
33311337SWilliam.Krier@Sun.COM  */
33411337SWilliam.Krier@Sun.COM static DWORD
33511337SWilliam.Krier@Sun.COM samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
33611337SWilliam.Krier@Sun.COM     ndr_xa_t *mxa)
33711337SWilliam.Krier@Sun.COM {
33811337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainInfo *info;
33911337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainEntry *entry;
34011337SWilliam.Krier@Sun.COM 	char *hostname;
34111337SWilliam.Krier@Sun.COM 
34211337SWilliam.Krier@Sun.COM 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
34311337SWilliam.Krier@Sun.COM 	if (hostname == NULL)
34411337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
34511337SWilliam.Krier@Sun.COM 
34611337SWilliam.Krier@Sun.COM 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
34711337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
34811337SWilliam.Krier@Sun.COM 
34911337SWilliam.Krier@Sun.COM 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
35011337SWilliam.Krier@Sun.COM 	if (entry == NULL)
35111337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
35211337SWilliam.Krier@Sun.COM 
35311337SWilliam.Krier@Sun.COM 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
35411337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
35511337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
35611337SWilliam.Krier@Sun.COM 
35711337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
35811337SWilliam.Krier@Sun.COM 	if (info == NULL)
35911337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
36011337SWilliam.Krier@Sun.COM 
36111337SWilliam.Krier@Sun.COM 	info->entries_read = 2;
36211337SWilliam.Krier@Sun.COM 	info->entry = entry;
36311337SWilliam.Krier@Sun.COM 	param->info = info;
36411337SWilliam.Krier@Sun.COM 	return (NT_STATUS_SUCCESS);
36511337SWilliam.Krier@Sun.COM }
36611337SWilliam.Krier@Sun.COM 
36711337SWilliam.Krier@Sun.COM /*
36811337SWilliam.Krier@Sun.COM  * samr_s_OpenDomain
36911337SWilliam.Krier@Sun.COM  *
37011337SWilliam.Krier@Sun.COM  * This is a request to open a domain within the local SAM database.
37111337SWilliam.Krier@Sun.COM  * The caller must supply a valid connect handle.
37211337SWilliam.Krier@Sun.COM  * We return a handle to be used to access objects within this domain.
37311337SWilliam.Krier@Sun.COM  */
37411337SWilliam.Krier@Sun.COM static int
37511337SWilliam.Krier@Sun.COM samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
37611337SWilliam.Krier@Sun.COM {
37711337SWilliam.Krier@Sun.COM 	struct samr_OpenDomain *param = arg;
37811337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
37911337SWilliam.Krier@Sun.COM 	smb_domain_t domain;
38011337SWilliam.Krier@Sun.COM 
38111337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
38211337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
38311337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
38411337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
38511337SWilliam.Krier@Sun.COM 	}
38611337SWilliam.Krier@Sun.COM 
38711337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
38811337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
38911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
39011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
39111337SWilliam.Krier@Sun.COM 	}
39211337SWilliam.Krier@Sun.COM 
39311337SWilliam.Krier@Sun.COM 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
39411337SWilliam.Krier@Sun.COM 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
39511337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
39611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
39711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
39811337SWilliam.Krier@Sun.COM 	}
39911337SWilliam.Krier@Sun.COM 
40011337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
40111337SWilliam.Krier@Sun.COM 	if (id) {
40211337SWilliam.Krier@Sun.COM 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
40311337SWilliam.Krier@Sun.COM 		param->status = 0;
40411337SWilliam.Krier@Sun.COM 	} else {
40511337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
40611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
40711337SWilliam.Krier@Sun.COM 	}
40811337SWilliam.Krier@Sun.COM 
40911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
41011337SWilliam.Krier@Sun.COM }
41111337SWilliam.Krier@Sun.COM 
41211337SWilliam.Krier@Sun.COM /*
41311337SWilliam.Krier@Sun.COM  * samr_s_QueryDomainInfo
41411337SWilliam.Krier@Sun.COM  *
41511337SWilliam.Krier@Sun.COM  * The caller should pass a domain handle.
41611337SWilliam.Krier@Sun.COM  *
41711337SWilliam.Krier@Sun.COM  * Windows 95 Server Manager sends requests for levels 6 and 7 when
41811337SWilliam.Krier@Sun.COM  * the services menu item is selected. Level 2 is basically for getting
41911337SWilliam.Krier@Sun.COM  * number of users, groups, and aliases in a domain.
42011337SWilliam.Krier@Sun.COM  * We have no information on what the various information levels mean.
42111337SWilliam.Krier@Sun.COM  */
42211337SWilliam.Krier@Sun.COM static int
42311337SWilliam.Krier@Sun.COM samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
42411337SWilliam.Krier@Sun.COM {
42511337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfo *param = arg;
42611337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfoRes *info;
42711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
42811337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
42911337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
43011337SWilliam.Krier@Sun.COM 	char *domain;
43111337SWilliam.Krier@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
43211337SWilliam.Krier@Sun.COM 	int alias_cnt, user_cnt;
43311337SWilliam.Krier@Sun.COM 	int rc = 0;
43411337SWilliam.Krier@Sun.COM 
43511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
43611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
43711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
43811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
43911337SWilliam.Krier@Sun.COM 	}
44011337SWilliam.Krier@Sun.COM 
44111337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
44211337SWilliam.Krier@Sun.COM 	if (info == NULL) {
44311337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
44411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
44511337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
44611337SWilliam.Krier@Sun.COM 	}
44711337SWilliam.Krier@Sun.COM 	info->switch_value = param->info_level;
44811337SWilliam.Krier@Sun.COM 	param->info = info;
44911337SWilliam.Krier@Sun.COM 
45011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
45111337SWilliam.Krier@Sun.COM 
45211337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
45311337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
45411337SWilliam.Krier@Sun.COM 		domain = "BUILTIN";
45511337SWilliam.Krier@Sun.COM 		user_cnt = 0;
45611337SWilliam.Krier@Sun.COM 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
45711337SWilliam.Krier@Sun.COM 		break;
45811337SWilliam.Krier@Sun.COM 
45911337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
46011337SWilliam.Krier@Sun.COM 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
46111337SWilliam.Krier@Sun.COM 		if (rc == 0) {
46211337SWilliam.Krier@Sun.COM 			domain = hostname;
46311337SWilliam.Krier@Sun.COM 			user_cnt = smb_sam_usr_cnt();
46411337SWilliam.Krier@Sun.COM 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
46511337SWilliam.Krier@Sun.COM 		}
46611337SWilliam.Krier@Sun.COM 		break;
46711337SWilliam.Krier@Sun.COM 
46811337SWilliam.Krier@Sun.COM 	default:
46911337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
47011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
47111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
47211337SWilliam.Krier@Sun.COM 	}
47311337SWilliam.Krier@Sun.COM 
47411337SWilliam.Krier@Sun.COM 	if (rc != 0) {
47511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
47611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
47711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
47811337SWilliam.Krier@Sun.COM 	}
47911337SWilliam.Krier@Sun.COM 
48011337SWilliam.Krier@Sun.COM 	switch (param->info_level) {
48111337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_6:
48211337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown1 = 0x00000000;
48311337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown2 = 0x00147FB0;
48411337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown3 = 0x00000000;
48511337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown4 = 0x00000000;
48611337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown5 = 0x00000000;
48711337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
48811337SWilliam.Krier@Sun.COM 		break;
48911337SWilliam.Krier@Sun.COM 
49011337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_7:
49111337SWilliam.Krier@Sun.COM 		info->ru.info7.unknown1 = 0x00000003;
49211337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
49311337SWilliam.Krier@Sun.COM 		break;
49411337SWilliam.Krier@Sun.COM 
49511337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_2:
49611337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown1 = 0x00000000;
49711337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown2 = 0x80000000;
49811337SWilliam.Krier@Sun.COM 
49911337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
50011337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s1));
50111337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, domain,
50211337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.domain));
50311337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
50411337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s2));
50511337SWilliam.Krier@Sun.COM 
50611337SWilliam.Krier@Sun.COM 		info->ru.info2.sequence_num = 0x0000002B;
50711337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown3 = 0x00000000;
50811337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown4 = 0x00000001;
50911337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown5 = 0x00000003;
51011337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown6 = 0x00000001;
51111337SWilliam.Krier@Sun.COM 		info->ru.info2.num_users = user_cnt;
51211337SWilliam.Krier@Sun.COM 		info->ru.info2.num_groups = 0;
51311337SWilliam.Krier@Sun.COM 		info->ru.info2.num_aliases = alias_cnt;
51411337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
51511337SWilliam.Krier@Sun.COM 		break;
51611337SWilliam.Krier@Sun.COM 
51711337SWilliam.Krier@Sun.COM 	default:
51811337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
51911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
52011337SWilliam.Krier@Sun.COM 	};
52111337SWilliam.Krier@Sun.COM 
52211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
52311337SWilliam.Krier@Sun.COM }
52411337SWilliam.Krier@Sun.COM 
52511337SWilliam.Krier@Sun.COM /*
526*11447Samw@Sun.COM  * QueryInfoDomain2: Identical to QueryDomainInfo.
527*11447Samw@Sun.COM  */
528*11447Samw@Sun.COM static int
529*11447Samw@Sun.COM samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
530*11447Samw@Sun.COM {
531*11447Samw@Sun.COM 	return (samr_s_QueryDomainInfo(arg, mxa));
532*11447Samw@Sun.COM }
533*11447Samw@Sun.COM 
534*11447Samw@Sun.COM /*
53511337SWilliam.Krier@Sun.COM  * Looks up the given name in the specified domain which could
53611337SWilliam.Krier@Sun.COM  * be either the built-in or local domain.
53711337SWilliam.Krier@Sun.COM  *
53811337SWilliam.Krier@Sun.COM  * CAVEAT: this function should be able to handle a list of
53911337SWilliam.Krier@Sun.COM  * names but currently it can only handle one name at a time.
54011337SWilliam.Krier@Sun.COM  */
54111337SWilliam.Krier@Sun.COM static int
54211337SWilliam.Krier@Sun.COM samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
54311337SWilliam.Krier@Sun.COM {
54411337SWilliam.Krier@Sun.COM 	struct samr_LookupNames *param = arg;
54511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
54611337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
54711337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
54811337SWilliam.Krier@Sun.COM 	smb_account_t account;
54911337SWilliam.Krier@Sun.COM 	smb_wka_t *wka;
55011337SWilliam.Krier@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
55111337SWilliam.Krier@Sun.COM 
55211337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
55311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
55411337SWilliam.Krier@Sun.COM 
55511337SWilliam.Krier@Sun.COM 	if (param->n_entry != 1)
55611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
55711337SWilliam.Krier@Sun.COM 
55811337SWilliam.Krier@Sun.COM 	if (param->name.str == NULL) {
55911337SWilliam.Krier@Sun.COM 		/*
56011337SWilliam.Krier@Sun.COM 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
56111337SWilliam.Krier@Sun.COM 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
56211337SWilliam.Krier@Sun.COM 		 */
56311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NONE_MAPPED;
56411337SWilliam.Krier@Sun.COM 	}
56511337SWilliam.Krier@Sun.COM 
56611337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
56711337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
56811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
56911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
57011337SWilliam.Krier@Sun.COM 	}
57111337SWilliam.Krier@Sun.COM 
57211337SWilliam.Krier@Sun.COM 	param->rids.rid = NDR_NEW(mxa, DWORD);
57311337SWilliam.Krier@Sun.COM 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
57411337SWilliam.Krier@Sun.COM 
57511337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
57611337SWilliam.Krier@Sun.COM 
57711337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
57811337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
579*11447Samw@Sun.COM 		wka = smb_wka_lookup_builtin((char *)param->name.str);
58011337SWilliam.Krier@Sun.COM 		if (wka != NULL) {
58111337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
58211337SWilliam.Krier@Sun.COM 			(void) smb_sid_getrid(wka->wka_binsid,
58311337SWilliam.Krier@Sun.COM 			    &param->rids.rid[0]);
58411337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
58511337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = wka->wka_type;
58611337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
58711337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
58811337SWilliam.Krier@Sun.COM 		}
58911337SWilliam.Krier@Sun.COM 		break;
59011337SWilliam.Krier@Sun.COM 
59111337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
59211337SWilliam.Krier@Sun.COM 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
59311337SWilliam.Krier@Sun.COM 		    SidTypeUnknown, &account);
59411337SWilliam.Krier@Sun.COM 		if (status == NT_STATUS_SUCCESS) {
59511337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
59611337SWilliam.Krier@Sun.COM 			param->rids.rid[0] = account.a_rid;
59711337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
59811337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = account.a_type;
59911337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
60011337SWilliam.Krier@Sun.COM 			smb_account_free(&account);
60111337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
60211337SWilliam.Krier@Sun.COM 		}
60311337SWilliam.Krier@Sun.COM 		break;
60411337SWilliam.Krier@Sun.COM 
60511337SWilliam.Krier@Sun.COM 	default:
60611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
60711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
60811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
60911337SWilliam.Krier@Sun.COM 	}
61011337SWilliam.Krier@Sun.COM 
61111337SWilliam.Krier@Sun.COM 	param->rids.n_entry = 0;
61211337SWilliam.Krier@Sun.COM 	param->rid_types.n_entry = 0;
61311337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
61411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
61511337SWilliam.Krier@Sun.COM }
61611337SWilliam.Krier@Sun.COM 
61711337SWilliam.Krier@Sun.COM /*
61811337SWilliam.Krier@Sun.COM  * samr_s_OpenUser
61911337SWilliam.Krier@Sun.COM  *
62011337SWilliam.Krier@Sun.COM  * This is a request to open a user within a specified domain in the
62111337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
62211337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The user is
62311337SWilliam.Krier@Sun.COM  * specified by the rid in the request.
62411337SWilliam.Krier@Sun.COM  */
62511337SWilliam.Krier@Sun.COM static int
62611337SWilliam.Krier@Sun.COM samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
62711337SWilliam.Krier@Sun.COM {
62811337SWilliam.Krier@Sun.COM 	struct samr_OpenUser *param = arg;
62911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
63011337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
63111337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
63211337SWilliam.Krier@Sun.COM 
63311337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
63411337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
63511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
63611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
63711337SWilliam.Krier@Sun.COM 	}
63811337SWilliam.Krier@Sun.COM 
63911337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
64011337SWilliam.Krier@Sun.COM 
64111337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
64211337SWilliam.Krier@Sun.COM 	if (id == NULL) {
64311337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
64411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
64511337SWilliam.Krier@Sun.COM 	} else {
64611337SWilliam.Krier@Sun.COM 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
64711337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
64811337SWilliam.Krier@Sun.COM 	}
64911337SWilliam.Krier@Sun.COM 
65011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
65111337SWilliam.Krier@Sun.COM }
65211337SWilliam.Krier@Sun.COM 
65311337SWilliam.Krier@Sun.COM /*
65411337SWilliam.Krier@Sun.COM  * samr_s_DeleteUser
65511337SWilliam.Krier@Sun.COM  *
65611337SWilliam.Krier@Sun.COM  * Request to delete a user within a specified domain in the local
65711337SWilliam.Krier@Sun.COM  * SAM database.  The caller should supply a valid user handle.
65811337SWilliam.Krier@Sun.COM  */
65911337SWilliam.Krier@Sun.COM /*ARGSUSED*/
66011337SWilliam.Krier@Sun.COM static int
66111337SWilliam.Krier@Sun.COM samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
66211337SWilliam.Krier@Sun.COM {
66311337SWilliam.Krier@Sun.COM 	struct samr_DeleteUser *param = arg;
66411337SWilliam.Krier@Sun.COM 
66511337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_DeleteUser));
66611337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
66711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
66811337SWilliam.Krier@Sun.COM }
66911337SWilliam.Krier@Sun.COM 
67011337SWilliam.Krier@Sun.COM /*
67111337SWilliam.Krier@Sun.COM  * samr_s_QueryUserInfo
67211337SWilliam.Krier@Sun.COM  *
67311337SWilliam.Krier@Sun.COM  * Returns:
67411337SWilliam.Krier@Sun.COM  * NT_STATUS_SUCCESS
67511337SWilliam.Krier@Sun.COM  * NT_STATUS_ACCESS_DENIED
67611337SWilliam.Krier@Sun.COM  * NT_STATUS_INVALID_INFO_CLASS
67711337SWilliam.Krier@Sun.COM  */
67811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
67911337SWilliam.Krier@Sun.COM static int
68011337SWilliam.Krier@Sun.COM samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
68111337SWilliam.Krier@Sun.COM {
68211337SWilliam.Krier@Sun.COM 	static uint16_t			owf_buf[8];
68311337SWilliam.Krier@Sun.COM 	static uint8_t			hour_buf[SAMR_SET_USER_HOURS_SZ];
68411337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo	*param = arg;
68511337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo21	*all_info;
68611337SWilliam.Krier@Sun.COM 	ndr_hdid_t			*id;
68711337SWilliam.Krier@Sun.COM 	ndr_handle_t			*hd;
68811337SWilliam.Krier@Sun.COM 	samr_keydata_t			*data;
68911337SWilliam.Krier@Sun.COM 	smb_domain_t			di;
69011337SWilliam.Krier@Sun.COM 	smb_account_t			account;
69111337SWilliam.Krier@Sun.COM 	smb_sid_t			*sid;
69211337SWilliam.Krier@Sun.COM 	uint32_t			status;
69311337SWilliam.Krier@Sun.COM 
69411337SWilliam.Krier@Sun.COM 	id = (ndr_hdid_t *)&param->user_handle;
69511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
69611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
69711337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
69811337SWilliam.Krier@Sun.COM 	}
69911337SWilliam.Krier@Sun.COM 
70011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
70111337SWilliam.Krier@Sun.COM 
70211337SWilliam.Krier@Sun.COM 	if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
70311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
70411337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
70511337SWilliam.Krier@Sun.COM 	}
70611337SWilliam.Krier@Sun.COM 
70711337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
70811337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
70911337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
71011337SWilliam.Krier@Sun.COM 	}
71111337SWilliam.Krier@Sun.COM 
71211337SWilliam.Krier@Sun.COM 	if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
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_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
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 	all_info = &param->ru.info21;
72311337SWilliam.Krier@Sun.COM 	bzero(all_info, sizeof (struct samr_QueryUserInfo21));
72411337SWilliam.Krier@Sun.COM 
72511337SWilliam.Krier@Sun.COM 	all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
72611337SWilliam.Krier@Sun.COM 
72711337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, account.a_name,
72811337SWilliam.Krier@Sun.COM 	    (ndr_mstring_t *)&all_info->UserName);
72911337SWilliam.Krier@Sun.COM 	all_info->UserId = data->kd_rid;
73011337SWilliam.Krier@Sun.COM 
73111337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.length = 16;
73211337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.maxlen = 16;
73311337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.buf = owf_buf;
73411337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.length = 16;
73511337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.maxlen = 16;
73611337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.buf = owf_buf;
73711337SWilliam.Krier@Sun.COM 	all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
73811337SWilliam.Krier@Sun.COM 	all_info->LogonHours.hours = hour_buf;
73911337SWilliam.Krier@Sun.COM 
74011337SWilliam.Krier@Sun.COM 	param->address = 1;
74111337SWilliam.Krier@Sun.COM 	param->switch_index = SAMR_QUERY_USER_ALL_INFO;
74211337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
74311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
74411337SWilliam.Krier@Sun.COM 
74511337SWilliam.Krier@Sun.COM QueryUserInfoError:
74611337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserInfo));
74711337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
74811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
74911337SWilliam.Krier@Sun.COM }
75011337SWilliam.Krier@Sun.COM 
75111337SWilliam.Krier@Sun.COM /*
75211337SWilliam.Krier@Sun.COM  * samr_s_QueryUserGroups
75311337SWilliam.Krier@Sun.COM  *
75411337SWilliam.Krier@Sun.COM  * Request the list of groups of which a user is a member.
75511337SWilliam.Krier@Sun.COM  * The user is identified from the handle, which contains an
75611337SWilliam.Krier@Sun.COM  * rid in the discriminator field. Note that this is a local user.
75711337SWilliam.Krier@Sun.COM  */
75811337SWilliam.Krier@Sun.COM static int
75911337SWilliam.Krier@Sun.COM samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
76011337SWilliam.Krier@Sun.COM {
76111337SWilliam.Krier@Sun.COM 	struct samr_QueryUserGroups *param = arg;
76211337SWilliam.Krier@Sun.COM 	struct samr_UserGroupInfo *info;
76311337SWilliam.Krier@Sun.COM 	struct samr_UserGroups *group;
76411337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
76511337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
76611337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
76711337SWilliam.Krier@Sun.COM 	smb_sid_t *user_sid = NULL;
76811337SWilliam.Krier@Sun.COM 	smb_group_t grp;
76911337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
77011337SWilliam.Krier@Sun.COM 	smb_domain_t di;
77111337SWilliam.Krier@Sun.COM 	uint32_t status;
77211337SWilliam.Krier@Sun.COM 	int size;
77311337SWilliam.Krier@Sun.COM 	int ngrp_max;
77411337SWilliam.Krier@Sun.COM 
77511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
77611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
77711337SWilliam.Krier@Sun.COM 		goto query_error;
77811337SWilliam.Krier@Sun.COM 	}
77911337SWilliam.Krier@Sun.COM 
78011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
78111337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
78211337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
78311337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
78411337SWilliam.Krier@Sun.COM 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
78511337SWilliam.Krier@Sun.COM 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
78611337SWilliam.Krier@Sun.COM 			goto query_error;
78711337SWilliam.Krier@Sun.COM 		}
78811337SWilliam.Krier@Sun.COM 		break;
78911337SWilliam.Krier@Sun.COM 	default:
79011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
79111337SWilliam.Krier@Sun.COM 		goto query_error;
79211337SWilliam.Krier@Sun.COM 	}
79311337SWilliam.Krier@Sun.COM 
79411337SWilliam.Krier@Sun.COM 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
79511337SWilliam.Krier@Sun.COM 	if (user_sid == NULL) {
79611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
79711337SWilliam.Krier@Sun.COM 		goto query_error;
79811337SWilliam.Krier@Sun.COM 	}
79911337SWilliam.Krier@Sun.COM 
80011337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
80111337SWilliam.Krier@Sun.COM 	if (info == NULL) {
80211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
80311337SWilliam.Krier@Sun.COM 		goto query_error;
80411337SWilliam.Krier@Sun.COM 	}
80511337SWilliam.Krier@Sun.COM 	bzero(info, sizeof (struct samr_UserGroupInfo));
80611337SWilliam.Krier@Sun.COM 
80711337SWilliam.Krier@Sun.COM 	size = 32 * 1024;
80811337SWilliam.Krier@Sun.COM 	info->groups = NDR_MALLOC(mxa, size);
80911337SWilliam.Krier@Sun.COM 	if (info->groups == NULL) {
81011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
81111337SWilliam.Krier@Sun.COM 		goto query_error;
81211337SWilliam.Krier@Sun.COM 	}
81311337SWilliam.Krier@Sun.COM 	ngrp_max = size / sizeof (struct samr_UserGroups);
81411337SWilliam.Krier@Sun.COM 
81511337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
81611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INTERNAL_ERROR;
81711337SWilliam.Krier@Sun.COM 		goto query_error;
81811337SWilliam.Krier@Sun.COM 	}
81911337SWilliam.Krier@Sun.COM 
82011337SWilliam.Krier@Sun.COM 	info->n_entry = 0;
82111337SWilliam.Krier@Sun.COM 	group = info->groups;
82211337SWilliam.Krier@Sun.COM 	while ((info->n_entry < ngrp_max) &&
82311337SWilliam.Krier@Sun.COM 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
82411337SWilliam.Krier@Sun.COM 		if (smb_lgrp_is_member(&grp, user_sid)) {
82511337SWilliam.Krier@Sun.COM 			group->rid = grp.sg_rid;
82611337SWilliam.Krier@Sun.COM 			group->attr = grp.sg_attr;
82711337SWilliam.Krier@Sun.COM 			group++;
82811337SWilliam.Krier@Sun.COM 			info->n_entry++;
82911337SWilliam.Krier@Sun.COM 		}
83011337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
83111337SWilliam.Krier@Sun.COM 	}
83211337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
83311337SWilliam.Krier@Sun.COM 
83411337SWilliam.Krier@Sun.COM 	free(user_sid);
83511337SWilliam.Krier@Sun.COM 	param->info = info;
83611337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
83711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
83811337SWilliam.Krier@Sun.COM 
83911337SWilliam.Krier@Sun.COM query_error:
84011337SWilliam.Krier@Sun.COM 	free(user_sid);
84111337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserGroups));
84211337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
84311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
84411337SWilliam.Krier@Sun.COM }
84511337SWilliam.Krier@Sun.COM 
84611337SWilliam.Krier@Sun.COM /*
84711337SWilliam.Krier@Sun.COM  * samr_s_OpenGroup
84811337SWilliam.Krier@Sun.COM  *
84911337SWilliam.Krier@Sun.COM  * This is a request to open a group within the specified domain in the
85011337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
85111337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The group is
85211337SWilliam.Krier@Sun.COM  * specified by the rid in the request. If this is a local RID it
85311337SWilliam.Krier@Sun.COM  * should already be encoded with type information.
85411337SWilliam.Krier@Sun.COM  *
85511337SWilliam.Krier@Sun.COM  * We return a handle to be used to access information about this group.
85611337SWilliam.Krier@Sun.COM  */
85711337SWilliam.Krier@Sun.COM static int
85811337SWilliam.Krier@Sun.COM samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
85911337SWilliam.Krier@Sun.COM {
86011337SWilliam.Krier@Sun.COM 	struct samr_OpenGroup *param = arg;
86111337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
86211337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
86311337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
86411337SWilliam.Krier@Sun.COM 
86511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
86611337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
86711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
86811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
86911337SWilliam.Krier@Sun.COM 	}
87011337SWilliam.Krier@Sun.COM 
87111337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
87211337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
87311337SWilliam.Krier@Sun.COM 
87411337SWilliam.Krier@Sun.COM 	if (id) {
87511337SWilliam.Krier@Sun.COM 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
87611337SWilliam.Krier@Sun.COM 		param->status = 0;
87711337SWilliam.Krier@Sun.COM 	} else {
87811337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
87911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
88011337SWilliam.Krier@Sun.COM 	}
88111337SWilliam.Krier@Sun.COM 
88211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
88311337SWilliam.Krier@Sun.COM }
88411337SWilliam.Krier@Sun.COM 
88511337SWilliam.Krier@Sun.COM /*
88611337SWilliam.Krier@Sun.COM  * samr_s_Connect
88711337SWilliam.Krier@Sun.COM  *
88811337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database.
88911337SWilliam.Krier@Sun.COM  * We don't support any form of update request and our database doesn't
89011337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in doing
89111337SWilliam.Krier@Sun.COM  * any access access checking here.
89211337SWilliam.Krier@Sun.COM  *
89311337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
89411337SWilliam.Krier@Sun.COM  */
89511337SWilliam.Krier@Sun.COM static int
89611337SWilliam.Krier@Sun.COM samr_s_Connect(void *arg, ndr_xa_t *mxa)
89711337SWilliam.Krier@Sun.COM {
89811337SWilliam.Krier@Sun.COM 	struct samr_Connect *param = arg;
89911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
90011337SWilliam.Krier@Sun.COM 
90111337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
90211337SWilliam.Krier@Sun.COM 	if (id) {
90311337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
90411337SWilliam.Krier@Sun.COM 		param->status = 0;
90511337SWilliam.Krier@Sun.COM 	} else {
90611337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
90711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
90811337SWilliam.Krier@Sun.COM 	}
90911337SWilliam.Krier@Sun.COM 
91011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
91111337SWilliam.Krier@Sun.COM }
91211337SWilliam.Krier@Sun.COM 
91311337SWilliam.Krier@Sun.COM /*
91411337SWilliam.Krier@Sun.COM  * samr_s_GetUserPwInfo
91511337SWilliam.Krier@Sun.COM  *
916*11447Samw@Sun.COM  * Request for a user's password policy information.
91711337SWilliam.Krier@Sun.COM  */
91811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
91911337SWilliam.Krier@Sun.COM static int
92011337SWilliam.Krier@Sun.COM samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
92111337SWilliam.Krier@Sun.COM {
922*11447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
923*11447Samw@Sun.COM 	struct samr_GetUserPwInfo	*param = arg;
92411337SWilliam.Krier@Sun.COM 
925*11447Samw@Sun.COM 	param->pwinfo = &pwinfo;
926*11447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
92711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
92811337SWilliam.Krier@Sun.COM }
92911337SWilliam.Krier@Sun.COM 
93011337SWilliam.Krier@Sun.COM /*
93111337SWilliam.Krier@Sun.COM  * samr_s_CreateUser
93211337SWilliam.Krier@Sun.COM  */
93311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
93411337SWilliam.Krier@Sun.COM static int
93511337SWilliam.Krier@Sun.COM samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
93611337SWilliam.Krier@Sun.COM {
93711337SWilliam.Krier@Sun.COM 	struct samr_CreateUser *param = arg;
93811337SWilliam.Krier@Sun.COM 
93911337SWilliam.Krier@Sun.COM 	bzero(&param->user_handle, sizeof (samr_handle_t));
94011337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
94111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
94211337SWilliam.Krier@Sun.COM }
94311337SWilliam.Krier@Sun.COM 
94411337SWilliam.Krier@Sun.COM /*
94511337SWilliam.Krier@Sun.COM  * samr_s_ChangeUserPasswd
94611337SWilliam.Krier@Sun.COM  */
94711337SWilliam.Krier@Sun.COM /*ARGSUSED*/
94811337SWilliam.Krier@Sun.COM static int
94911337SWilliam.Krier@Sun.COM samr_s_ChangeUserPasswd(void *arg, ndr_xa_t *mxa)
95011337SWilliam.Krier@Sun.COM {
95111337SWilliam.Krier@Sun.COM 	struct samr_ChangeUserPasswd *param = arg;
95211337SWilliam.Krier@Sun.COM 
95311337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_ChangeUserPasswd));
95411337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
95511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
95611337SWilliam.Krier@Sun.COM }
95711337SWilliam.Krier@Sun.COM 
95811337SWilliam.Krier@Sun.COM /*
95911337SWilliam.Krier@Sun.COM  * samr_s_GetDomainPwInfo
960*11447Samw@Sun.COM  *
961*11447Samw@Sun.COM  * Request for the domain password policy information.
96211337SWilliam.Krier@Sun.COM  */
96311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
96411337SWilliam.Krier@Sun.COM static int
96511337SWilliam.Krier@Sun.COM samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
96611337SWilliam.Krier@Sun.COM {
967*11447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
968*11447Samw@Sun.COM 	struct samr_GetDomainPwInfo	*param = arg;
96911337SWilliam.Krier@Sun.COM 
970*11447Samw@Sun.COM 	param->pwinfo = &pwinfo;
971*11447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
97211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
97311337SWilliam.Krier@Sun.COM }
97411337SWilliam.Krier@Sun.COM 
97511337SWilliam.Krier@Sun.COM /*
97611337SWilliam.Krier@Sun.COM  * samr_s_SetUserInfo
97711337SWilliam.Krier@Sun.COM  */
97811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
97911337SWilliam.Krier@Sun.COM static int
98011337SWilliam.Krier@Sun.COM samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
98111337SWilliam.Krier@Sun.COM {
98211337SWilliam.Krier@Sun.COM 	struct samr_SetUserInfo *param = arg;
98311337SWilliam.Krier@Sun.COM 
98411337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_SetUserInfo));
98511337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
98611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
98711337SWilliam.Krier@Sun.COM }
98811337SWilliam.Krier@Sun.COM 
98911337SWilliam.Krier@Sun.COM /*
99011337SWilliam.Krier@Sun.COM  * samr_s_QueryDispInfo
99111337SWilliam.Krier@Sun.COM  *
99211337SWilliam.Krier@Sun.COM  * This function currently return local users' information only.
99311337SWilliam.Krier@Sun.COM  * This RPC is called repeatedly until all the users info are
99411337SWilliam.Krier@Sun.COM  * retrieved.
99511337SWilliam.Krier@Sun.COM  *
99611337SWilliam.Krier@Sun.COM  * The total count and the returned count are returned as total size
99711337SWilliam.Krier@Sun.COM  * and returned size.  The client doesn't seem to care.
99811337SWilliam.Krier@Sun.COM  */
99911337SWilliam.Krier@Sun.COM static int
100011337SWilliam.Krier@Sun.COM samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
100111337SWilliam.Krier@Sun.COM {
100211337SWilliam.Krier@Sun.COM 	struct samr_QueryDispInfo *param = arg;
100311337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
100411337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
100511337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
100611337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
100711337SWilliam.Krier@Sun.COM 	struct user_acct_info *user;
100811337SWilliam.Krier@Sun.COM 	smb_pwditer_t pwi;
100911337SWilliam.Krier@Sun.COM 	smb_luser_t *uinfo;
101011337SWilliam.Krier@Sun.COM 	int num_users;
101111337SWilliam.Krier@Sun.COM 	int start_idx;
101211337SWilliam.Krier@Sun.COM 	int max_retcnt, retcnt;
101311337SWilliam.Krier@Sun.COM 	int skip;
101411337SWilliam.Krier@Sun.COM 
101511337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
101611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
101711337SWilliam.Krier@Sun.COM 		goto error;
101811337SWilliam.Krier@Sun.COM 	}
101911337SWilliam.Krier@Sun.COM 
102011337SWilliam.Krier@Sun.COM 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
102111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
102211337SWilliam.Krier@Sun.COM 		goto error;
102311337SWilliam.Krier@Sun.COM 	}
102411337SWilliam.Krier@Sun.COM 
102511337SWilliam.Krier@Sun.COM 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
102611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NOT_IMPLEMENTED;
102711337SWilliam.Krier@Sun.COM 		goto error;
102811337SWilliam.Krier@Sun.COM 	}
102911337SWilliam.Krier@Sun.COM 
103011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
103111337SWilliam.Krier@Sun.COM 
103211337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
103311337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
103411337SWilliam.Krier@Sun.COM 		goto no_info;
103511337SWilliam.Krier@Sun.COM 
103611337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
103711337SWilliam.Krier@Sun.COM 		num_users = smb_sam_usr_cnt();
103811337SWilliam.Krier@Sun.COM 		start_idx = param->start_idx;
103911337SWilliam.Krier@Sun.COM 		if ((num_users == 0) || (start_idx >= num_users))
104011337SWilliam.Krier@Sun.COM 			goto no_info;
104111337SWilliam.Krier@Sun.COM 
104211337SWilliam.Krier@Sun.COM 		max_retcnt = num_users - start_idx;
104311337SWilliam.Krier@Sun.COM 		if (max_retcnt > param->max_entries)
104411337SWilliam.Krier@Sun.COM 			max_retcnt = param->max_entries;
104511337SWilliam.Krier@Sun.COM 		param->users.acct = NDR_MALLOC(mxa,
104611337SWilliam.Krier@Sun.COM 		    max_retcnt * sizeof (struct user_acct_info));
104711337SWilliam.Krier@Sun.COM 		user = param->users.acct;
104811337SWilliam.Krier@Sun.COM 		if (user == NULL) {
104911337SWilliam.Krier@Sun.COM 			status = NT_STATUS_NO_MEMORY;
105011337SWilliam.Krier@Sun.COM 			goto error;
105111337SWilliam.Krier@Sun.COM 		}
105211337SWilliam.Krier@Sun.COM 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
105311337SWilliam.Krier@Sun.COM 
105411337SWilliam.Krier@Sun.COM 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
105511337SWilliam.Krier@Sun.COM 			goto no_info;
105611337SWilliam.Krier@Sun.COM 
105711337SWilliam.Krier@Sun.COM 		skip = retcnt = 0;
105811337SWilliam.Krier@Sun.COM 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
105911337SWilliam.Krier@Sun.COM 			if (skip++ < start_idx)
106011337SWilliam.Krier@Sun.COM 				continue;
106111337SWilliam.Krier@Sun.COM 
106211337SWilliam.Krier@Sun.COM 			if (retcnt++ >= max_retcnt)
106311337SWilliam.Krier@Sun.COM 				break;
106411337SWilliam.Krier@Sun.COM 
106511337SWilliam.Krier@Sun.COM 			assert(uinfo->su_name != NULL);
106611337SWilliam.Krier@Sun.COM 
106711337SWilliam.Krier@Sun.COM 			user->index = start_idx + retcnt;
106811337SWilliam.Krier@Sun.COM 			user->rid = uinfo->su_rid;
106911337SWilliam.Krier@Sun.COM 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
107011337SWilliam.Krier@Sun.COM 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
107111337SWilliam.Krier@Sun.COM 				user->ctrl |= ACF_DISABLED;
107211337SWilliam.Krier@Sun.COM 			if (NDR_MSTRING(mxa, uinfo->su_name,
107311337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->name) == -1) {
107411337SWilliam.Krier@Sun.COM 				smb_pwd_iterclose(&pwi);
107511337SWilliam.Krier@Sun.COM 				status = NT_STATUS_NO_MEMORY;
107611337SWilliam.Krier@Sun.COM 				goto error;
107711337SWilliam.Krier@Sun.COM 			}
107811337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
107911337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->fullname);
108011337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
108111337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->desc);
108211337SWilliam.Krier@Sun.COM 			user++;
108311337SWilliam.Krier@Sun.COM 		}
108411337SWilliam.Krier@Sun.COM 		smb_pwd_iterclose(&pwi);
108511337SWilliam.Krier@Sun.COM 
108611337SWilliam.Krier@Sun.COM 		if (retcnt >= max_retcnt) {
108711337SWilliam.Krier@Sun.COM 			retcnt = max_retcnt;
108811337SWilliam.Krier@Sun.COM 			param->status = status;
108911337SWilliam.Krier@Sun.COM 		} else {
109011337SWilliam.Krier@Sun.COM 			param->status = ERROR_MORE_ENTRIES;
109111337SWilliam.Krier@Sun.COM 		}
109211337SWilliam.Krier@Sun.COM 
109311337SWilliam.Krier@Sun.COM 		param->users.total_size = num_users;
109411337SWilliam.Krier@Sun.COM 		param->users.returned_size = retcnt;
109511337SWilliam.Krier@Sun.COM 		param->users.switch_value = param->level;
109611337SWilliam.Krier@Sun.COM 		param->users.count = retcnt;
109711337SWilliam.Krier@Sun.COM 
109811337SWilliam.Krier@Sun.COM 		break;
109911337SWilliam.Krier@Sun.COM 
110011337SWilliam.Krier@Sun.COM 	default:
110111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
110211337SWilliam.Krier@Sun.COM 		goto error;
110311337SWilliam.Krier@Sun.COM 	}
110411337SWilliam.Krier@Sun.COM 
110511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
110611337SWilliam.Krier@Sun.COM 
110711337SWilliam.Krier@Sun.COM no_info:
110811337SWilliam.Krier@Sun.COM 	param->users.total_size = 0;
110911337SWilliam.Krier@Sun.COM 	param->users.returned_size = 0;
111011337SWilliam.Krier@Sun.COM 	param->users.switch_value = param->level;
111111337SWilliam.Krier@Sun.COM 	param->users.count = 0;
111211337SWilliam.Krier@Sun.COM 	param->users.acct = NULL;
111311337SWilliam.Krier@Sun.COM 	param->status = status;
111411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
111511337SWilliam.Krier@Sun.COM 
111611337SWilliam.Krier@Sun.COM error:
111711337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryDispInfo));
111811337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
111911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
112011337SWilliam.Krier@Sun.COM }
112111337SWilliam.Krier@Sun.COM 
112211337SWilliam.Krier@Sun.COM /*
112311337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainGroups
112411337SWilliam.Krier@Sun.COM  *
112511337SWilliam.Krier@Sun.COM  *
112611337SWilliam.Krier@Sun.COM  * This function is supposed to return local group information.
112711337SWilliam.Krier@Sun.COM  * As we don't support local users, this function dosen't send
112811337SWilliam.Krier@Sun.COM  * back any information.
112911337SWilliam.Krier@Sun.COM  *
113011337SWilliam.Krier@Sun.COM  * Added template that returns information for a domain group as None.
113111337SWilliam.Krier@Sun.COM  * All information is hard-coded from packet captures.
113211337SWilliam.Krier@Sun.COM  */
113311337SWilliam.Krier@Sun.COM static int
113411337SWilliam.Krier@Sun.COM samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
113511337SWilliam.Krier@Sun.COM {
113611337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainGroups *param = arg;
113711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
113811337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
113911337SWilliam.Krier@Sun.COM 
114011337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
114111337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
114211337SWilliam.Krier@Sun.COM 
114311337SWilliam.Krier@Sun.COM 	param->total_size = 0;
114411337SWilliam.Krier@Sun.COM 	param->returned_size = 0;
114511337SWilliam.Krier@Sun.COM 	param->switch_value = 3;
114611337SWilliam.Krier@Sun.COM 	param->count = 0;
114711337SWilliam.Krier@Sun.COM 	param->groups = 0;
114811337SWilliam.Krier@Sun.COM 	param->status = status;
114911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
115011337SWilliam.Krier@Sun.COM 
115111337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_GROUPS
115211337SWilliam.Krier@Sun.COM 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
115311337SWilliam.Krier@Sun.COM 		param->total_size = 0;
115411337SWilliam.Krier@Sun.COM 		param->returned_size = 0;
115511337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
115611337SWilliam.Krier@Sun.COM 		param->count = 0;
115711337SWilliam.Krier@Sun.COM 		param->groups = 0;
115811337SWilliam.Krier@Sun.COM 	} else {
115911337SWilliam.Krier@Sun.COM 		param->total_size = 64;
116011337SWilliam.Krier@Sun.COM 		param->returned_size = 64;
116111337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
116211337SWilliam.Krier@Sun.COM 		param->count = 1;
116311337SWilliam.Krier@Sun.COM 		param->groups = (struct group_disp_info *)NDR_MALLOC(
116411337SWilliam.Krier@Sun.COM 		    mxa, sizeof (struct group_disp_info));
116511337SWilliam.Krier@Sun.COM 
116611337SWilliam.Krier@Sun.COM 		param->groups->count = 1;
116711337SWilliam.Krier@Sun.COM 		param->groups->acct[0].index = 1;
116811337SWilliam.Krier@Sun.COM 		param->groups->acct[0].rid = 513;
116911337SWilliam.Krier@Sun.COM 		param->groups->acct[0].ctrl = 0x7;
117011337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "None",
117111337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].name);
117211337SWilliam.Krier@Sun.COM 
117311337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "Ordinary users",
117411337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
117511337SWilliam.Krier@Sun.COM 	}
117611337SWilliam.Krier@Sun.COM 
117711337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
117811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
117911337SWilliam.Krier@Sun.COM #endif
118011337SWilliam.Krier@Sun.COM }
118111337SWilliam.Krier@Sun.COM 
118211337SWilliam.Krier@Sun.COM /*
118311337SWilliam.Krier@Sun.COM  * samr_s_OpenAlias
118411337SWilliam.Krier@Sun.COM  *
118511337SWilliam.Krier@Sun.COM  * Lookup for requested alias, if it exists return a handle
118611337SWilliam.Krier@Sun.COM  * for that alias. The alias domain sid should match with
118711337SWilliam.Krier@Sun.COM  * the passed domain handle.
118811337SWilliam.Krier@Sun.COM  */
118911337SWilliam.Krier@Sun.COM static int
119011337SWilliam.Krier@Sun.COM samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
119111337SWilliam.Krier@Sun.COM {
119211337SWilliam.Krier@Sun.COM 	struct samr_OpenAlias *param = arg;
1193*11447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
1194*11447Samw@Sun.COM 	ndr_handle_t	*hd;
1195*11447Samw@Sun.COM 	samr_keydata_t	*data;
1196*11447Samw@Sun.COM 	smb_gdomain_t	gd_type;
1197*11447Samw@Sun.COM 	smb_sid_t	*sid;
1198*11447Samw@Sun.COM 	smb_wka_t	*wka;
1199*11447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
1200*11447Samw@Sun.COM 	uint32_t	rid;
1201*11447Samw@Sun.COM 	uint32_t	status;
1202*11447Samw@Sun.COM 	int		rc;
120311337SWilliam.Krier@Sun.COM 
120411337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
120511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
120611337SWilliam.Krier@Sun.COM 		goto open_alias_err;
120711337SWilliam.Krier@Sun.COM 	}
120811337SWilliam.Krier@Sun.COM 
120911337SWilliam.Krier@Sun.COM 	if (param->access_mask != SAMR_ALIAS_ACCESS_GET_INFO) {
121011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
121111337SWilliam.Krier@Sun.COM 		goto open_alias_err;
121211337SWilliam.Krier@Sun.COM 	}
121311337SWilliam.Krier@Sun.COM 
121411337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1215*11447Samw@Sun.COM 	gd_type = (smb_gdomain_t)data->kd_type;
1216*11447Samw@Sun.COM 	rid = param->rid;
1217*11447Samw@Sun.COM 
1218*11447Samw@Sun.COM 	switch (gd_type) {
1219*11447Samw@Sun.COM 	case SMB_LGRP_BUILTIN:
1220*11447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1221*11447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1222*11447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1223*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1224*11447Samw@Sun.COM 			goto open_alias_err;
1225*11447Samw@Sun.COM 		}
1226*11447Samw@Sun.COM 
1227*11447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
1228*11447Samw@Sun.COM 		smb_sid_free(sid);
1229*11447Samw@Sun.COM 
1230*11447Samw@Sun.COM 		if (wka == NULL) {
1231*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1232*11447Samw@Sun.COM 			goto open_alias_err;
1233*11447Samw@Sun.COM 		}
1234*11447Samw@Sun.COM 		break;
1235*11447Samw@Sun.COM 
1236*11447Samw@Sun.COM 	case SMB_LGRP_LOCAL:
1237*11447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
1238*11447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
1239*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1240*11447Samw@Sun.COM 			goto open_alias_err;
1241*11447Samw@Sun.COM 		}
1242*11447Samw@Sun.COM 		break;
1243*11447Samw@Sun.COM 
1244*11447Samw@Sun.COM 	default:
124511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
124611337SWilliam.Krier@Sun.COM 		goto open_alias_err;
124711337SWilliam.Krier@Sun.COM 	}
124811337SWilliam.Krier@Sun.COM 
124911337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
125011337SWilliam.Krier@Sun.COM 	if (id) {
125111337SWilliam.Krier@Sun.COM 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
125211337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
125311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
125411337SWilliam.Krier@Sun.COM 	}
125511337SWilliam.Krier@Sun.COM 
125611337SWilliam.Krier@Sun.COM 	status = NT_STATUS_NO_MEMORY;
125711337SWilliam.Krier@Sun.COM 
125811337SWilliam.Krier@Sun.COM open_alias_err:
125911337SWilliam.Krier@Sun.COM 	bzero(&param->alias_handle, sizeof (samr_handle_t));
126011337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
126111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
126211337SWilliam.Krier@Sun.COM }
126311337SWilliam.Krier@Sun.COM 
126411337SWilliam.Krier@Sun.COM /*
126511337SWilliam.Krier@Sun.COM  * samr_s_CreateDomainAlias
126611337SWilliam.Krier@Sun.COM  *
126711337SWilliam.Krier@Sun.COM  * Creates a local group in the security database, which is the
126811337SWilliam.Krier@Sun.COM  * security accounts manager (SAM)
126911337SWilliam.Krier@Sun.COM  * For more information you can look at MSDN page for NetLocalGroupAdd.
127011337SWilliam.Krier@Sun.COM  * This RPC is used by CMC and right now it returns access denied.
127111337SWilliam.Krier@Sun.COM  * The peice of code that creates a local group doesn't get compiled.
127211337SWilliam.Krier@Sun.COM  */
127311337SWilliam.Krier@Sun.COM /*ARGSUSED*/
127411337SWilliam.Krier@Sun.COM static int
127511337SWilliam.Krier@Sun.COM samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
127611337SWilliam.Krier@Sun.COM {
127711337SWilliam.Krier@Sun.COM 	struct samr_CreateDomainAlias *param = arg;
127811337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
127911337SWilliam.Krier@Sun.COM 
128011337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) {
128111337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_CreateDomainAlias));
128211337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
128311337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
128411337SWilliam.Krier@Sun.COM 	}
128511337SWilliam.Krier@Sun.COM 
128611337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_CreateDomainAlias));
128711337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
128811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
128911337SWilliam.Krier@Sun.COM 
129011337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_ADD_ALIAS
129111337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
129211337SWilliam.Krier@Sun.COM 	nt_group_t *grp;
129311337SWilliam.Krier@Sun.COM 	char *alias_name;
129411337SWilliam.Krier@Sun.COM 
129511337SWilliam.Krier@Sun.COM 	alias_name = param->alias_name.str;
129611337SWilliam.Krier@Sun.COM 	if (alias_name == 0) {
129711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_PARAMETER;
129811337SWilliam.Krier@Sun.COM 		goto create_alias_err;
129911337SWilliam.Krier@Sun.COM 	}
130011337SWilliam.Krier@Sun.COM 
130111337SWilliam.Krier@Sun.COM 	/*
130211337SWilliam.Krier@Sun.COM 	 * Check access mask.  User should be member of
130311337SWilliam.Krier@Sun.COM 	 * Administrators or Account Operators local group.
130411337SWilliam.Krier@Sun.COM 	 */
130511337SWilliam.Krier@Sun.COM 	status = nt_group_add(alias_name, 0,
130611337SWilliam.Krier@Sun.COM 	    NT_GROUP_AF_ADD | NT_GROUP_AF_LOCAL);
130711337SWilliam.Krier@Sun.COM 
130811337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS)
130911337SWilliam.Krier@Sun.COM 		goto create_alias_err;
131011337SWilliam.Krier@Sun.COM 
131111337SWilliam.Krier@Sun.COM 	grp = nt_group_getinfo(alias_name, RWLOCK_READER);
131211337SWilliam.Krier@Sun.COM 	if (grp == NULL) {
131311337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INTERNAL_ERROR;
131411337SWilliam.Krier@Sun.COM 		goto create_alias_err;
131511337SWilliam.Krier@Sun.COM 	}
131611337SWilliam.Krier@Sun.COM 
131711337SWilliam.Krier@Sun.COM 	(void) smb_sid_getrid(grp->sid, &param->rid);
131811337SWilliam.Krier@Sun.COM 	nt_group_putinfo(grp);
131911337SWilliam.Krier@Sun.COM 	handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY,
132011337SWilliam.Krier@Sun.COM 	    param->rid);
132111337SWilliam.Krier@Sun.COM 	bcopy(handle, &param->alias_handle, sizeof (samr_handle_t));
132211337SWilliam.Krier@Sun.COM 
132311337SWilliam.Krier@Sun.COM 	param->status = 0;
132411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
132511337SWilliam.Krier@Sun.COM 
132611337SWilliam.Krier@Sun.COM create_alias_err:
132711337SWilliam.Krier@Sun.COM 	bzero(&param->alias_handle, sizeof (samr_handle_t));
132811337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
132911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
133011337SWilliam.Krier@Sun.COM #endif
133111337SWilliam.Krier@Sun.COM }
133211337SWilliam.Krier@Sun.COM 
133311337SWilliam.Krier@Sun.COM /*
133411337SWilliam.Krier@Sun.COM  * samr_s_SetAliasInfo
133511337SWilliam.Krier@Sun.COM  *
133611337SWilliam.Krier@Sun.COM  * Similar to NetLocalGroupSetInfo.
133711337SWilliam.Krier@Sun.COM  */
133811337SWilliam.Krier@Sun.COM static int
133911337SWilliam.Krier@Sun.COM samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
134011337SWilliam.Krier@Sun.COM {
134111337SWilliam.Krier@Sun.COM 	struct samr_SetAliasInfo *param = arg;
134211337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
134311337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
134411337SWilliam.Krier@Sun.COM 
134511337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
134611337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
134711337SWilliam.Krier@Sun.COM 
134811337SWilliam.Krier@Sun.COM 	param->status = status;
134911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
135011337SWilliam.Krier@Sun.COM }
135111337SWilliam.Krier@Sun.COM 
135211337SWilliam.Krier@Sun.COM /*
135311337SWilliam.Krier@Sun.COM  * samr_s_QueryAliasInfo
135411337SWilliam.Krier@Sun.COM  *
135511337SWilliam.Krier@Sun.COM  * Retrieves information about the specified local group account
135611337SWilliam.Krier@Sun.COM  * by given handle.
135711337SWilliam.Krier@Sun.COM  */
135811337SWilliam.Krier@Sun.COM static int
135911337SWilliam.Krier@Sun.COM samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
136011337SWilliam.Krier@Sun.COM {
136111337SWilliam.Krier@Sun.COM 	struct samr_QueryAliasInfo *param = arg;
1362*11447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
1363*11447Samw@Sun.COM 	ndr_handle_t	*hd;
1364*11447Samw@Sun.COM 	samr_keydata_t	*data;
1365*11447Samw@Sun.COM 	smb_group_t	grp;
1366*11447Samw@Sun.COM 	smb_gdomain_t	gd_type;
1367*11447Samw@Sun.COM 	smb_sid_t	*sid;
1368*11447Samw@Sun.COM 	smb_wka_t	*wka;
1369*11447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
1370*11447Samw@Sun.COM 	char		*name;
1371*11447Samw@Sun.COM 	char		*desc;
1372*11447Samw@Sun.COM 	uint32_t	rid;
1373*11447Samw@Sun.COM 	uint32_t	status;
1374*11447Samw@Sun.COM 	int		rc;
137511337SWilliam.Krier@Sun.COM 
137611337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
137711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
137811337SWilliam.Krier@Sun.COM 		goto query_alias_err;
137911337SWilliam.Krier@Sun.COM 	}
138011337SWilliam.Krier@Sun.COM 
138111337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1382*11447Samw@Sun.COM 	gd_type = (smb_gdomain_t)data->kd_type;
1383*11447Samw@Sun.COM 	rid = data->kd_rid;
1384*11447Samw@Sun.COM 
1385*11447Samw@Sun.COM 	switch (gd_type) {
1386*11447Samw@Sun.COM 	case SMB_LGRP_BUILTIN:
1387*11447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1388*11447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1389*11447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1390*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1391*11447Samw@Sun.COM 			goto query_alias_err;
1392*11447Samw@Sun.COM 		}
1393*11447Samw@Sun.COM 
1394*11447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
1395*11447Samw@Sun.COM 		smb_sid_free(sid);
1396*11447Samw@Sun.COM 
1397*11447Samw@Sun.COM 		if (wka == NULL) {
1398*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1399*11447Samw@Sun.COM 			goto query_alias_err;
1400*11447Samw@Sun.COM 		}
1401*11447Samw@Sun.COM 
1402*11447Samw@Sun.COM 		name = wka->wka_name;
1403*11447Samw@Sun.COM 		desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
1404*11447Samw@Sun.COM 		break;
1405*11447Samw@Sun.COM 
1406*11447Samw@Sun.COM 	case SMB_LGRP_LOCAL:
1407*11447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1408*11447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
1409*11447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
1410*11447Samw@Sun.COM 			goto query_alias_err;
1411*11447Samw@Sun.COM 		}
1412*11447Samw@Sun.COM 		name = grp.sg_name;
1413*11447Samw@Sun.COM 		desc = grp.sg_cmnt;
1414*11447Samw@Sun.COM 		break;
1415*11447Samw@Sun.COM 
1416*11447Samw@Sun.COM 	default:
141711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
141811337SWilliam.Krier@Sun.COM 		goto query_alias_err;
141911337SWilliam.Krier@Sun.COM 	}
142011337SWilliam.Krier@Sun.COM 
142111337SWilliam.Krier@Sun.COM 	switch (param->level) {
142211337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_1:
142311337SWilliam.Krier@Sun.COM 		param->ru.info1.level = param->level;
1424*11447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, name,
142511337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.name);
142611337SWilliam.Krier@Sun.COM 
1427*11447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
142811337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.desc);
142911337SWilliam.Krier@Sun.COM 
143011337SWilliam.Krier@Sun.COM 		param->ru.info1.unknown = 1;
143111337SWilliam.Krier@Sun.COM 		break;
143211337SWilliam.Krier@Sun.COM 
143311337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_3:
143411337SWilliam.Krier@Sun.COM 		param->ru.info3.level = param->level;
1435*11447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
143611337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info3.desc);
143711337SWilliam.Krier@Sun.COM 		break;
143811337SWilliam.Krier@Sun.COM 
143911337SWilliam.Krier@Sun.COM 	default:
1440*11447Samw@Sun.COM 		if (gd_type == SMB_LGRP_LOCAL)
1441*11447Samw@Sun.COM 			smb_lgrp_free(&grp);
144211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
144311337SWilliam.Krier@Sun.COM 		goto query_alias_err;
144411337SWilliam.Krier@Sun.COM 	};
144511337SWilliam.Krier@Sun.COM 
1446*11447Samw@Sun.COM 	if (gd_type == SMB_LGRP_LOCAL)
1447*11447Samw@Sun.COM 		smb_lgrp_free(&grp);
144811337SWilliam.Krier@Sun.COM 	param->address = (DWORD)(uintptr_t)&param->ru;
144911337SWilliam.Krier@Sun.COM 	param->status = 0;
145011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
145111337SWilliam.Krier@Sun.COM 
145211337SWilliam.Krier@Sun.COM query_alias_err:
145311337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
145411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
145511337SWilliam.Krier@Sun.COM }
145611337SWilliam.Krier@Sun.COM 
145711337SWilliam.Krier@Sun.COM /*
145811337SWilliam.Krier@Sun.COM  * samr_s_DeleteDomainAlias
145911337SWilliam.Krier@Sun.COM  *
146011337SWilliam.Krier@Sun.COM  * Deletes a local group account and all its members from the
146111337SWilliam.Krier@Sun.COM  * security database, which is the security accounts manager (SAM) database.
146211337SWilliam.Krier@Sun.COM  * Only members of the Administrators or Account Operators local group can
146311337SWilliam.Krier@Sun.COM  * execute this function.
146411337SWilliam.Krier@Sun.COM  * For more information you can look at MSDN page for NetLocalGroupSetInfo.
146511337SWilliam.Krier@Sun.COM  *
146611337SWilliam.Krier@Sun.COM  * This RPC is used by CMC and right now it returns access denied.
146711337SWilliam.Krier@Sun.COM  * The peice of code that removes a local group doesn't get compiled.
146811337SWilliam.Krier@Sun.COM  */
146911337SWilliam.Krier@Sun.COM static int
147011337SWilliam.Krier@Sun.COM samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
147111337SWilliam.Krier@Sun.COM {
147211337SWilliam.Krier@Sun.COM 	struct samr_DeleteDomainAlias *param = arg;
147311337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
147411337SWilliam.Krier@Sun.COM 
147511337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) {
147611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
147711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
147811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
147911337SWilliam.Krier@Sun.COM 	}
148011337SWilliam.Krier@Sun.COM 
148111337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_DeleteDomainAlias));
148211337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
148311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
148411337SWilliam.Krier@Sun.COM 
148511337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_DEL_ALIAS
148611337SWilliam.Krier@Sun.COM 	nt_group_t *grp;
148711337SWilliam.Krier@Sun.COM 	char *alias_name;
148811337SWilliam.Krier@Sun.COM 	DWORD status;
148911337SWilliam.Krier@Sun.COM 
149011337SWilliam.Krier@Sun.COM 	grp = nt_groups_lookup_rid(desc->discrim);
149111337SWilliam.Krier@Sun.COM 	if (grp == 0) {
149211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
149311337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
149411337SWilliam.Krier@Sun.COM 	}
149511337SWilliam.Krier@Sun.COM 
149611337SWilliam.Krier@Sun.COM 	alias_name = strdup(grp->name);
149711337SWilliam.Krier@Sun.COM 	if (alias_name == 0) {
149811337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
149911337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
150011337SWilliam.Krier@Sun.COM 	}
150111337SWilliam.Krier@Sun.COM 
150211337SWilliam.Krier@Sun.COM 	status = nt_group_delete(alias_name);
150311337SWilliam.Krier@Sun.COM 	free(alias_name);
150411337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS)
150511337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
150611337SWilliam.Krier@Sun.COM 
150711337SWilliam.Krier@Sun.COM 	param->status = 0;
150811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
150911337SWilliam.Krier@Sun.COM 
151011337SWilliam.Krier@Sun.COM delete_alias_err:
151111337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
151211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
151311337SWilliam.Krier@Sun.COM #endif
151411337SWilliam.Krier@Sun.COM }
151511337SWilliam.Krier@Sun.COM 
151611337SWilliam.Krier@Sun.COM /*
151711337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainAliases
151811337SWilliam.Krier@Sun.COM  *
151911337SWilliam.Krier@Sun.COM  * This function sends back a list which contains all local groups' name.
152011337SWilliam.Krier@Sun.COM  */
152111337SWilliam.Krier@Sun.COM static int
152211337SWilliam.Krier@Sun.COM samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
152311337SWilliam.Krier@Sun.COM {
152411337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainAliases *param = arg;
152511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
152611337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
152711337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
152811337SWilliam.Krier@Sun.COM 	smb_group_t grp;
152911337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
153011337SWilliam.Krier@Sun.COM 	int cnt, skip, i;
153111337SWilliam.Krier@Sun.COM 	struct name_rid *info;
153211337SWilliam.Krier@Sun.COM 
153311337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
153411337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
153511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
153611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
153711337SWilliam.Krier@Sun.COM 	}
153811337SWilliam.Krier@Sun.COM 
153911337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
154011337SWilliam.Krier@Sun.COM 
154111337SWilliam.Krier@Sun.COM 	cnt = smb_sam_grp_cnt(data->kd_type);
154211337SWilliam.Krier@Sun.COM 	if (cnt <= param->resume_handle) {
154311337SWilliam.Krier@Sun.COM 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
154411337SWilliam.Krier@Sun.COM 		    sizeof (struct aliases_info));
154511337SWilliam.Krier@Sun.COM 
154611337SWilliam.Krier@Sun.COM 		if (param->aliases == NULL) {
154711337SWilliam.Krier@Sun.COM 			bzero(param, sizeof (struct samr_EnumDomainAliases));
154811337SWilliam.Krier@Sun.COM 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
154911337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
155011337SWilliam.Krier@Sun.COM 		}
155111337SWilliam.Krier@Sun.COM 
155211337SWilliam.Krier@Sun.COM 		bzero(param->aliases, sizeof (struct aliases_info));
155311337SWilliam.Krier@Sun.COM 		param->out_resume = 0;
155411337SWilliam.Krier@Sun.COM 		param->entries = 0;
155511337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
155611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
155711337SWilliam.Krier@Sun.COM 	}
155811337SWilliam.Krier@Sun.COM 
155911337SWilliam.Krier@Sun.COM 	cnt -= param->resume_handle;
156011337SWilliam.Krier@Sun.COM 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
156111337SWilliam.Krier@Sun.COM 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
156211337SWilliam.Krier@Sun.COM 
156311337SWilliam.Krier@Sun.COM 	if (param->aliases == NULL) {
156411337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
156511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
156611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
156711337SWilliam.Krier@Sun.COM 	}
156811337SWilliam.Krier@Sun.COM 
156911337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
157011337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
157111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
157211337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
157311337SWilliam.Krier@Sun.COM 	}
157411337SWilliam.Krier@Sun.COM 
157511337SWilliam.Krier@Sun.COM 	skip = i = 0;
157611337SWilliam.Krier@Sun.COM 	info = param->aliases->info;
157711337SWilliam.Krier@Sun.COM 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
157811337SWilliam.Krier@Sun.COM 		if ((skip++ >= param->resume_handle) &&
157911337SWilliam.Krier@Sun.COM 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
158011337SWilliam.Krier@Sun.COM 			info->rid = grp.sg_rid;
158111337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, grp.sg_name,
158211337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&info->name);
158311337SWilliam.Krier@Sun.COM 
158411337SWilliam.Krier@Sun.COM 			info++;
158511337SWilliam.Krier@Sun.COM 		}
158611337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
158711337SWilliam.Krier@Sun.COM 	}
158811337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
158911337SWilliam.Krier@Sun.COM 
159011337SWilliam.Krier@Sun.COM 	param->aliases->count = i;
159111337SWilliam.Krier@Sun.COM 	param->aliases->address = i;
159211337SWilliam.Krier@Sun.COM 
159311337SWilliam.Krier@Sun.COM 	param->out_resume = i;
159411337SWilliam.Krier@Sun.COM 	param->entries = i;
159511337SWilliam.Krier@Sun.COM 	param->status = 0;
159611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
159711337SWilliam.Krier@Sun.COM }
159811337SWilliam.Krier@Sun.COM 
159911337SWilliam.Krier@Sun.COM /*
160011337SWilliam.Krier@Sun.COM  * samr_s_Connect3
160111337SWilliam.Krier@Sun.COM  */
160211337SWilliam.Krier@Sun.COM static int
160311337SWilliam.Krier@Sun.COM samr_s_Connect3(void *arg, ndr_xa_t *mxa)
160411337SWilliam.Krier@Sun.COM {
1605*11447Samw@Sun.COM 	struct samr_Connect3	*param = arg;
1606*11447Samw@Sun.COM 	ndr_hdid_t		*id;
160711337SWilliam.Krier@Sun.COM 
1608*11447Samw@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1609*11447Samw@Sun.COM 	if (id) {
1610*11447Samw@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1611*11447Samw@Sun.COM 		param->status = 0;
1612*11447Samw@Sun.COM 	} else {
1613*11447Samw@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
1614*11447Samw@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1615*11447Samw@Sun.COM 	}
1616*11447Samw@Sun.COM 
1617*11447Samw@Sun.COM 	return (NDR_DRC_OK);
161811337SWilliam.Krier@Sun.COM }
161911337SWilliam.Krier@Sun.COM 
162011337SWilliam.Krier@Sun.COM /*
162111337SWilliam.Krier@Sun.COM  * samr_s_Connect4
162211337SWilliam.Krier@Sun.COM  *
162311337SWilliam.Krier@Sun.COM  * This is the connect4 form of the connect request used by Windows XP.
162411337SWilliam.Krier@Sun.COM  * Returns an RPC fault for now.
162511337SWilliam.Krier@Sun.COM  */
162611337SWilliam.Krier@Sun.COM /*ARGSUSED*/
162711337SWilliam.Krier@Sun.COM static int
162811337SWilliam.Krier@Sun.COM samr_s_Connect4(void *arg, ndr_xa_t *mxa)
162911337SWilliam.Krier@Sun.COM {
163011337SWilliam.Krier@Sun.COM 	struct samr_Connect4 *param = arg;
163111337SWilliam.Krier@Sun.COM 
163211337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_Connect4));
163311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
163411337SWilliam.Krier@Sun.COM }
163511337SWilliam.Krier@Sun.COM 
163611337SWilliam.Krier@Sun.COM static ndr_stub_table_t samr_stub_table[] = {
163711337SWilliam.Krier@Sun.COM 	{ samr_s_ConnectAnon,		SAMR_OPNUM_ConnectAnon },
163811337SWilliam.Krier@Sun.COM 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
163911337SWilliam.Krier@Sun.COM 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
164011337SWilliam.Krier@Sun.COM 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
164111337SWilliam.Krier@Sun.COM 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
164211337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
1643*11447Samw@Sun.COM 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
164411337SWilliam.Krier@Sun.COM 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
164511337SWilliam.Krier@Sun.COM 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
164611337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
164711337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
164811337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
164911337SWilliam.Krier@Sun.COM 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
165011337SWilliam.Krier@Sun.COM 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
165111337SWilliam.Krier@Sun.COM 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
165211337SWilliam.Krier@Sun.COM 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
165311337SWilliam.Krier@Sun.COM 	{ samr_s_ChangeUserPasswd,	SAMR_OPNUM_ChangeUserPasswd },
165411337SWilliam.Krier@Sun.COM 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
165511337SWilliam.Krier@Sun.COM 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
165611337SWilliam.Krier@Sun.COM 	{ samr_s_Connect3,		SAMR_OPNUM_Connect3 },
165711337SWilliam.Krier@Sun.COM 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
165811337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
165911337SWilliam.Krier@Sun.COM 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
166011337SWilliam.Krier@Sun.COM 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
166111337SWilliam.Krier@Sun.COM 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
166211337SWilliam.Krier@Sun.COM 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
166311337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
166411337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
166511337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainGroups,	SAMR_OPNUM_EnumDomainGroups },
166611337SWilliam.Krier@Sun.COM 	{0}
166711337SWilliam.Krier@Sun.COM };
166811337SWilliam.Krier@Sun.COM 
166911337SWilliam.Krier@Sun.COM /*
167011337SWilliam.Krier@Sun.COM  * There is a bug in the way that midl and the marshalling code handles
167111337SWilliam.Krier@Sun.COM  * unions so we need to fix some of the data offsets at runtime. The
167211337SWilliam.Krier@Sun.COM  * following macros and the fixup functions handle the corrections.
167311337SWilliam.Krier@Sun.COM  */
167411337SWilliam.Krier@Sun.COM 
167511337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
167611337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
167711337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
167811337SWilliam.Krier@Sun.COM 
167911337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
168011337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result);
168111337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryUserInfo);
168211337SWilliam.Krier@Sun.COM 
168311337SWilliam.Krier@Sun.COM void
168411337SWilliam.Krier@Sun.COM fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
168511337SWilliam.Krier@Sun.COM {
168611337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
168711337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
168811337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
168911337SWilliam.Krier@Sun.COM 
169011337SWilliam.Krier@Sun.COM 	switch (val->level) {
169111337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 1);
169211337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 3);
169311337SWilliam.Krier@Sun.COM 
169411337SWilliam.Krier@Sun.COM 		default:
169511337SWilliam.Krier@Sun.COM 			return;
169611337SWilliam.Krier@Sun.COM 	};
169711337SWilliam.Krier@Sun.COM 
169811337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
169911337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
170011337SWilliam.Krier@Sun.COM 
170111337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
170211337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
170311337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
170411337SWilliam.Krier@Sun.COM }
170511337SWilliam.Krier@Sun.COM 
170611337SWilliam.Krier@Sun.COM void
170711337SWilliam.Krier@Sun.COM fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
170811337SWilliam.Krier@Sun.COM {
170911337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
171011337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
171111337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
171211337SWilliam.Krier@Sun.COM 
171311337SWilliam.Krier@Sun.COM 	switch (val->switch_index) {
171411337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
171511337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
171611337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
171711337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
171811337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
171911337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
172011337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
172111337SWilliam.Krier@Sun.COM 
172211337SWilliam.Krier@Sun.COM 		default:
172311337SWilliam.Krier@Sun.COM 			return;
172411337SWilliam.Krier@Sun.COM 	};
172511337SWilliam.Krier@Sun.COM 
172611337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
172711337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
172811337SWilliam.Krier@Sun.COM 
172911337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
173011337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
173111337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
173211337SWilliam.Krier@Sun.COM }
173311337SWilliam.Krier@Sun.COM 
173411337SWilliam.Krier@Sun.COM /*
173511337SWilliam.Krier@Sun.COM  * As long as there is only one entry in the union, there is no need
173611337SWilliam.Krier@Sun.COM  * to patch anything.
173711337SWilliam.Krier@Sun.COM  */
173811337SWilliam.Krier@Sun.COM /*ARGSUSED*/
173911337SWilliam.Krier@Sun.COM void
174011337SWilliam.Krier@Sun.COM fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
174111337SWilliam.Krier@Sun.COM {
174211337SWilliam.Krier@Sun.COM }
1743