xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (revision 11963:061945695ce1)
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 /*
2211447Samw@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 {
159*11963SAfshin.Ardakani@Sun.COM 	ndr_handle_t	*hd;
160*11963SAfshin.Ardakani@Sun.COM 	ndr_hdid_t	*id;
161*11963SAfshin.Ardakani@Sun.COM 	samr_keydata_t	*data;
16211337SWilliam.Krier@Sun.COM 
16311337SWilliam.Krier@Sun.COM 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
16411337SWilliam.Krier@Sun.COM 		return (NULL);
16511337SWilliam.Krier@Sun.COM 
16611337SWilliam.Krier@Sun.COM 	data->kd_key = key;
16711337SWilliam.Krier@Sun.COM 	data->kd_type = domain_type;
16811337SWilliam.Krier@Sun.COM 	data->kd_rid = rid;
16911337SWilliam.Krier@Sun.COM 
170*11963SAfshin.Ardakani@Sun.COM 	if ((id = ndr_hdalloc(mxa, data)) == NULL) {
171*11963SAfshin.Ardakani@Sun.COM 		free(data);
172*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
173*11963SAfshin.Ardakani@Sun.COM 	}
174*11963SAfshin.Ardakani@Sun.COM 
175*11963SAfshin.Ardakani@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
176*11963SAfshin.Ardakani@Sun.COM 		hd->nh_data_free = free;
177*11963SAfshin.Ardakani@Sun.COM 
178*11963SAfshin.Ardakani@Sun.COM 	return (id);
17911337SWilliam.Krier@Sun.COM }
18011337SWilliam.Krier@Sun.COM 
18111337SWilliam.Krier@Sun.COM /*
18211337SWilliam.Krier@Sun.COM  * Handle deallocation wrapper to free the local context.
18311337SWilliam.Krier@Sun.COM  */
18411337SWilliam.Krier@Sun.COM static void
18511337SWilliam.Krier@Sun.COM samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
18611337SWilliam.Krier@Sun.COM {
18711337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
18811337SWilliam.Krier@Sun.COM 
18911337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
19011337SWilliam.Krier@Sun.COM 		free(hd->nh_data);
191*11963SAfshin.Ardakani@Sun.COM 		hd->nh_data = NULL;
19211337SWilliam.Krier@Sun.COM 		ndr_hdfree(mxa, id);
19311337SWilliam.Krier@Sun.COM 	}
19411337SWilliam.Krier@Sun.COM }
19511337SWilliam.Krier@Sun.COM 
19611337SWilliam.Krier@Sun.COM /*
19711337SWilliam.Krier@Sun.COM  * Handle lookup wrapper to validate the local context.
19811337SWilliam.Krier@Sun.COM  */
19911337SWilliam.Krier@Sun.COM static ndr_handle_t *
20011337SWilliam.Krier@Sun.COM samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
20111337SWilliam.Krier@Sun.COM {
20211337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
20311337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
20411337SWilliam.Krier@Sun.COM 
20511337SWilliam.Krier@Sun.COM 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
20611337SWilliam.Krier@Sun.COM 		return (NULL);
20711337SWilliam.Krier@Sun.COM 
20811337SWilliam.Krier@Sun.COM 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
20911337SWilliam.Krier@Sun.COM 		return (NULL);
21011337SWilliam.Krier@Sun.COM 
21111337SWilliam.Krier@Sun.COM 	if (data->kd_key != key)
21211337SWilliam.Krier@Sun.COM 		return (NULL);
21311337SWilliam.Krier@Sun.COM 
21411337SWilliam.Krier@Sun.COM 	return (hd);
21511337SWilliam.Krier@Sun.COM }
21611337SWilliam.Krier@Sun.COM 
21711337SWilliam.Krier@Sun.COM /*
21811337SWilliam.Krier@Sun.COM  * samr_s_ConnectAnon
21911337SWilliam.Krier@Sun.COM  *
22011337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database. We don't
22111337SWilliam.Krier@Sun.COM  * support any form of update request and our database doesn't
22211337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in
22311337SWilliam.Krier@Sun.COM  * doing any access access checking here.
22411337SWilliam.Krier@Sun.COM  *
22511337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
22611337SWilliam.Krier@Sun.COM  */
22711337SWilliam.Krier@Sun.COM static int
22811337SWilliam.Krier@Sun.COM samr_s_ConnectAnon(void *arg, ndr_xa_t *mxa)
22911337SWilliam.Krier@Sun.COM {
23011337SWilliam.Krier@Sun.COM 	struct samr_ConnectAnon *param = arg;
23111337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
23211337SWilliam.Krier@Sun.COM 
23311337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
23411337SWilliam.Krier@Sun.COM 	if (id) {
23511337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
23611337SWilliam.Krier@Sun.COM 		param->status = 0;
23711337SWilliam.Krier@Sun.COM 	} else {
23811337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
23911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
24011337SWilliam.Krier@Sun.COM 	}
24111337SWilliam.Krier@Sun.COM 
24211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
24311337SWilliam.Krier@Sun.COM }
24411337SWilliam.Krier@Sun.COM 
24511337SWilliam.Krier@Sun.COM /*
24611337SWilliam.Krier@Sun.COM  * samr_s_CloseHandle
24711337SWilliam.Krier@Sun.COM  *
24811337SWilliam.Krier@Sun.COM  * Close the SAM interface specified by the handle.
24911337SWilliam.Krier@Sun.COM  * Free the handle and zero out the result handle for the client.
25011337SWilliam.Krier@Sun.COM  */
25111337SWilliam.Krier@Sun.COM static int
25211337SWilliam.Krier@Sun.COM samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
25311337SWilliam.Krier@Sun.COM {
25411337SWilliam.Krier@Sun.COM 	struct samr_CloseHandle *param = arg;
25511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
25611337SWilliam.Krier@Sun.COM 
25711337SWilliam.Krier@Sun.COM 	samr_hdfree(mxa, id);
25811337SWilliam.Krier@Sun.COM 
25911337SWilliam.Krier@Sun.COM 	bzero(&param->result_handle, sizeof (samr_handle_t));
26011337SWilliam.Krier@Sun.COM 	param->status = 0;
26111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
26211337SWilliam.Krier@Sun.COM }
26311337SWilliam.Krier@Sun.COM 
26411337SWilliam.Krier@Sun.COM /*
26511337SWilliam.Krier@Sun.COM  * samr_s_LookupDomain
26611337SWilliam.Krier@Sun.COM  *
26711337SWilliam.Krier@Sun.COM  * This is a request to map a domain name to a domain SID. We can map
26811337SWilliam.Krier@Sun.COM  * the primary domain name, our local domain name (hostname) and the
26911337SWilliam.Krier@Sun.COM  * builtin domain names to the appropriate SID. Anything else will be
27011337SWilliam.Krier@Sun.COM  * rejected.
27111337SWilliam.Krier@Sun.COM  */
27211337SWilliam.Krier@Sun.COM static int
27311337SWilliam.Krier@Sun.COM samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
27411337SWilliam.Krier@Sun.COM {
27511337SWilliam.Krier@Sun.COM 	struct samr_LookupDomain *param = arg;
27611337SWilliam.Krier@Sun.COM 	char *domain_name;
27711337SWilliam.Krier@Sun.COM 	smb_domain_t di;
27811337SWilliam.Krier@Sun.COM 
27911337SWilliam.Krier@Sun.COM 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
28011337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
28111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
28211337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
28311337SWilliam.Krier@Sun.COM 	}
28411337SWilliam.Krier@Sun.COM 
28511337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_name(domain_name, &di)) {
28611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
28711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
28811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
28911337SWilliam.Krier@Sun.COM 	}
29011337SWilliam.Krier@Sun.COM 
29111337SWilliam.Krier@Sun.COM 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
29211337SWilliam.Krier@Sun.COM 	if (param->sid == NULL) {
29311337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupDomain));
29411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
29511337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
29611337SWilliam.Krier@Sun.COM 	}
29711337SWilliam.Krier@Sun.COM 
29811337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
29911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
30011337SWilliam.Krier@Sun.COM }
30111337SWilliam.Krier@Sun.COM 
30211337SWilliam.Krier@Sun.COM /*
30311337SWilliam.Krier@Sun.COM  * samr_s_EnumLocalDomains
30411337SWilliam.Krier@Sun.COM  *
30511337SWilliam.Krier@Sun.COM  * This is a request for the local domains supported by this server.
30611337SWilliam.Krier@Sun.COM  * All we do here is validate the handle and set the status. The real
30711337SWilliam.Krier@Sun.COM  * work is done in samr_s_enum_local_domains.
30811337SWilliam.Krier@Sun.COM  */
30911337SWilliam.Krier@Sun.COM static int
31011337SWilliam.Krier@Sun.COM samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
31111337SWilliam.Krier@Sun.COM {
31211337SWilliam.Krier@Sun.COM 	struct samr_EnumLocalDomain *param = arg;
31311337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
31411337SWilliam.Krier@Sun.COM 	DWORD status;
31511337SWilliam.Krier@Sun.COM 
31611337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
31711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
31811337SWilliam.Krier@Sun.COM 	else
31911337SWilliam.Krier@Sun.COM 		status = samr_s_enum_local_domains(param, mxa);
32011337SWilliam.Krier@Sun.COM 
32111337SWilliam.Krier@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
32211337SWilliam.Krier@Sun.COM 		param->enum_context = param->info->entries_read;
32311337SWilliam.Krier@Sun.COM 		param->total_entries = param->info->entries_read;
32411337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
32511337SWilliam.Krier@Sun.COM 	} else {
32611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumLocalDomain));
32711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
32811337SWilliam.Krier@Sun.COM 	}
32911337SWilliam.Krier@Sun.COM 
33011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
33111337SWilliam.Krier@Sun.COM }
33211337SWilliam.Krier@Sun.COM 
33311337SWilliam.Krier@Sun.COM 
33411337SWilliam.Krier@Sun.COM /*
33511337SWilliam.Krier@Sun.COM  * samr_s_enum_local_domains
33611337SWilliam.Krier@Sun.COM  *
33711337SWilliam.Krier@Sun.COM  * This function should only be called via samr_s_EnumLocalDomains to
33811337SWilliam.Krier@Sun.COM  * ensure that the appropriate validation is performed. We will answer
33911337SWilliam.Krier@Sun.COM  * queries about two domains: the local domain, synonymous with the
34011337SWilliam.Krier@Sun.COM  * local hostname, and the BUILTIN domain. So we return these two
34111337SWilliam.Krier@Sun.COM  * strings.
34211337SWilliam.Krier@Sun.COM  *
34311337SWilliam.Krier@Sun.COM  * Returns NT status values.
34411337SWilliam.Krier@Sun.COM  */
34511337SWilliam.Krier@Sun.COM static DWORD
34611337SWilliam.Krier@Sun.COM samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
34711337SWilliam.Krier@Sun.COM     ndr_xa_t *mxa)
34811337SWilliam.Krier@Sun.COM {
34911337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainInfo *info;
35011337SWilliam.Krier@Sun.COM 	struct samr_LocalDomainEntry *entry;
35111337SWilliam.Krier@Sun.COM 	char *hostname;
35211337SWilliam.Krier@Sun.COM 
35311337SWilliam.Krier@Sun.COM 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
35411337SWilliam.Krier@Sun.COM 	if (hostname == NULL)
35511337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
35611337SWilliam.Krier@Sun.COM 
35711337SWilliam.Krier@Sun.COM 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
35811337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
35911337SWilliam.Krier@Sun.COM 
36011337SWilliam.Krier@Sun.COM 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
36111337SWilliam.Krier@Sun.COM 	if (entry == NULL)
36211337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
36311337SWilliam.Krier@Sun.COM 
36411337SWilliam.Krier@Sun.COM 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
36511337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
36611337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
36711337SWilliam.Krier@Sun.COM 
36811337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
36911337SWilliam.Krier@Sun.COM 	if (info == NULL)
37011337SWilliam.Krier@Sun.COM 		return (NT_STATUS_NO_MEMORY);
37111337SWilliam.Krier@Sun.COM 
37211337SWilliam.Krier@Sun.COM 	info->entries_read = 2;
37311337SWilliam.Krier@Sun.COM 	info->entry = entry;
37411337SWilliam.Krier@Sun.COM 	param->info = info;
37511337SWilliam.Krier@Sun.COM 	return (NT_STATUS_SUCCESS);
37611337SWilliam.Krier@Sun.COM }
37711337SWilliam.Krier@Sun.COM 
37811337SWilliam.Krier@Sun.COM /*
37911337SWilliam.Krier@Sun.COM  * samr_s_OpenDomain
38011337SWilliam.Krier@Sun.COM  *
38111337SWilliam.Krier@Sun.COM  * This is a request to open a domain within the local SAM database.
38211337SWilliam.Krier@Sun.COM  * The caller must supply a valid connect handle.
38311337SWilliam.Krier@Sun.COM  * We return a handle to be used to access objects within this domain.
38411337SWilliam.Krier@Sun.COM  */
38511337SWilliam.Krier@Sun.COM static int
38611337SWilliam.Krier@Sun.COM samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
38711337SWilliam.Krier@Sun.COM {
38811337SWilliam.Krier@Sun.COM 	struct samr_OpenDomain *param = arg;
38911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
39011337SWilliam.Krier@Sun.COM 	smb_domain_t domain;
39111337SWilliam.Krier@Sun.COM 
39211337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
39311337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
39411337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
39511337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
39611337SWilliam.Krier@Sun.COM 	}
39711337SWilliam.Krier@Sun.COM 
39811337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
39911337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
40011337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
40111337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
40211337SWilliam.Krier@Sun.COM 	}
40311337SWilliam.Krier@Sun.COM 
40411337SWilliam.Krier@Sun.COM 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
40511337SWilliam.Krier@Sun.COM 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
40611337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
40711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
40811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
40911337SWilliam.Krier@Sun.COM 	}
41011337SWilliam.Krier@Sun.COM 
41111337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
41211337SWilliam.Krier@Sun.COM 	if (id) {
41311337SWilliam.Krier@Sun.COM 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
41411337SWilliam.Krier@Sun.COM 		param->status = 0;
41511337SWilliam.Krier@Sun.COM 	} else {
41611337SWilliam.Krier@Sun.COM 		bzero(&param->domain_handle, sizeof (samr_handle_t));
41711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
41811337SWilliam.Krier@Sun.COM 	}
41911337SWilliam.Krier@Sun.COM 
42011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
42111337SWilliam.Krier@Sun.COM }
42211337SWilliam.Krier@Sun.COM 
42311337SWilliam.Krier@Sun.COM /*
42411337SWilliam.Krier@Sun.COM  * samr_s_QueryDomainInfo
42511337SWilliam.Krier@Sun.COM  *
42611337SWilliam.Krier@Sun.COM  * The caller should pass a domain handle.
42711337SWilliam.Krier@Sun.COM  *
42811337SWilliam.Krier@Sun.COM  * Windows 95 Server Manager sends requests for levels 6 and 7 when
42911337SWilliam.Krier@Sun.COM  * the services menu item is selected. Level 2 is basically for getting
43011337SWilliam.Krier@Sun.COM  * number of users, groups, and aliases in a domain.
43111337SWilliam.Krier@Sun.COM  * We have no information on what the various information levels mean.
43211337SWilliam.Krier@Sun.COM  */
43311337SWilliam.Krier@Sun.COM static int
43411337SWilliam.Krier@Sun.COM samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
43511337SWilliam.Krier@Sun.COM {
43611337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfo *param = arg;
43711337SWilliam.Krier@Sun.COM 	struct samr_QueryDomainInfoRes *info;
43811337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
43911337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
44011337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
44111337SWilliam.Krier@Sun.COM 	char *domain;
44211337SWilliam.Krier@Sun.COM 	char hostname[NETBIOS_NAME_SZ];
44311337SWilliam.Krier@Sun.COM 	int alias_cnt, user_cnt;
44411337SWilliam.Krier@Sun.COM 	int rc = 0;
44511337SWilliam.Krier@Sun.COM 
44611337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
44711337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
44811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
44911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
45011337SWilliam.Krier@Sun.COM 	}
45111337SWilliam.Krier@Sun.COM 
45211337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
45311337SWilliam.Krier@Sun.COM 	if (info == NULL) {
45411337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
45511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
45611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
45711337SWilliam.Krier@Sun.COM 	}
45811337SWilliam.Krier@Sun.COM 	info->switch_value = param->info_level;
45911337SWilliam.Krier@Sun.COM 	param->info = info;
46011337SWilliam.Krier@Sun.COM 
46111337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
46211337SWilliam.Krier@Sun.COM 
46311337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
46411337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
46511337SWilliam.Krier@Sun.COM 		domain = "BUILTIN";
46611337SWilliam.Krier@Sun.COM 		user_cnt = 0;
46711337SWilliam.Krier@Sun.COM 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
46811337SWilliam.Krier@Sun.COM 		break;
46911337SWilliam.Krier@Sun.COM 
47011337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
47111337SWilliam.Krier@Sun.COM 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
47211337SWilliam.Krier@Sun.COM 		if (rc == 0) {
47311337SWilliam.Krier@Sun.COM 			domain = hostname;
47411337SWilliam.Krier@Sun.COM 			user_cnt = smb_sam_usr_cnt();
47511337SWilliam.Krier@Sun.COM 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
47611337SWilliam.Krier@Sun.COM 		}
47711337SWilliam.Krier@Sun.COM 		break;
47811337SWilliam.Krier@Sun.COM 
47911337SWilliam.Krier@Sun.COM 	default:
48011337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
48111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
48211337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
48311337SWilliam.Krier@Sun.COM 	}
48411337SWilliam.Krier@Sun.COM 
48511337SWilliam.Krier@Sun.COM 	if (rc != 0) {
48611337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
48711337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
48811337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
48911337SWilliam.Krier@Sun.COM 	}
49011337SWilliam.Krier@Sun.COM 
49111337SWilliam.Krier@Sun.COM 	switch (param->info_level) {
49211337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_6:
49311337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown1 = 0x00000000;
49411337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown2 = 0x00147FB0;
49511337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown3 = 0x00000000;
49611337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown4 = 0x00000000;
49711337SWilliam.Krier@Sun.COM 		info->ru.info6.unknown5 = 0x00000000;
49811337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
49911337SWilliam.Krier@Sun.COM 		break;
50011337SWilliam.Krier@Sun.COM 
50111337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_7:
50211337SWilliam.Krier@Sun.COM 		info->ru.info7.unknown1 = 0x00000003;
50311337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
50411337SWilliam.Krier@Sun.COM 		break;
50511337SWilliam.Krier@Sun.COM 
50611337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_DOMAIN_INFO_2:
50711337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown1 = 0x00000000;
50811337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown2 = 0x80000000;
50911337SWilliam.Krier@Sun.COM 
51011337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
51111337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s1));
51211337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, domain,
51311337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.domain));
51411337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "",
51511337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&(info->ru.info2.s2));
51611337SWilliam.Krier@Sun.COM 
51711337SWilliam.Krier@Sun.COM 		info->ru.info2.sequence_num = 0x0000002B;
51811337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown3 = 0x00000000;
51911337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown4 = 0x00000001;
52011337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown5 = 0x00000003;
52111337SWilliam.Krier@Sun.COM 		info->ru.info2.unknown6 = 0x00000001;
52211337SWilliam.Krier@Sun.COM 		info->ru.info2.num_users = user_cnt;
52311337SWilliam.Krier@Sun.COM 		info->ru.info2.num_groups = 0;
52411337SWilliam.Krier@Sun.COM 		info->ru.info2.num_aliases = alias_cnt;
52511337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
52611337SWilliam.Krier@Sun.COM 		break;
52711337SWilliam.Krier@Sun.COM 
52811337SWilliam.Krier@Sun.COM 	default:
52911337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_QueryDomainInfo));
53011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
53111337SWilliam.Krier@Sun.COM 	};
53211337SWilliam.Krier@Sun.COM 
53311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
53411337SWilliam.Krier@Sun.COM }
53511337SWilliam.Krier@Sun.COM 
53611337SWilliam.Krier@Sun.COM /*
53711447Samw@Sun.COM  * QueryInfoDomain2: Identical to QueryDomainInfo.
53811447Samw@Sun.COM  */
53911447Samw@Sun.COM static int
54011447Samw@Sun.COM samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
54111447Samw@Sun.COM {
54211447Samw@Sun.COM 	return (samr_s_QueryDomainInfo(arg, mxa));
54311447Samw@Sun.COM }
54411447Samw@Sun.COM 
54511447Samw@Sun.COM /*
54611337SWilliam.Krier@Sun.COM  * Looks up the given name in the specified domain which could
54711337SWilliam.Krier@Sun.COM  * be either the built-in or local domain.
54811337SWilliam.Krier@Sun.COM  *
54911337SWilliam.Krier@Sun.COM  * CAVEAT: this function should be able to handle a list of
55011337SWilliam.Krier@Sun.COM  * names but currently it can only handle one name at a time.
55111337SWilliam.Krier@Sun.COM  */
55211337SWilliam.Krier@Sun.COM static int
55311337SWilliam.Krier@Sun.COM samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
55411337SWilliam.Krier@Sun.COM {
55511337SWilliam.Krier@Sun.COM 	struct samr_LookupNames *param = arg;
55611337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
55711337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
55811337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
55911337SWilliam.Krier@Sun.COM 	smb_account_t account;
56011337SWilliam.Krier@Sun.COM 	smb_wka_t *wka;
56111337SWilliam.Krier@Sun.COM 	uint32_t status = NT_STATUS_SUCCESS;
56211337SWilliam.Krier@Sun.COM 
56311337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
56411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
56511337SWilliam.Krier@Sun.COM 
56611337SWilliam.Krier@Sun.COM 	if (param->n_entry != 1)
56711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
56811337SWilliam.Krier@Sun.COM 
56911337SWilliam.Krier@Sun.COM 	if (param->name.str == NULL) {
57011337SWilliam.Krier@Sun.COM 		/*
57111337SWilliam.Krier@Sun.COM 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
57211337SWilliam.Krier@Sun.COM 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
57311337SWilliam.Krier@Sun.COM 		 */
57411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NONE_MAPPED;
57511337SWilliam.Krier@Sun.COM 	}
57611337SWilliam.Krier@Sun.COM 
57711337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
57811337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
57911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(status);
58011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
58111337SWilliam.Krier@Sun.COM 	}
58211337SWilliam.Krier@Sun.COM 
58311337SWilliam.Krier@Sun.COM 	param->rids.rid = NDR_NEW(mxa, DWORD);
58411337SWilliam.Krier@Sun.COM 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
58511337SWilliam.Krier@Sun.COM 
58611337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
58711337SWilliam.Krier@Sun.COM 
58811337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
58911337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
59011447Samw@Sun.COM 		wka = smb_wka_lookup_builtin((char *)param->name.str);
59111337SWilliam.Krier@Sun.COM 		if (wka != NULL) {
59211337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
59311337SWilliam.Krier@Sun.COM 			(void) smb_sid_getrid(wka->wka_binsid,
59411337SWilliam.Krier@Sun.COM 			    &param->rids.rid[0]);
59511337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
59611337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = wka->wka_type;
59711337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
59811337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
59911337SWilliam.Krier@Sun.COM 		}
60011337SWilliam.Krier@Sun.COM 		break;
60111337SWilliam.Krier@Sun.COM 
60211337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
60311337SWilliam.Krier@Sun.COM 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
60411337SWilliam.Krier@Sun.COM 		    SidTypeUnknown, &account);
60511337SWilliam.Krier@Sun.COM 		if (status == NT_STATUS_SUCCESS) {
60611337SWilliam.Krier@Sun.COM 			param->rids.n_entry = 1;
60711337SWilliam.Krier@Sun.COM 			param->rids.rid[0] = account.a_rid;
60811337SWilliam.Krier@Sun.COM 			param->rid_types.n_entry = 1;
60911337SWilliam.Krier@Sun.COM 			param->rid_types.rid_type[0] = account.a_type;
61011337SWilliam.Krier@Sun.COM 			param->status = NT_STATUS_SUCCESS;
61111337SWilliam.Krier@Sun.COM 			smb_account_free(&account);
61211337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
61311337SWilliam.Krier@Sun.COM 		}
61411337SWilliam.Krier@Sun.COM 		break;
61511337SWilliam.Krier@Sun.COM 
61611337SWilliam.Krier@Sun.COM 	default:
61711337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_LookupNames));
61811337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
61911337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
62011337SWilliam.Krier@Sun.COM 	}
62111337SWilliam.Krier@Sun.COM 
62211337SWilliam.Krier@Sun.COM 	param->rids.n_entry = 0;
62311337SWilliam.Krier@Sun.COM 	param->rid_types.n_entry = 0;
62411337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
62511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
62611337SWilliam.Krier@Sun.COM }
62711337SWilliam.Krier@Sun.COM 
62811337SWilliam.Krier@Sun.COM /*
62911337SWilliam.Krier@Sun.COM  * samr_s_OpenUser
63011337SWilliam.Krier@Sun.COM  *
63111337SWilliam.Krier@Sun.COM  * This is a request to open a user within a specified domain in the
63211337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
63311337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The user is
63411337SWilliam.Krier@Sun.COM  * specified by the rid in the request.
63511337SWilliam.Krier@Sun.COM  */
63611337SWilliam.Krier@Sun.COM static int
63711337SWilliam.Krier@Sun.COM samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
63811337SWilliam.Krier@Sun.COM {
63911337SWilliam.Krier@Sun.COM 	struct samr_OpenUser *param = arg;
64011337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
64111337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
64211337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
64311337SWilliam.Krier@Sun.COM 
64411337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
64511337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
64611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
64711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
64811337SWilliam.Krier@Sun.COM 	}
64911337SWilliam.Krier@Sun.COM 
65011337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
65111337SWilliam.Krier@Sun.COM 
65211337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
65311337SWilliam.Krier@Sun.COM 	if (id == NULL) {
65411337SWilliam.Krier@Sun.COM 		bzero(&param->user_handle, sizeof (samr_handle_t));
65511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
65611337SWilliam.Krier@Sun.COM 	} else {
65711337SWilliam.Krier@Sun.COM 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
65811337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
65911337SWilliam.Krier@Sun.COM 	}
66011337SWilliam.Krier@Sun.COM 
66111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
66211337SWilliam.Krier@Sun.COM }
66311337SWilliam.Krier@Sun.COM 
66411337SWilliam.Krier@Sun.COM /*
66511337SWilliam.Krier@Sun.COM  * samr_s_DeleteUser
66611337SWilliam.Krier@Sun.COM  *
66711337SWilliam.Krier@Sun.COM  * Request to delete a user within a specified domain in the local
66811337SWilliam.Krier@Sun.COM  * SAM database.  The caller should supply a valid user handle.
66911337SWilliam.Krier@Sun.COM  */
67011337SWilliam.Krier@Sun.COM /*ARGSUSED*/
67111337SWilliam.Krier@Sun.COM static int
67211337SWilliam.Krier@Sun.COM samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
67311337SWilliam.Krier@Sun.COM {
67411337SWilliam.Krier@Sun.COM 	struct samr_DeleteUser *param = arg;
67511337SWilliam.Krier@Sun.COM 
67611337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_DeleteUser));
67711337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
67811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
67911337SWilliam.Krier@Sun.COM }
68011337SWilliam.Krier@Sun.COM 
68111337SWilliam.Krier@Sun.COM /*
68211337SWilliam.Krier@Sun.COM  * samr_s_QueryUserInfo
68311337SWilliam.Krier@Sun.COM  *
68411337SWilliam.Krier@Sun.COM  * Returns:
68511337SWilliam.Krier@Sun.COM  * NT_STATUS_SUCCESS
68611337SWilliam.Krier@Sun.COM  * NT_STATUS_ACCESS_DENIED
68711337SWilliam.Krier@Sun.COM  * NT_STATUS_INVALID_INFO_CLASS
68811337SWilliam.Krier@Sun.COM  */
68911337SWilliam.Krier@Sun.COM /*ARGSUSED*/
69011337SWilliam.Krier@Sun.COM static int
69111337SWilliam.Krier@Sun.COM samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
69211337SWilliam.Krier@Sun.COM {
69311337SWilliam.Krier@Sun.COM 	static uint16_t			owf_buf[8];
69411337SWilliam.Krier@Sun.COM 	static uint8_t			hour_buf[SAMR_SET_USER_HOURS_SZ];
69511337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo	*param = arg;
69611337SWilliam.Krier@Sun.COM 	struct samr_QueryUserInfo21	*all_info;
69711337SWilliam.Krier@Sun.COM 	ndr_hdid_t			*id;
69811337SWilliam.Krier@Sun.COM 	ndr_handle_t			*hd;
69911337SWilliam.Krier@Sun.COM 	samr_keydata_t			*data;
70011337SWilliam.Krier@Sun.COM 	smb_domain_t			di;
70111337SWilliam.Krier@Sun.COM 	smb_account_t			account;
70211337SWilliam.Krier@Sun.COM 	smb_sid_t			*sid;
70311337SWilliam.Krier@Sun.COM 	uint32_t			status;
70411337SWilliam.Krier@Sun.COM 
70511337SWilliam.Krier@Sun.COM 	id = (ndr_hdid_t *)&param->user_handle;
70611337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
70711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
70811337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
70911337SWilliam.Krier@Sun.COM 	}
71011337SWilliam.Krier@Sun.COM 
71111337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
71211337SWilliam.Krier@Sun.COM 
71311337SWilliam.Krier@Sun.COM 	if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
71411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
71511337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
71611337SWilliam.Krier@Sun.COM 	}
71711337SWilliam.Krier@Sun.COM 
71811337SWilliam.Krier@Sun.COM 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
71911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
72011337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
72111337SWilliam.Krier@Sun.COM 	}
72211337SWilliam.Krier@Sun.COM 
72311337SWilliam.Krier@Sun.COM 	if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
72411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
72511337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
72611337SWilliam.Krier@Sun.COM 	}
72711337SWilliam.Krier@Sun.COM 
72811337SWilliam.Krier@Sun.COM 	if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
72911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
73011337SWilliam.Krier@Sun.COM 		goto QueryUserInfoError;
73111337SWilliam.Krier@Sun.COM 	}
73211337SWilliam.Krier@Sun.COM 
73311337SWilliam.Krier@Sun.COM 	all_info = &param->ru.info21;
73411337SWilliam.Krier@Sun.COM 	bzero(all_info, sizeof (struct samr_QueryUserInfo21));
73511337SWilliam.Krier@Sun.COM 
73611337SWilliam.Krier@Sun.COM 	all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
73711337SWilliam.Krier@Sun.COM 
73811337SWilliam.Krier@Sun.COM 	(void) NDR_MSTRING(mxa, account.a_name,
73911337SWilliam.Krier@Sun.COM 	    (ndr_mstring_t *)&all_info->UserName);
74011337SWilliam.Krier@Sun.COM 	all_info->UserId = data->kd_rid;
74111337SWilliam.Krier@Sun.COM 
74211337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.length = 16;
74311337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.maxlen = 16;
74411337SWilliam.Krier@Sun.COM 	all_info->LmOwfPassword.buf = owf_buf;
74511337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.length = 16;
74611337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.maxlen = 16;
74711337SWilliam.Krier@Sun.COM 	all_info->NtOwfPassword.buf = owf_buf;
74811337SWilliam.Krier@Sun.COM 	all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
74911337SWilliam.Krier@Sun.COM 	all_info->LogonHours.hours = hour_buf;
75011337SWilliam.Krier@Sun.COM 
75111337SWilliam.Krier@Sun.COM 	param->address = 1;
75211337SWilliam.Krier@Sun.COM 	param->switch_index = SAMR_QUERY_USER_ALL_INFO;
75311337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
754*11963SAfshin.Ardakani@Sun.COM 	smb_account_free(&account);
755*11963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sid);
75611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
75711337SWilliam.Krier@Sun.COM 
75811337SWilliam.Krier@Sun.COM QueryUserInfoError:
759*11963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sid);
76011337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserInfo));
76111337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
76211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
76311337SWilliam.Krier@Sun.COM }
76411337SWilliam.Krier@Sun.COM 
76511337SWilliam.Krier@Sun.COM /*
76611337SWilliam.Krier@Sun.COM  * samr_s_QueryUserGroups
76711337SWilliam.Krier@Sun.COM  *
76811337SWilliam.Krier@Sun.COM  * Request the list of groups of which a user is a member.
76911337SWilliam.Krier@Sun.COM  * The user is identified from the handle, which contains an
77011337SWilliam.Krier@Sun.COM  * rid in the discriminator field. Note that this is a local user.
77111337SWilliam.Krier@Sun.COM  */
77211337SWilliam.Krier@Sun.COM static int
77311337SWilliam.Krier@Sun.COM samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
77411337SWilliam.Krier@Sun.COM {
77511337SWilliam.Krier@Sun.COM 	struct samr_QueryUserGroups *param = arg;
77611337SWilliam.Krier@Sun.COM 	struct samr_UserGroupInfo *info;
77711337SWilliam.Krier@Sun.COM 	struct samr_UserGroups *group;
77811337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
77911337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
78011337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
78111337SWilliam.Krier@Sun.COM 	smb_sid_t *user_sid = NULL;
78211337SWilliam.Krier@Sun.COM 	smb_group_t grp;
78311337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
78411337SWilliam.Krier@Sun.COM 	smb_domain_t di;
78511337SWilliam.Krier@Sun.COM 	uint32_t status;
78611337SWilliam.Krier@Sun.COM 	int size;
78711337SWilliam.Krier@Sun.COM 	int ngrp_max;
78811337SWilliam.Krier@Sun.COM 
78911337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
79011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
79111337SWilliam.Krier@Sun.COM 		goto query_error;
79211337SWilliam.Krier@Sun.COM 	}
79311337SWilliam.Krier@Sun.COM 
79411337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
79511337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
79611337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
79711337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
79811337SWilliam.Krier@Sun.COM 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
79911337SWilliam.Krier@Sun.COM 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
80011337SWilliam.Krier@Sun.COM 			goto query_error;
80111337SWilliam.Krier@Sun.COM 		}
80211337SWilliam.Krier@Sun.COM 		break;
80311337SWilliam.Krier@Sun.COM 	default:
80411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
80511337SWilliam.Krier@Sun.COM 		goto query_error;
80611337SWilliam.Krier@Sun.COM 	}
80711337SWilliam.Krier@Sun.COM 
80811337SWilliam.Krier@Sun.COM 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
80911337SWilliam.Krier@Sun.COM 	if (user_sid == 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 
81411337SWilliam.Krier@Sun.COM 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
81511337SWilliam.Krier@Sun.COM 	if (info == NULL) {
81611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
81711337SWilliam.Krier@Sun.COM 		goto query_error;
81811337SWilliam.Krier@Sun.COM 	}
81911337SWilliam.Krier@Sun.COM 	bzero(info, sizeof (struct samr_UserGroupInfo));
82011337SWilliam.Krier@Sun.COM 
82111337SWilliam.Krier@Sun.COM 	size = 32 * 1024;
82211337SWilliam.Krier@Sun.COM 	info->groups = NDR_MALLOC(mxa, size);
82311337SWilliam.Krier@Sun.COM 	if (info->groups == NULL) {
82411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
82511337SWilliam.Krier@Sun.COM 		goto query_error;
82611337SWilliam.Krier@Sun.COM 	}
82711337SWilliam.Krier@Sun.COM 	ngrp_max = size / sizeof (struct samr_UserGroups);
82811337SWilliam.Krier@Sun.COM 
82911337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
83011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INTERNAL_ERROR;
83111337SWilliam.Krier@Sun.COM 		goto query_error;
83211337SWilliam.Krier@Sun.COM 	}
83311337SWilliam.Krier@Sun.COM 
83411337SWilliam.Krier@Sun.COM 	info->n_entry = 0;
83511337SWilliam.Krier@Sun.COM 	group = info->groups;
83611337SWilliam.Krier@Sun.COM 	while ((info->n_entry < ngrp_max) &&
83711337SWilliam.Krier@Sun.COM 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
83811337SWilliam.Krier@Sun.COM 		if (smb_lgrp_is_member(&grp, user_sid)) {
83911337SWilliam.Krier@Sun.COM 			group->rid = grp.sg_rid;
84011337SWilliam.Krier@Sun.COM 			group->attr = grp.sg_attr;
84111337SWilliam.Krier@Sun.COM 			group++;
84211337SWilliam.Krier@Sun.COM 			info->n_entry++;
84311337SWilliam.Krier@Sun.COM 		}
84411337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
84511337SWilliam.Krier@Sun.COM 	}
84611337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
84711337SWilliam.Krier@Sun.COM 
84811337SWilliam.Krier@Sun.COM 	free(user_sid);
84911337SWilliam.Krier@Sun.COM 	param->info = info;
85011337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
85111337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
85211337SWilliam.Krier@Sun.COM 
85311337SWilliam.Krier@Sun.COM query_error:
85411337SWilliam.Krier@Sun.COM 	free(user_sid);
85511337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryUserGroups));
85611337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
85711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
85811337SWilliam.Krier@Sun.COM }
85911337SWilliam.Krier@Sun.COM 
86011337SWilliam.Krier@Sun.COM /*
86111337SWilliam.Krier@Sun.COM  * samr_s_OpenGroup
86211337SWilliam.Krier@Sun.COM  *
86311337SWilliam.Krier@Sun.COM  * This is a request to open a group within the specified domain in the
86411337SWilliam.Krier@Sun.COM  * local SAM database. The caller must supply a valid domain handle,
86511337SWilliam.Krier@Sun.COM  * obtained via a successful domain open request. The group is
86611337SWilliam.Krier@Sun.COM  * specified by the rid in the request. If this is a local RID it
86711337SWilliam.Krier@Sun.COM  * should already be encoded with type information.
86811337SWilliam.Krier@Sun.COM  *
86911337SWilliam.Krier@Sun.COM  * We return a handle to be used to access information about this group.
87011337SWilliam.Krier@Sun.COM  */
87111337SWilliam.Krier@Sun.COM static int
87211337SWilliam.Krier@Sun.COM samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
87311337SWilliam.Krier@Sun.COM {
87411337SWilliam.Krier@Sun.COM 	struct samr_OpenGroup *param = arg;
87511337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
87611337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
87711337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
87811337SWilliam.Krier@Sun.COM 
87911337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
88011337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
88111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
88211337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
88311337SWilliam.Krier@Sun.COM 	}
88411337SWilliam.Krier@Sun.COM 
88511337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
88611337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
88711337SWilliam.Krier@Sun.COM 
88811337SWilliam.Krier@Sun.COM 	if (id) {
88911337SWilliam.Krier@Sun.COM 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
89011337SWilliam.Krier@Sun.COM 		param->status = 0;
89111337SWilliam.Krier@Sun.COM 	} else {
89211337SWilliam.Krier@Sun.COM 		bzero(&param->group_handle, sizeof (samr_handle_t));
89311337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
89411337SWilliam.Krier@Sun.COM 	}
89511337SWilliam.Krier@Sun.COM 
89611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
89711337SWilliam.Krier@Sun.COM }
89811337SWilliam.Krier@Sun.COM 
89911337SWilliam.Krier@Sun.COM /*
90011337SWilliam.Krier@Sun.COM  * samr_s_Connect
90111337SWilliam.Krier@Sun.COM  *
90211337SWilliam.Krier@Sun.COM  * This is a request to connect to the local SAM database.
90311337SWilliam.Krier@Sun.COM  * We don't support any form of update request and our database doesn't
90411337SWilliam.Krier@Sun.COM  * contain any private information, so there is little point in doing
90511337SWilliam.Krier@Sun.COM  * any access access checking here.
90611337SWilliam.Krier@Sun.COM  *
90711337SWilliam.Krier@Sun.COM  * Return a handle for use with subsequent SAM requests.
90811337SWilliam.Krier@Sun.COM  */
90911337SWilliam.Krier@Sun.COM static int
91011337SWilliam.Krier@Sun.COM samr_s_Connect(void *arg, ndr_xa_t *mxa)
91111337SWilliam.Krier@Sun.COM {
91211337SWilliam.Krier@Sun.COM 	struct samr_Connect *param = arg;
91311337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id;
91411337SWilliam.Krier@Sun.COM 
91511337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
91611337SWilliam.Krier@Sun.COM 	if (id) {
91711337SWilliam.Krier@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
91811337SWilliam.Krier@Sun.COM 		param->status = 0;
91911337SWilliam.Krier@Sun.COM 	} else {
92011337SWilliam.Krier@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
92111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
92211337SWilliam.Krier@Sun.COM 	}
92311337SWilliam.Krier@Sun.COM 
92411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
92511337SWilliam.Krier@Sun.COM }
92611337SWilliam.Krier@Sun.COM 
92711337SWilliam.Krier@Sun.COM /*
92811337SWilliam.Krier@Sun.COM  * samr_s_GetUserPwInfo
92911337SWilliam.Krier@Sun.COM  *
93011447Samw@Sun.COM  * Request for a user's password policy information.
93111337SWilliam.Krier@Sun.COM  */
93211337SWilliam.Krier@Sun.COM /*ARGSUSED*/
93311337SWilliam.Krier@Sun.COM static int
93411337SWilliam.Krier@Sun.COM samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
93511337SWilliam.Krier@Sun.COM {
93611447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
93711447Samw@Sun.COM 	struct samr_GetUserPwInfo	*param = arg;
93811337SWilliam.Krier@Sun.COM 
93911447Samw@Sun.COM 	param->pwinfo = &pwinfo;
94011447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
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_CreateUser
94611337SWilliam.Krier@Sun.COM  */
94711337SWilliam.Krier@Sun.COM /*ARGSUSED*/
94811337SWilliam.Krier@Sun.COM static int
94911337SWilliam.Krier@Sun.COM samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
95011337SWilliam.Krier@Sun.COM {
95111337SWilliam.Krier@Sun.COM 	struct samr_CreateUser *param = arg;
95211337SWilliam.Krier@Sun.COM 
95311337SWilliam.Krier@Sun.COM 	bzero(&param->user_handle, sizeof (samr_handle_t));
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_ChangeUserPasswd
96011337SWilliam.Krier@Sun.COM  */
96111337SWilliam.Krier@Sun.COM /*ARGSUSED*/
96211337SWilliam.Krier@Sun.COM static int
96311337SWilliam.Krier@Sun.COM samr_s_ChangeUserPasswd(void *arg, ndr_xa_t *mxa)
96411337SWilliam.Krier@Sun.COM {
96511337SWilliam.Krier@Sun.COM 	struct samr_ChangeUserPasswd *param = arg;
96611337SWilliam.Krier@Sun.COM 
96711337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_ChangeUserPasswd));
96811337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
96911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
97011337SWilliam.Krier@Sun.COM }
97111337SWilliam.Krier@Sun.COM 
97211337SWilliam.Krier@Sun.COM /*
97311337SWilliam.Krier@Sun.COM  * samr_s_GetDomainPwInfo
97411447Samw@Sun.COM  *
97511447Samw@Sun.COM  * Request for the domain password policy information.
97611337SWilliam.Krier@Sun.COM  */
97711337SWilliam.Krier@Sun.COM /*ARGSUSED*/
97811337SWilliam.Krier@Sun.COM static int
97911337SWilliam.Krier@Sun.COM samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
98011337SWilliam.Krier@Sun.COM {
98111447Samw@Sun.COM 	static samr_password_info_t	pwinfo;
98211447Samw@Sun.COM 	struct samr_GetDomainPwInfo	*param = arg;
98311337SWilliam.Krier@Sun.COM 
98411447Samw@Sun.COM 	param->pwinfo = &pwinfo;
98511447Samw@Sun.COM 	param->status = NT_STATUS_SUCCESS;
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_SetUserInfo
99111337SWilliam.Krier@Sun.COM  */
99211337SWilliam.Krier@Sun.COM /*ARGSUSED*/
99311337SWilliam.Krier@Sun.COM static int
99411337SWilliam.Krier@Sun.COM samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
99511337SWilliam.Krier@Sun.COM {
99611337SWilliam.Krier@Sun.COM 	struct samr_SetUserInfo *param = arg;
99711337SWilliam.Krier@Sun.COM 
99811337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_SetUserInfo));
99911337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
100011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
100111337SWilliam.Krier@Sun.COM }
100211337SWilliam.Krier@Sun.COM 
100311337SWilliam.Krier@Sun.COM /*
100411337SWilliam.Krier@Sun.COM  * samr_s_QueryDispInfo
100511337SWilliam.Krier@Sun.COM  *
100611337SWilliam.Krier@Sun.COM  * This function currently return local users' information only.
100711337SWilliam.Krier@Sun.COM  * This RPC is called repeatedly until all the users info are
100811337SWilliam.Krier@Sun.COM  * retrieved.
100911337SWilliam.Krier@Sun.COM  *
101011337SWilliam.Krier@Sun.COM  * The total count and the returned count are returned as total size
101111337SWilliam.Krier@Sun.COM  * and returned size.  The client doesn't seem to care.
101211337SWilliam.Krier@Sun.COM  */
101311337SWilliam.Krier@Sun.COM static int
101411337SWilliam.Krier@Sun.COM samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
101511337SWilliam.Krier@Sun.COM {
101611337SWilliam.Krier@Sun.COM 	struct samr_QueryDispInfo *param = arg;
101711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
101811337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
101911337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
102011337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
102111337SWilliam.Krier@Sun.COM 	struct user_acct_info *user;
102211337SWilliam.Krier@Sun.COM 	smb_pwditer_t pwi;
102311337SWilliam.Krier@Sun.COM 	smb_luser_t *uinfo;
102411337SWilliam.Krier@Sun.COM 	int num_users;
102511337SWilliam.Krier@Sun.COM 	int start_idx;
102611337SWilliam.Krier@Sun.COM 	int max_retcnt, retcnt;
102711337SWilliam.Krier@Sun.COM 	int skip;
102811337SWilliam.Krier@Sun.COM 
102911337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
103011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
103111337SWilliam.Krier@Sun.COM 		goto error;
103211337SWilliam.Krier@Sun.COM 	}
103311337SWilliam.Krier@Sun.COM 
103411337SWilliam.Krier@Sun.COM 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
103511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
103611337SWilliam.Krier@Sun.COM 		goto error;
103711337SWilliam.Krier@Sun.COM 	}
103811337SWilliam.Krier@Sun.COM 
103911337SWilliam.Krier@Sun.COM 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
104011337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NOT_IMPLEMENTED;
104111337SWilliam.Krier@Sun.COM 		goto error;
104211337SWilliam.Krier@Sun.COM 	}
104311337SWilliam.Krier@Sun.COM 
104411337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
104511337SWilliam.Krier@Sun.COM 
104611337SWilliam.Krier@Sun.COM 	switch (data->kd_type) {
104711337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_BUILTIN:
104811337SWilliam.Krier@Sun.COM 		goto no_info;
104911337SWilliam.Krier@Sun.COM 
105011337SWilliam.Krier@Sun.COM 	case SMB_DOMAIN_LOCAL:
105111337SWilliam.Krier@Sun.COM 		num_users = smb_sam_usr_cnt();
105211337SWilliam.Krier@Sun.COM 		start_idx = param->start_idx;
105311337SWilliam.Krier@Sun.COM 		if ((num_users == 0) || (start_idx >= num_users))
105411337SWilliam.Krier@Sun.COM 			goto no_info;
105511337SWilliam.Krier@Sun.COM 
105611337SWilliam.Krier@Sun.COM 		max_retcnt = num_users - start_idx;
105711337SWilliam.Krier@Sun.COM 		if (max_retcnt > param->max_entries)
105811337SWilliam.Krier@Sun.COM 			max_retcnt = param->max_entries;
105911337SWilliam.Krier@Sun.COM 		param->users.acct = NDR_MALLOC(mxa,
106011337SWilliam.Krier@Sun.COM 		    max_retcnt * sizeof (struct user_acct_info));
106111337SWilliam.Krier@Sun.COM 		user = param->users.acct;
106211337SWilliam.Krier@Sun.COM 		if (user == NULL) {
106311337SWilliam.Krier@Sun.COM 			status = NT_STATUS_NO_MEMORY;
106411337SWilliam.Krier@Sun.COM 			goto error;
106511337SWilliam.Krier@Sun.COM 		}
106611337SWilliam.Krier@Sun.COM 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
106711337SWilliam.Krier@Sun.COM 
106811337SWilliam.Krier@Sun.COM 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
106911337SWilliam.Krier@Sun.COM 			goto no_info;
107011337SWilliam.Krier@Sun.COM 
107111337SWilliam.Krier@Sun.COM 		skip = retcnt = 0;
107211337SWilliam.Krier@Sun.COM 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
107311337SWilliam.Krier@Sun.COM 			if (skip++ < start_idx)
107411337SWilliam.Krier@Sun.COM 				continue;
107511337SWilliam.Krier@Sun.COM 
107611337SWilliam.Krier@Sun.COM 			if (retcnt++ >= max_retcnt)
107711337SWilliam.Krier@Sun.COM 				break;
107811337SWilliam.Krier@Sun.COM 
107911337SWilliam.Krier@Sun.COM 			assert(uinfo->su_name != NULL);
108011337SWilliam.Krier@Sun.COM 
108111337SWilliam.Krier@Sun.COM 			user->index = start_idx + retcnt;
108211337SWilliam.Krier@Sun.COM 			user->rid = uinfo->su_rid;
108311337SWilliam.Krier@Sun.COM 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
108411337SWilliam.Krier@Sun.COM 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
108511337SWilliam.Krier@Sun.COM 				user->ctrl |= ACF_DISABLED;
108611337SWilliam.Krier@Sun.COM 			if (NDR_MSTRING(mxa, uinfo->su_name,
108711337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->name) == -1) {
108811337SWilliam.Krier@Sun.COM 				smb_pwd_iterclose(&pwi);
108911337SWilliam.Krier@Sun.COM 				status = NT_STATUS_NO_MEMORY;
109011337SWilliam.Krier@Sun.COM 				goto error;
109111337SWilliam.Krier@Sun.COM 			}
109211337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
109311337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->fullname);
109411337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
109511337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&user->desc);
109611337SWilliam.Krier@Sun.COM 			user++;
109711337SWilliam.Krier@Sun.COM 		}
109811337SWilliam.Krier@Sun.COM 		smb_pwd_iterclose(&pwi);
109911337SWilliam.Krier@Sun.COM 
110011337SWilliam.Krier@Sun.COM 		if (retcnt >= max_retcnt) {
110111337SWilliam.Krier@Sun.COM 			retcnt = max_retcnt;
110211337SWilliam.Krier@Sun.COM 			param->status = status;
110311337SWilliam.Krier@Sun.COM 		} else {
110411337SWilliam.Krier@Sun.COM 			param->status = ERROR_MORE_ENTRIES;
110511337SWilliam.Krier@Sun.COM 		}
110611337SWilliam.Krier@Sun.COM 
110711337SWilliam.Krier@Sun.COM 		param->users.total_size = num_users;
110811337SWilliam.Krier@Sun.COM 		param->users.returned_size = retcnt;
110911337SWilliam.Krier@Sun.COM 		param->users.switch_value = param->level;
111011337SWilliam.Krier@Sun.COM 		param->users.count = retcnt;
111111337SWilliam.Krier@Sun.COM 
111211337SWilliam.Krier@Sun.COM 		break;
111311337SWilliam.Krier@Sun.COM 
111411337SWilliam.Krier@Sun.COM 	default:
111511337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
111611337SWilliam.Krier@Sun.COM 		goto error;
111711337SWilliam.Krier@Sun.COM 	}
111811337SWilliam.Krier@Sun.COM 
111911337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
112011337SWilliam.Krier@Sun.COM 
112111337SWilliam.Krier@Sun.COM no_info:
112211337SWilliam.Krier@Sun.COM 	param->users.total_size = 0;
112311337SWilliam.Krier@Sun.COM 	param->users.returned_size = 0;
112411337SWilliam.Krier@Sun.COM 	param->users.switch_value = param->level;
112511337SWilliam.Krier@Sun.COM 	param->users.count = 0;
112611337SWilliam.Krier@Sun.COM 	param->users.acct = NULL;
112711337SWilliam.Krier@Sun.COM 	param->status = status;
112811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
112911337SWilliam.Krier@Sun.COM 
113011337SWilliam.Krier@Sun.COM error:
113111337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_QueryDispInfo));
113211337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
113311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
113411337SWilliam.Krier@Sun.COM }
113511337SWilliam.Krier@Sun.COM 
113611337SWilliam.Krier@Sun.COM /*
113711337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainGroups
113811337SWilliam.Krier@Sun.COM  *
113911337SWilliam.Krier@Sun.COM  *
114011337SWilliam.Krier@Sun.COM  * This function is supposed to return local group information.
114111337SWilliam.Krier@Sun.COM  * As we don't support local users, this function dosen't send
114211337SWilliam.Krier@Sun.COM  * back any information.
114311337SWilliam.Krier@Sun.COM  *
114411337SWilliam.Krier@Sun.COM  * Added template that returns information for a domain group as None.
114511337SWilliam.Krier@Sun.COM  * All information is hard-coded from packet captures.
114611337SWilliam.Krier@Sun.COM  */
114711337SWilliam.Krier@Sun.COM static int
114811337SWilliam.Krier@Sun.COM samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
114911337SWilliam.Krier@Sun.COM {
115011337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainGroups *param = arg;
115111337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
115211337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
115311337SWilliam.Krier@Sun.COM 
115411337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
115511337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
115611337SWilliam.Krier@Sun.COM 
115711337SWilliam.Krier@Sun.COM 	param->total_size = 0;
115811337SWilliam.Krier@Sun.COM 	param->returned_size = 0;
115911337SWilliam.Krier@Sun.COM 	param->switch_value = 3;
116011337SWilliam.Krier@Sun.COM 	param->count = 0;
116111337SWilliam.Krier@Sun.COM 	param->groups = 0;
116211337SWilliam.Krier@Sun.COM 	param->status = status;
116311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
116411337SWilliam.Krier@Sun.COM 
116511337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_GROUPS
116611337SWilliam.Krier@Sun.COM 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
116711337SWilliam.Krier@Sun.COM 		param->total_size = 0;
116811337SWilliam.Krier@Sun.COM 		param->returned_size = 0;
116911337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
117011337SWilliam.Krier@Sun.COM 		param->count = 0;
117111337SWilliam.Krier@Sun.COM 		param->groups = 0;
117211337SWilliam.Krier@Sun.COM 	} else {
117311337SWilliam.Krier@Sun.COM 		param->total_size = 64;
117411337SWilliam.Krier@Sun.COM 		param->returned_size = 64;
117511337SWilliam.Krier@Sun.COM 		param->switch_value = 3;
117611337SWilliam.Krier@Sun.COM 		param->count = 1;
117711337SWilliam.Krier@Sun.COM 		param->groups = (struct group_disp_info *)NDR_MALLOC(
117811337SWilliam.Krier@Sun.COM 		    mxa, sizeof (struct group_disp_info));
117911337SWilliam.Krier@Sun.COM 
118011337SWilliam.Krier@Sun.COM 		param->groups->count = 1;
118111337SWilliam.Krier@Sun.COM 		param->groups->acct[0].index = 1;
118211337SWilliam.Krier@Sun.COM 		param->groups->acct[0].rid = 513;
118311337SWilliam.Krier@Sun.COM 		param->groups->acct[0].ctrl = 0x7;
118411337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "None",
118511337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].name);
118611337SWilliam.Krier@Sun.COM 
118711337SWilliam.Krier@Sun.COM 		(void) NDR_MSTRING(mxa, "Ordinary users",
118811337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
118911337SWilliam.Krier@Sun.COM 	}
119011337SWilliam.Krier@Sun.COM 
119111337SWilliam.Krier@Sun.COM 	param->status = NT_STATUS_SUCCESS;
119211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
119311337SWilliam.Krier@Sun.COM #endif
119411337SWilliam.Krier@Sun.COM }
119511337SWilliam.Krier@Sun.COM 
119611337SWilliam.Krier@Sun.COM /*
119711337SWilliam.Krier@Sun.COM  * samr_s_OpenAlias
119811337SWilliam.Krier@Sun.COM  *
119911337SWilliam.Krier@Sun.COM  * Lookup for requested alias, if it exists return a handle
120011337SWilliam.Krier@Sun.COM  * for that alias. The alias domain sid should match with
120111337SWilliam.Krier@Sun.COM  * the passed domain handle.
120211337SWilliam.Krier@Sun.COM  */
120311337SWilliam.Krier@Sun.COM static int
120411337SWilliam.Krier@Sun.COM samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
120511337SWilliam.Krier@Sun.COM {
120611337SWilliam.Krier@Sun.COM 	struct samr_OpenAlias *param = arg;
120711447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
120811447Samw@Sun.COM 	ndr_handle_t	*hd;
120911447Samw@Sun.COM 	samr_keydata_t	*data;
1210*11963SAfshin.Ardakani@Sun.COM 	smb_domain_type_t gd_type;
121111447Samw@Sun.COM 	smb_sid_t	*sid;
121211447Samw@Sun.COM 	smb_wka_t	*wka;
121311447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
121411447Samw@Sun.COM 	uint32_t	rid;
121511447Samw@Sun.COM 	uint32_t	status;
121611447Samw@Sun.COM 	int		rc;
121711337SWilliam.Krier@Sun.COM 
121811337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
121911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
122011337SWilliam.Krier@Sun.COM 		goto open_alias_err;
122111337SWilliam.Krier@Sun.COM 	}
122211337SWilliam.Krier@Sun.COM 
122311337SWilliam.Krier@Sun.COM 	if (param->access_mask != SAMR_ALIAS_ACCESS_GET_INFO) {
122411337SWilliam.Krier@Sun.COM 		status = NT_STATUS_ACCESS_DENIED;
122511337SWilliam.Krier@Sun.COM 		goto open_alias_err;
122611337SWilliam.Krier@Sun.COM 	}
122711337SWilliam.Krier@Sun.COM 
122811337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1229*11963SAfshin.Ardakani@Sun.COM 	gd_type = (smb_domain_type_t)data->kd_type;
123011447Samw@Sun.COM 	rid = param->rid;
123111447Samw@Sun.COM 
123211447Samw@Sun.COM 	switch (gd_type) {
1233*11963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_BUILTIN:
123411447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
123511447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
123611447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
123711447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
123811447Samw@Sun.COM 			goto open_alias_err;
123911447Samw@Sun.COM 		}
124011447Samw@Sun.COM 
124111447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
124211447Samw@Sun.COM 		smb_sid_free(sid);
124311447Samw@Sun.COM 
124411447Samw@Sun.COM 		if (wka == NULL) {
124511447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
124611447Samw@Sun.COM 			goto open_alias_err;
124711447Samw@Sun.COM 		}
124811447Samw@Sun.COM 		break;
124911447Samw@Sun.COM 
1250*11963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_LOCAL:
125111447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
125211447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
125311447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
125411447Samw@Sun.COM 			goto open_alias_err;
125511447Samw@Sun.COM 		}
125611447Samw@Sun.COM 		break;
125711447Samw@Sun.COM 
125811447Samw@Sun.COM 	default:
125911337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
126011337SWilliam.Krier@Sun.COM 		goto open_alias_err;
126111337SWilliam.Krier@Sun.COM 	}
126211337SWilliam.Krier@Sun.COM 
126311337SWilliam.Krier@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
126411337SWilliam.Krier@Sun.COM 	if (id) {
126511337SWilliam.Krier@Sun.COM 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
126611337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
126711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
126811337SWilliam.Krier@Sun.COM 	}
126911337SWilliam.Krier@Sun.COM 
127011337SWilliam.Krier@Sun.COM 	status = NT_STATUS_NO_MEMORY;
127111337SWilliam.Krier@Sun.COM 
127211337SWilliam.Krier@Sun.COM open_alias_err:
127311337SWilliam.Krier@Sun.COM 	bzero(&param->alias_handle, sizeof (samr_handle_t));
127411337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
127511337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
127611337SWilliam.Krier@Sun.COM }
127711337SWilliam.Krier@Sun.COM 
127811337SWilliam.Krier@Sun.COM /*
127911337SWilliam.Krier@Sun.COM  * samr_s_CreateDomainAlias
128011337SWilliam.Krier@Sun.COM  *
128111337SWilliam.Krier@Sun.COM  * Creates a local group in the security database, which is the
128211337SWilliam.Krier@Sun.COM  * security accounts manager (SAM)
128311337SWilliam.Krier@Sun.COM  * For more information you can look at MSDN page for NetLocalGroupAdd.
128411337SWilliam.Krier@Sun.COM  * This RPC is used by CMC and right now it returns access denied.
128511337SWilliam.Krier@Sun.COM  * The peice of code that creates a local group doesn't get compiled.
128611337SWilliam.Krier@Sun.COM  */
128711337SWilliam.Krier@Sun.COM /*ARGSUSED*/
128811337SWilliam.Krier@Sun.COM static int
128911337SWilliam.Krier@Sun.COM samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
129011337SWilliam.Krier@Sun.COM {
129111337SWilliam.Krier@Sun.COM 	struct samr_CreateDomainAlias *param = arg;
129211337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
129311337SWilliam.Krier@Sun.COM 
129411337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) {
129511337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_CreateDomainAlias));
129611337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
129711337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
129811337SWilliam.Krier@Sun.COM 	}
129911337SWilliam.Krier@Sun.COM 
130011337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_CreateDomainAlias));
130111337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
130211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
130311337SWilliam.Krier@Sun.COM 
130411337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_ADD_ALIAS
130511337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
130611337SWilliam.Krier@Sun.COM 	nt_group_t *grp;
130711337SWilliam.Krier@Sun.COM 	char *alias_name;
130811337SWilliam.Krier@Sun.COM 
130911337SWilliam.Krier@Sun.COM 	alias_name = param->alias_name.str;
131011337SWilliam.Krier@Sun.COM 	if (alias_name == 0) {
131111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_PARAMETER;
131211337SWilliam.Krier@Sun.COM 		goto create_alias_err;
131311337SWilliam.Krier@Sun.COM 	}
131411337SWilliam.Krier@Sun.COM 
131511337SWilliam.Krier@Sun.COM 	/*
131611337SWilliam.Krier@Sun.COM 	 * Check access mask.  User should be member of
131711337SWilliam.Krier@Sun.COM 	 * Administrators or Account Operators local group.
131811337SWilliam.Krier@Sun.COM 	 */
131911337SWilliam.Krier@Sun.COM 	status = nt_group_add(alias_name, 0,
132011337SWilliam.Krier@Sun.COM 	    NT_GROUP_AF_ADD | NT_GROUP_AF_LOCAL);
132111337SWilliam.Krier@Sun.COM 
132211337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS)
132311337SWilliam.Krier@Sun.COM 		goto create_alias_err;
132411337SWilliam.Krier@Sun.COM 
132511337SWilliam.Krier@Sun.COM 	grp = nt_group_getinfo(alias_name, RWLOCK_READER);
132611337SWilliam.Krier@Sun.COM 	if (grp == NULL) {
132711337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INTERNAL_ERROR;
132811337SWilliam.Krier@Sun.COM 		goto create_alias_err;
132911337SWilliam.Krier@Sun.COM 	}
133011337SWilliam.Krier@Sun.COM 
133111337SWilliam.Krier@Sun.COM 	(void) smb_sid_getrid(grp->sid, &param->rid);
133211337SWilliam.Krier@Sun.COM 	nt_group_putinfo(grp);
133311337SWilliam.Krier@Sun.COM 	handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY,
133411337SWilliam.Krier@Sun.COM 	    param->rid);
133511337SWilliam.Krier@Sun.COM 	bcopy(handle, &param->alias_handle, sizeof (samr_handle_t));
133611337SWilliam.Krier@Sun.COM 
133711337SWilliam.Krier@Sun.COM 	param->status = 0;
133811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
133911337SWilliam.Krier@Sun.COM 
134011337SWilliam.Krier@Sun.COM create_alias_err:
134111337SWilliam.Krier@Sun.COM 	bzero(&param->alias_handle, sizeof (samr_handle_t));
134211337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
134311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
134411337SWilliam.Krier@Sun.COM #endif
134511337SWilliam.Krier@Sun.COM }
134611337SWilliam.Krier@Sun.COM 
134711337SWilliam.Krier@Sun.COM /*
134811337SWilliam.Krier@Sun.COM  * samr_s_SetAliasInfo
134911337SWilliam.Krier@Sun.COM  *
135011337SWilliam.Krier@Sun.COM  * Similar to NetLocalGroupSetInfo.
135111337SWilliam.Krier@Sun.COM  */
135211337SWilliam.Krier@Sun.COM static int
135311337SWilliam.Krier@Sun.COM samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
135411337SWilliam.Krier@Sun.COM {
135511337SWilliam.Krier@Sun.COM 	struct samr_SetAliasInfo *param = arg;
135611337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
135711337SWilliam.Krier@Sun.COM 	DWORD status = NT_STATUS_SUCCESS;
135811337SWilliam.Krier@Sun.COM 
135911337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
136011337SWilliam.Krier@Sun.COM 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
136111337SWilliam.Krier@Sun.COM 
136211337SWilliam.Krier@Sun.COM 	param->status = status;
136311337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
136411337SWilliam.Krier@Sun.COM }
136511337SWilliam.Krier@Sun.COM 
136611337SWilliam.Krier@Sun.COM /*
136711337SWilliam.Krier@Sun.COM  * samr_s_QueryAliasInfo
136811337SWilliam.Krier@Sun.COM  *
136911337SWilliam.Krier@Sun.COM  * Retrieves information about the specified local group account
137011337SWilliam.Krier@Sun.COM  * by given handle.
137111337SWilliam.Krier@Sun.COM  */
137211337SWilliam.Krier@Sun.COM static int
137311337SWilliam.Krier@Sun.COM samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
137411337SWilliam.Krier@Sun.COM {
137511337SWilliam.Krier@Sun.COM 	struct samr_QueryAliasInfo *param = arg;
137611447Samw@Sun.COM 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
137711447Samw@Sun.COM 	ndr_handle_t	*hd;
137811447Samw@Sun.COM 	samr_keydata_t	*data;
137911447Samw@Sun.COM 	smb_group_t	grp;
1380*11963SAfshin.Ardakani@Sun.COM 	smb_domain_type_t gd_type;
138111447Samw@Sun.COM 	smb_sid_t	*sid;
138211447Samw@Sun.COM 	smb_wka_t	*wka;
138311447Samw@Sun.COM 	char		sidstr[SMB_SID_STRSZ];
138411447Samw@Sun.COM 	char		*name;
138511447Samw@Sun.COM 	char		*desc;
138611447Samw@Sun.COM 	uint32_t	rid;
138711447Samw@Sun.COM 	uint32_t	status;
138811447Samw@Sun.COM 	int		rc;
138911337SWilliam.Krier@Sun.COM 
139011337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
139111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_HANDLE;
139211337SWilliam.Krier@Sun.COM 		goto query_alias_err;
139311337SWilliam.Krier@Sun.COM 	}
139411337SWilliam.Krier@Sun.COM 
139511337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
1396*11963SAfshin.Ardakani@Sun.COM 	gd_type = (smb_domain_type_t)data->kd_type;
139711447Samw@Sun.COM 	rid = data->kd_rid;
139811447Samw@Sun.COM 
139911447Samw@Sun.COM 	switch (gd_type) {
1400*11963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_BUILTIN:
140111447Samw@Sun.COM 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
140211447Samw@Sun.COM 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
140311447Samw@Sun.COM 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
140411447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
140511447Samw@Sun.COM 			goto query_alias_err;
140611447Samw@Sun.COM 		}
140711447Samw@Sun.COM 
140811447Samw@Sun.COM 		wka = smb_wka_lookup_sid(sid);
140911447Samw@Sun.COM 		smb_sid_free(sid);
141011447Samw@Sun.COM 
141111447Samw@Sun.COM 		if (wka == NULL) {
141211447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
141311447Samw@Sun.COM 			goto query_alias_err;
141411447Samw@Sun.COM 		}
141511447Samw@Sun.COM 
141611447Samw@Sun.COM 		name = wka->wka_name;
141711447Samw@Sun.COM 		desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
141811447Samw@Sun.COM 		break;
141911447Samw@Sun.COM 
1420*11963SAfshin.Ardakani@Sun.COM 	case SMB_DOMAIN_LOCAL:
142111447Samw@Sun.COM 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
142211447Samw@Sun.COM 		if (rc != SMB_LGRP_SUCCESS) {
142311447Samw@Sun.COM 			status = NT_STATUS_NO_SUCH_ALIAS;
142411447Samw@Sun.COM 			goto query_alias_err;
142511447Samw@Sun.COM 		}
142611447Samw@Sun.COM 		name = grp.sg_name;
142711447Samw@Sun.COM 		desc = grp.sg_cmnt;
142811447Samw@Sun.COM 		break;
142911447Samw@Sun.COM 
143011447Samw@Sun.COM 	default:
143111337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
143211337SWilliam.Krier@Sun.COM 		goto query_alias_err;
143311337SWilliam.Krier@Sun.COM 	}
143411337SWilliam.Krier@Sun.COM 
143511337SWilliam.Krier@Sun.COM 	switch (param->level) {
143611337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_1:
143711337SWilliam.Krier@Sun.COM 		param->ru.info1.level = param->level;
143811447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, name,
143911337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.name);
144011337SWilliam.Krier@Sun.COM 
144111447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
144211337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info1.desc);
144311337SWilliam.Krier@Sun.COM 
144411337SWilliam.Krier@Sun.COM 		param->ru.info1.unknown = 1;
144511337SWilliam.Krier@Sun.COM 		break;
144611337SWilliam.Krier@Sun.COM 
144711337SWilliam.Krier@Sun.COM 	case SAMR_QUERY_ALIAS_INFO_3:
144811337SWilliam.Krier@Sun.COM 		param->ru.info3.level = param->level;
144911447Samw@Sun.COM 		(void) NDR_MSTRING(mxa, desc,
145011337SWilliam.Krier@Sun.COM 		    (ndr_mstring_t *)&param->ru.info3.desc);
145111337SWilliam.Krier@Sun.COM 		break;
145211337SWilliam.Krier@Sun.COM 
145311337SWilliam.Krier@Sun.COM 	default:
1454*11963SAfshin.Ardakani@Sun.COM 		if (gd_type == SMB_DOMAIN_LOCAL)
145511447Samw@Sun.COM 			smb_lgrp_free(&grp);
145611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_INVALID_INFO_CLASS;
145711337SWilliam.Krier@Sun.COM 		goto query_alias_err;
145811337SWilliam.Krier@Sun.COM 	};
145911337SWilliam.Krier@Sun.COM 
1460*11963SAfshin.Ardakani@Sun.COM 	if (gd_type == SMB_DOMAIN_LOCAL)
146111447Samw@Sun.COM 		smb_lgrp_free(&grp);
146211337SWilliam.Krier@Sun.COM 	param->address = (DWORD)(uintptr_t)&param->ru;
146311337SWilliam.Krier@Sun.COM 	param->status = 0;
146411337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
146511337SWilliam.Krier@Sun.COM 
146611337SWilliam.Krier@Sun.COM query_alias_err:
146711337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
146811337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
146911337SWilliam.Krier@Sun.COM }
147011337SWilliam.Krier@Sun.COM 
147111337SWilliam.Krier@Sun.COM /*
147211337SWilliam.Krier@Sun.COM  * samr_s_DeleteDomainAlias
147311337SWilliam.Krier@Sun.COM  *
147411337SWilliam.Krier@Sun.COM  * Deletes a local group account and all its members from the
147511337SWilliam.Krier@Sun.COM  * security database, which is the security accounts manager (SAM) database.
147611337SWilliam.Krier@Sun.COM  * Only members of the Administrators or Account Operators local group can
147711337SWilliam.Krier@Sun.COM  * execute this function.
147811337SWilliam.Krier@Sun.COM  * For more information you can look at MSDN page for NetLocalGroupSetInfo.
147911337SWilliam.Krier@Sun.COM  *
148011337SWilliam.Krier@Sun.COM  * This RPC is used by CMC and right now it returns access denied.
148111337SWilliam.Krier@Sun.COM  * The peice of code that removes a local group doesn't get compiled.
148211337SWilliam.Krier@Sun.COM  */
148311337SWilliam.Krier@Sun.COM static int
148411337SWilliam.Krier@Sun.COM samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
148511337SWilliam.Krier@Sun.COM {
148611337SWilliam.Krier@Sun.COM 	struct samr_DeleteDomainAlias *param = arg;
148711337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
148811337SWilliam.Krier@Sun.COM 
148911337SWilliam.Krier@Sun.COM 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) {
149011337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
149111337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
149211337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
149311337SWilliam.Krier@Sun.COM 	}
149411337SWilliam.Krier@Sun.COM 
149511337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_DeleteDomainAlias));
149611337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
149711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
149811337SWilliam.Krier@Sun.COM 
149911337SWilliam.Krier@Sun.COM #ifdef SAMR_SUPPORT_DEL_ALIAS
150011337SWilliam.Krier@Sun.COM 	nt_group_t *grp;
150111337SWilliam.Krier@Sun.COM 	char *alias_name;
150211337SWilliam.Krier@Sun.COM 	DWORD status;
150311337SWilliam.Krier@Sun.COM 
150411337SWilliam.Krier@Sun.COM 	grp = nt_groups_lookup_rid(desc->discrim);
150511337SWilliam.Krier@Sun.COM 	if (grp == 0) {
150611337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_SUCH_ALIAS;
150711337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
150811337SWilliam.Krier@Sun.COM 	}
150911337SWilliam.Krier@Sun.COM 
151011337SWilliam.Krier@Sun.COM 	alias_name = strdup(grp->name);
151111337SWilliam.Krier@Sun.COM 	if (alias_name == 0) {
151211337SWilliam.Krier@Sun.COM 		status = NT_STATUS_NO_MEMORY;
151311337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
151411337SWilliam.Krier@Sun.COM 	}
151511337SWilliam.Krier@Sun.COM 
151611337SWilliam.Krier@Sun.COM 	status = nt_group_delete(alias_name);
151711337SWilliam.Krier@Sun.COM 	free(alias_name);
151811337SWilliam.Krier@Sun.COM 	if (status != NT_STATUS_SUCCESS)
151911337SWilliam.Krier@Sun.COM 		goto delete_alias_err;
152011337SWilliam.Krier@Sun.COM 
152111337SWilliam.Krier@Sun.COM 	param->status = 0;
152211337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
152311337SWilliam.Krier@Sun.COM 
152411337SWilliam.Krier@Sun.COM delete_alias_err:
152511337SWilliam.Krier@Sun.COM 	param->status = NT_SC_ERROR(status);
152611337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
152711337SWilliam.Krier@Sun.COM #endif
152811337SWilliam.Krier@Sun.COM }
152911337SWilliam.Krier@Sun.COM 
153011337SWilliam.Krier@Sun.COM /*
153111337SWilliam.Krier@Sun.COM  * samr_s_EnumDomainAliases
153211337SWilliam.Krier@Sun.COM  *
153311337SWilliam.Krier@Sun.COM  * This function sends back a list which contains all local groups' name.
153411337SWilliam.Krier@Sun.COM  */
153511337SWilliam.Krier@Sun.COM static int
153611337SWilliam.Krier@Sun.COM samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
153711337SWilliam.Krier@Sun.COM {
153811337SWilliam.Krier@Sun.COM 	struct samr_EnumDomainAliases *param = arg;
153911337SWilliam.Krier@Sun.COM 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
154011337SWilliam.Krier@Sun.COM 	ndr_handle_t *hd;
154111337SWilliam.Krier@Sun.COM 	samr_keydata_t *data;
154211337SWilliam.Krier@Sun.COM 	smb_group_t grp;
154311337SWilliam.Krier@Sun.COM 	smb_giter_t gi;
154411337SWilliam.Krier@Sun.COM 	int cnt, skip, i;
154511337SWilliam.Krier@Sun.COM 	struct name_rid *info;
154611337SWilliam.Krier@Sun.COM 
154711337SWilliam.Krier@Sun.COM 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
154811337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
154911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
155011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
155111337SWilliam.Krier@Sun.COM 	}
155211337SWilliam.Krier@Sun.COM 
155311337SWilliam.Krier@Sun.COM 	data = (samr_keydata_t *)hd->nh_data;
155411337SWilliam.Krier@Sun.COM 
155511337SWilliam.Krier@Sun.COM 	cnt = smb_sam_grp_cnt(data->kd_type);
155611337SWilliam.Krier@Sun.COM 	if (cnt <= param->resume_handle) {
155711337SWilliam.Krier@Sun.COM 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
155811337SWilliam.Krier@Sun.COM 		    sizeof (struct aliases_info));
155911337SWilliam.Krier@Sun.COM 
156011337SWilliam.Krier@Sun.COM 		if (param->aliases == NULL) {
156111337SWilliam.Krier@Sun.COM 			bzero(param, sizeof (struct samr_EnumDomainAliases));
156211337SWilliam.Krier@Sun.COM 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
156311337SWilliam.Krier@Sun.COM 			return (NDR_DRC_OK);
156411337SWilliam.Krier@Sun.COM 		}
156511337SWilliam.Krier@Sun.COM 
156611337SWilliam.Krier@Sun.COM 		bzero(param->aliases, sizeof (struct aliases_info));
156711337SWilliam.Krier@Sun.COM 		param->out_resume = 0;
156811337SWilliam.Krier@Sun.COM 		param->entries = 0;
156911337SWilliam.Krier@Sun.COM 		param->status = NT_STATUS_SUCCESS;
157011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
157111337SWilliam.Krier@Sun.COM 	}
157211337SWilliam.Krier@Sun.COM 
157311337SWilliam.Krier@Sun.COM 	cnt -= param->resume_handle;
157411337SWilliam.Krier@Sun.COM 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
157511337SWilliam.Krier@Sun.COM 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
157611337SWilliam.Krier@Sun.COM 
157711337SWilliam.Krier@Sun.COM 	if (param->aliases == NULL) {
157811337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
157911337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
158011337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
158111337SWilliam.Krier@Sun.COM 	}
158211337SWilliam.Krier@Sun.COM 
158311337SWilliam.Krier@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
158411337SWilliam.Krier@Sun.COM 		bzero(param, sizeof (struct samr_EnumDomainAliases));
158511337SWilliam.Krier@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
158611337SWilliam.Krier@Sun.COM 		return (NDR_DRC_OK);
158711337SWilliam.Krier@Sun.COM 	}
158811337SWilliam.Krier@Sun.COM 
158911337SWilliam.Krier@Sun.COM 	skip = i = 0;
159011337SWilliam.Krier@Sun.COM 	info = param->aliases->info;
159111337SWilliam.Krier@Sun.COM 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
159211337SWilliam.Krier@Sun.COM 		if ((skip++ >= param->resume_handle) &&
159311337SWilliam.Krier@Sun.COM 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
159411337SWilliam.Krier@Sun.COM 			info->rid = grp.sg_rid;
159511337SWilliam.Krier@Sun.COM 			(void) NDR_MSTRING(mxa, grp.sg_name,
159611337SWilliam.Krier@Sun.COM 			    (ndr_mstring_t *)&info->name);
159711337SWilliam.Krier@Sun.COM 
159811337SWilliam.Krier@Sun.COM 			info++;
159911337SWilliam.Krier@Sun.COM 		}
160011337SWilliam.Krier@Sun.COM 		smb_lgrp_free(&grp);
160111337SWilliam.Krier@Sun.COM 	}
160211337SWilliam.Krier@Sun.COM 	smb_lgrp_iterclose(&gi);
160311337SWilliam.Krier@Sun.COM 
160411337SWilliam.Krier@Sun.COM 	param->aliases->count = i;
160511337SWilliam.Krier@Sun.COM 	param->aliases->address = i;
160611337SWilliam.Krier@Sun.COM 
160711337SWilliam.Krier@Sun.COM 	param->out_resume = i;
160811337SWilliam.Krier@Sun.COM 	param->entries = i;
160911337SWilliam.Krier@Sun.COM 	param->status = 0;
161011337SWilliam.Krier@Sun.COM 	return (NDR_DRC_OK);
161111337SWilliam.Krier@Sun.COM }
161211337SWilliam.Krier@Sun.COM 
161311337SWilliam.Krier@Sun.COM /*
161411337SWilliam.Krier@Sun.COM  * samr_s_Connect3
161511337SWilliam.Krier@Sun.COM  */
161611337SWilliam.Krier@Sun.COM static int
161711337SWilliam.Krier@Sun.COM samr_s_Connect3(void *arg, ndr_xa_t *mxa)
161811337SWilliam.Krier@Sun.COM {
161911447Samw@Sun.COM 	struct samr_Connect3	*param = arg;
162011447Samw@Sun.COM 	ndr_hdid_t		*id;
162111337SWilliam.Krier@Sun.COM 
162211447Samw@Sun.COM 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
162311447Samw@Sun.COM 	if (id) {
162411447Samw@Sun.COM 		bcopy(id, &param->handle, sizeof (samr_handle_t));
162511447Samw@Sun.COM 		param->status = 0;
162611447Samw@Sun.COM 	} else {
162711447Samw@Sun.COM 		bzero(&param->handle, sizeof (samr_handle_t));
162811447Samw@Sun.COM 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
162911447Samw@Sun.COM 	}
163011447Samw@Sun.COM 
163111447Samw@Sun.COM 	return (NDR_DRC_OK);
163211337SWilliam.Krier@Sun.COM }
163311337SWilliam.Krier@Sun.COM 
163411337SWilliam.Krier@Sun.COM /*
163511337SWilliam.Krier@Sun.COM  * samr_s_Connect4
163611337SWilliam.Krier@Sun.COM  *
163711337SWilliam.Krier@Sun.COM  * This is the connect4 form of the connect request used by Windows XP.
163811337SWilliam.Krier@Sun.COM  * Returns an RPC fault for now.
163911337SWilliam.Krier@Sun.COM  */
164011337SWilliam.Krier@Sun.COM /*ARGSUSED*/
164111337SWilliam.Krier@Sun.COM static int
164211337SWilliam.Krier@Sun.COM samr_s_Connect4(void *arg, ndr_xa_t *mxa)
164311337SWilliam.Krier@Sun.COM {
164411337SWilliam.Krier@Sun.COM 	struct samr_Connect4 *param = arg;
164511337SWilliam.Krier@Sun.COM 
164611337SWilliam.Krier@Sun.COM 	bzero(param, sizeof (struct samr_Connect4));
164711337SWilliam.Krier@Sun.COM 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
164811337SWilliam.Krier@Sun.COM }
164911337SWilliam.Krier@Sun.COM 
165011337SWilliam.Krier@Sun.COM static ndr_stub_table_t samr_stub_table[] = {
165111337SWilliam.Krier@Sun.COM 	{ samr_s_ConnectAnon,		SAMR_OPNUM_ConnectAnon },
165211337SWilliam.Krier@Sun.COM 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
165311337SWilliam.Krier@Sun.COM 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
165411337SWilliam.Krier@Sun.COM 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
165511337SWilliam.Krier@Sun.COM 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
165611337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
165711447Samw@Sun.COM 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
165811337SWilliam.Krier@Sun.COM 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
165911337SWilliam.Krier@Sun.COM 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
166011337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
166111337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
166211337SWilliam.Krier@Sun.COM 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
166311337SWilliam.Krier@Sun.COM 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
166411337SWilliam.Krier@Sun.COM 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
166511337SWilliam.Krier@Sun.COM 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
166611337SWilliam.Krier@Sun.COM 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
166711337SWilliam.Krier@Sun.COM 	{ samr_s_ChangeUserPasswd,	SAMR_OPNUM_ChangeUserPasswd },
166811337SWilliam.Krier@Sun.COM 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
166911337SWilliam.Krier@Sun.COM 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
167011337SWilliam.Krier@Sun.COM 	{ samr_s_Connect3,		SAMR_OPNUM_Connect3 },
167111337SWilliam.Krier@Sun.COM 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
167211337SWilliam.Krier@Sun.COM 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
167311337SWilliam.Krier@Sun.COM 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
167411337SWilliam.Krier@Sun.COM 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
167511337SWilliam.Krier@Sun.COM 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
167611337SWilliam.Krier@Sun.COM 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
167711337SWilliam.Krier@Sun.COM 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
167811337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
167911337SWilliam.Krier@Sun.COM 	{ samr_s_EnumDomainGroups,	SAMR_OPNUM_EnumDomainGroups },
168011337SWilliam.Krier@Sun.COM 	{0}
168111337SWilliam.Krier@Sun.COM };
168211337SWilliam.Krier@Sun.COM 
168311337SWilliam.Krier@Sun.COM /*
168411337SWilliam.Krier@Sun.COM  * There is a bug in the way that midl and the marshalling code handles
168511337SWilliam.Krier@Sun.COM  * unions so we need to fix some of the data offsets at runtime. The
168611337SWilliam.Krier@Sun.COM  * following macros and the fixup functions handle the corrections.
168711337SWilliam.Krier@Sun.COM  */
168811337SWilliam.Krier@Sun.COM 
168911337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
169011337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
169111337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
169211337SWilliam.Krier@Sun.COM 
169311337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
169411337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(QueryUserInfo_result);
169511337SWilliam.Krier@Sun.COM DECL_FIXUP_STRUCT(samr_QueryUserInfo);
169611337SWilliam.Krier@Sun.COM 
169711337SWilliam.Krier@Sun.COM void
169811337SWilliam.Krier@Sun.COM fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
169911337SWilliam.Krier@Sun.COM {
170011337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
170111337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
170211337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
170311337SWilliam.Krier@Sun.COM 
170411337SWilliam.Krier@Sun.COM 	switch (val->level) {
170511337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 1);
170611337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryAliasInfo, 3);
170711337SWilliam.Krier@Sun.COM 
170811337SWilliam.Krier@Sun.COM 		default:
170911337SWilliam.Krier@Sun.COM 			return;
171011337SWilliam.Krier@Sun.COM 	};
171111337SWilliam.Krier@Sun.COM 
171211337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
171311337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
171411337SWilliam.Krier@Sun.COM 
171511337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
171611337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
171711337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
171811337SWilliam.Krier@Sun.COM }
171911337SWilliam.Krier@Sun.COM 
172011337SWilliam.Krier@Sun.COM void
172111337SWilliam.Krier@Sun.COM fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
172211337SWilliam.Krier@Sun.COM {
172311337SWilliam.Krier@Sun.COM 	unsigned short size1 = 0;
172411337SWilliam.Krier@Sun.COM 	unsigned short size2 = 0;
172511337SWilliam.Krier@Sun.COM 	unsigned short size3 = 0;
172611337SWilliam.Krier@Sun.COM 
172711337SWilliam.Krier@Sun.COM 	switch (val->switch_index) {
172811337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
172911337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
173011337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
173111337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
173211337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
173311337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
173411337SWilliam.Krier@Sun.COM 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
173511337SWilliam.Krier@Sun.COM 
173611337SWilliam.Krier@Sun.COM 		default:
173711337SWilliam.Krier@Sun.COM 			return;
173811337SWilliam.Krier@Sun.COM 	};
173911337SWilliam.Krier@Sun.COM 
174011337SWilliam.Krier@Sun.COM 	size2 = size1 + (2 * sizeof (DWORD));
174111337SWilliam.Krier@Sun.COM 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
174211337SWilliam.Krier@Sun.COM 
174311337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
174411337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
174511337SWilliam.Krier@Sun.COM 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
174611337SWilliam.Krier@Sun.COM }
174711337SWilliam.Krier@Sun.COM 
174811337SWilliam.Krier@Sun.COM /*
174911337SWilliam.Krier@Sun.COM  * As long as there is only one entry in the union, there is no need
175011337SWilliam.Krier@Sun.COM  * to patch anything.
175111337SWilliam.Krier@Sun.COM  */
175211337SWilliam.Krier@Sun.COM /*ARGSUSED*/
175311337SWilliam.Krier@Sun.COM void
175411337SWilliam.Krier@Sun.COM fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
175511337SWilliam.Krier@Sun.COM {
175611337SWilliam.Krier@Sun.COM }
1757