xref: /titanic_41/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c (revision cf115f3609b69ef25a8b5a1c0a4a5afa19271fa8)
1fe1c642dSBill Krier /*
2fe1c642dSBill Krier  * CDDL HEADER START
3fe1c642dSBill Krier  *
4fe1c642dSBill Krier  * The contents of this file are subject to the terms of the
5fe1c642dSBill Krier  * Common Development and Distribution License (the "License").
6fe1c642dSBill Krier  * You may not use this file except in compliance with the License.
7fe1c642dSBill Krier  *
8fe1c642dSBill Krier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fe1c642dSBill Krier  * or http://www.opensolaris.org/os/licensing.
10fe1c642dSBill Krier  * See the License for the specific language governing permissions
11fe1c642dSBill Krier  * and limitations under the License.
12fe1c642dSBill Krier  *
13fe1c642dSBill Krier  * When distributing Covered Code, include this CDDL HEADER in each
14fe1c642dSBill Krier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fe1c642dSBill Krier  * If applicable, add the following below this CDDL HEADER, with the
16fe1c642dSBill Krier  * fields enclosed by brackets "[]" replaced with your own identifying
17fe1c642dSBill Krier  * information: Portions Copyright [yyyy] [name of copyright owner]
18fe1c642dSBill Krier  *
19fe1c642dSBill Krier  * CDDL HEADER END
20fe1c642dSBill Krier  */
21148c5f43SAlan Wright 
22fe1c642dSBill Krier /*
23148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*cf115f36SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
25fe1c642dSBill Krier  */
26fe1c642dSBill Krier 
27fe1c642dSBill Krier /*
28fe1c642dSBill Krier  * Local Security Authority RPC (LSAR) server-side interface.
29fe1c642dSBill Krier  */
30fe1c642dSBill Krier 
31fe1c642dSBill Krier #include <unistd.h>
32fe1c642dSBill Krier #include <strings.h>
33fe1c642dSBill Krier #include <pwd.h>
34fe1c642dSBill Krier #include <grp.h>
35fe1c642dSBill Krier 
36fe1c642dSBill Krier #include <smbsrv/libsmb.h>
37fe1c642dSBill Krier #include <smbsrv/libmlrpc.h>
38fe1c642dSBill Krier #include <smbsrv/libmlsvc.h>
39fe1c642dSBill Krier #include <smbsrv/ndl/lsarpc.ndl>
40fe1c642dSBill Krier #include <lsalib.h>
41fe1c642dSBill Krier #include <smbsrv/smbinfo.h>
42fe1c642dSBill Krier #include <smbsrv/nmpipes.h>
43fe1c642dSBill Krier #include <smbsrv/ntlocale.h>
44fe1c642dSBill Krier 
45fe1c642dSBill Krier struct local_group_table {
46fe1c642dSBill Krier 	WORD sid_name_use;
47fe1c642dSBill Krier 	WORD domain_ix;
48fe1c642dSBill Krier 	char *sid;
49fe1c642dSBill Krier 	char *name;
50fe1c642dSBill Krier };
51fe1c642dSBill Krier 
52fe1c642dSBill Krier static int lsarpc_key_domain;
53fe1c642dSBill Krier static int lsarpc_key_account;
54fe1c642dSBill Krier 
55fe1c642dSBill Krier static int lsarpc_call_stub(ndr_xa_t *mxa);
56fe1c642dSBill Krier 
57fe1c642dSBill Krier static int lsarpc_s_CloseHandle(void *, ndr_xa_t *);
58fe1c642dSBill Krier static int lsarpc_s_QuerySecurityObject(void *, ndr_xa_t *);
59fe1c642dSBill Krier static int lsarpc_s_EnumAccounts(void *, ndr_xa_t *);
60fe1c642dSBill Krier static int lsarpc_s_EnumTrustedDomain(void *, ndr_xa_t *);
61fe1c642dSBill Krier static int lsarpc_s_EnumTrustedDomainsEx(void *, ndr_xa_t *);
62fe1c642dSBill Krier static int lsarpc_s_OpenAccount(void *, ndr_xa_t *);
63fe1c642dSBill Krier static int lsarpc_s_EnumPrivsAccount(void *, ndr_xa_t *);
64fe1c642dSBill Krier static int lsarpc_s_LookupPrivValue(void *, ndr_xa_t *);
65fe1c642dSBill Krier static int lsarpc_s_LookupPrivName(void *, ndr_xa_t *);
66fe1c642dSBill Krier static int lsarpc_s_LookupPrivDisplayName(void *, ndr_xa_t *);
67fe1c642dSBill Krier static int lsarpc_s_CreateSecret(void *, ndr_xa_t *);
68fe1c642dSBill Krier static int lsarpc_s_OpenSecret(void *, ndr_xa_t *);
69fe1c642dSBill Krier static int lsarpc_s_QueryInfoPolicy(void *, ndr_xa_t *);
70fe1c642dSBill Krier static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
71fe1c642dSBill Krier static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
72fe1c642dSBill Krier static int lsarpc_s_LookupSids(void *, ndr_xa_t *);
73fe1c642dSBill Krier static int lsarpc_s_LookupNames(void *, ndr_xa_t *);
74fe1c642dSBill Krier static int lsarpc_s_GetConnectedUser(void *, ndr_xa_t *);
75fe1c642dSBill Krier static int lsarpc_s_LookupSids2(void *, ndr_xa_t *);
76fe1c642dSBill Krier static int lsarpc_s_LookupSids3(void *, ndr_xa_t *);
77fe1c642dSBill Krier static int lsarpc_s_LookupNames2(void *, ndr_xa_t *);
78fe1c642dSBill Krier static int lsarpc_s_LookupNames3(void *, ndr_xa_t *);
79fe1c642dSBill Krier static int lsarpc_s_LookupNames4(void *, ndr_xa_t *);
80fe1c642dSBill Krier 
81fe1c642dSBill Krier static DWORD lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *,
82fe1c642dSBill Krier     ndr_xa_t *);
83fe1c642dSBill Krier static DWORD lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *,
84fe1c642dSBill Krier     ndr_xa_t *);
85fe1c642dSBill Krier static int lsarpc_s_UpdateDomainTable(ndr_xa_t *,
86fe1c642dSBill Krier     smb_account_t *, struct mslsa_domain_table *, DWORD *);
87fe1c642dSBill Krier 
88fe1c642dSBill Krier static ndr_stub_table_t lsarpc_stub_table[] = {
89fe1c642dSBill Krier 	{ lsarpc_s_CloseHandle,		  LSARPC_OPNUM_CloseHandle },
90fe1c642dSBill Krier 	{ lsarpc_s_QuerySecurityObject,	  LSARPC_OPNUM_QuerySecurityObject },
91fe1c642dSBill Krier 	{ lsarpc_s_EnumAccounts,	  LSARPC_OPNUM_EnumerateAccounts },
92fe1c642dSBill Krier 	{ lsarpc_s_EnumTrustedDomain,	  LSARPC_OPNUM_EnumTrustedDomain },
93fe1c642dSBill Krier 	{ lsarpc_s_EnumTrustedDomainsEx,  LSARPC_OPNUM_EnumTrustedDomainsEx },
94fe1c642dSBill Krier 	{ lsarpc_s_OpenAccount,		  LSARPC_OPNUM_OpenAccount },
95fe1c642dSBill Krier 	{ lsarpc_s_EnumPrivsAccount,	  LSARPC_OPNUM_EnumPrivsAccount },
96fe1c642dSBill Krier 	{ lsarpc_s_LookupPrivValue,	  LSARPC_OPNUM_LookupPrivValue },
97fe1c642dSBill Krier 	{ lsarpc_s_LookupPrivName,	  LSARPC_OPNUM_LookupPrivName },
98fe1c642dSBill Krier 	{ lsarpc_s_LookupPrivDisplayName, LSARPC_OPNUM_LookupPrivDisplayName },
99fe1c642dSBill Krier 	{ lsarpc_s_CreateSecret,	  LSARPC_OPNUM_CreateSecret },
100fe1c642dSBill Krier 	{ lsarpc_s_OpenSecret,		  LSARPC_OPNUM_OpenSecret },
101fe1c642dSBill Krier 	{ lsarpc_s_QueryInfoPolicy,	  LSARPC_OPNUM_QueryInfoPolicy },
102fe1c642dSBill Krier 	{ lsarpc_s_OpenDomainHandle,	  LSARPC_OPNUM_OpenPolicy },
103fe1c642dSBill Krier 	{ lsarpc_s_OpenDomainHandle,	  LSARPC_OPNUM_OpenPolicy2 },
104fe1c642dSBill Krier 	{ lsarpc_s_LookupSids,		  LSARPC_OPNUM_LookupSids },
105fe1c642dSBill Krier 	{ lsarpc_s_LookupNames,		  LSARPC_OPNUM_LookupNames },
106fe1c642dSBill Krier 	{ lsarpc_s_GetConnectedUser,	  LSARPC_OPNUM_GetConnectedUser },
107fe1c642dSBill Krier 	{ lsarpc_s_LookupSids2,		  LSARPC_OPNUM_LookupSids2 },
108fe1c642dSBill Krier 	{ lsarpc_s_LookupSids3,		  LSARPC_OPNUM_LookupSids3 },
109fe1c642dSBill Krier 	{ lsarpc_s_LookupNames2,	  LSARPC_OPNUM_LookupNames2 },
110fe1c642dSBill Krier 	{ lsarpc_s_LookupNames3,	  LSARPC_OPNUM_LookupNames3 },
111fe1c642dSBill Krier 	{ lsarpc_s_LookupNames4,	  LSARPC_OPNUM_LookupNames4 },
112fe1c642dSBill Krier 	{0}
113fe1c642dSBill Krier };
114fe1c642dSBill Krier 
115fe1c642dSBill Krier static ndr_service_t lsarpc_service = {
116fe1c642dSBill Krier 	"LSARPC",			/* name */
117fe1c642dSBill Krier 	"Local Security Authority",	/* desc */
118fe1c642dSBill Krier 	"\\lsarpc",			/* endpoint */
119fe1c642dSBill Krier 	PIPE_LSASS,			/* sec_addr_port */
120fe1c642dSBill Krier 	"12345778-1234-abcd-ef00-0123456789ab", 0,	/* abstract */
121fe1c642dSBill Krier 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
122fe1c642dSBill Krier 	0,				/* no bind_instance_size */
123fe1c642dSBill Krier 	NULL,				/* no bind_req() */
124fe1c642dSBill Krier 	NULL,				/* no unbind_and_close() */
125fe1c642dSBill Krier 	lsarpc_call_stub,		/* call_stub() */
126fe1c642dSBill Krier 	&TYPEINFO(lsarpc_interface),	/* interface ti */
127fe1c642dSBill Krier 	lsarpc_stub_table		/* stub_table */
128fe1c642dSBill Krier };
129fe1c642dSBill Krier 
130fe1c642dSBill Krier /*
131fe1c642dSBill Krier  * lsarpc_initialize
132fe1c642dSBill Krier  *
133fe1c642dSBill Krier  * This function registers the LSA RPC interface with the RPC runtime
134fe1c642dSBill Krier  * library. It must be called in order to use either the client side
135fe1c642dSBill Krier  * or the server side functions.
136fe1c642dSBill Krier  */
137fe1c642dSBill Krier void
lsarpc_initialize(void)138fe1c642dSBill Krier lsarpc_initialize(void)
139fe1c642dSBill Krier {
140fe1c642dSBill Krier 	(void) ndr_svc_register(&lsarpc_service);
141fe1c642dSBill Krier }
142fe1c642dSBill Krier 
143fe1c642dSBill Krier /*
144fe1c642dSBill Krier  * Custom call_stub to set the stream string policy.
145fe1c642dSBill Krier  */
146fe1c642dSBill Krier static int
lsarpc_call_stub(ndr_xa_t * mxa)147fe1c642dSBill Krier lsarpc_call_stub(ndr_xa_t *mxa)
148fe1c642dSBill Krier {
149fe1c642dSBill Krier 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
150fe1c642dSBill Krier 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
151fe1c642dSBill Krier 
152fe1c642dSBill Krier 	return (ndr_generic_call_stub(mxa));
153fe1c642dSBill Krier }
154fe1c642dSBill Krier 
155fe1c642dSBill Krier /*
156fe1c642dSBill Krier  * lsarpc_s_OpenDomainHandle opnum=0x06
157fe1c642dSBill Krier  *
158fe1c642dSBill Krier  * This is a request to open the LSA (OpenPolicy and OpenPolicy2).
159fe1c642dSBill Krier  * The client is looking for an LSA domain handle.
160fe1c642dSBill Krier  */
161fe1c642dSBill Krier static int
lsarpc_s_OpenDomainHandle(void * arg,ndr_xa_t * mxa)162fe1c642dSBill Krier lsarpc_s_OpenDomainHandle(void *arg, ndr_xa_t *mxa)
163fe1c642dSBill Krier {
164fe1c642dSBill Krier 	struct mslsa_OpenPolicy2 *param = arg;
165fe1c642dSBill Krier 	ndr_hdid_t *id;
166fe1c642dSBill Krier 
167fe1c642dSBill Krier 	if ((id = ndr_hdalloc(mxa, &lsarpc_key_domain)) != NULL) {
168fe1c642dSBill Krier 		bcopy(id, &param->domain_handle, sizeof (mslsa_handle_t));
169fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
170fe1c642dSBill Krier 	} else {
171fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (mslsa_handle_t));
172fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
173fe1c642dSBill Krier 	}
174fe1c642dSBill Krier 
175fe1c642dSBill Krier 	return (NDR_DRC_OK);
176fe1c642dSBill Krier }
177fe1c642dSBill Krier 
178fe1c642dSBill Krier /*
179fe1c642dSBill Krier  * lsarpc_s_CloseHandle opnum=0x00
180fe1c642dSBill Krier  *
181fe1c642dSBill Krier  * This is a request to close the LSA interface specified by the handle.
182fe1c642dSBill Krier  * We don't track handles (yet), so just zero out the handle and return
183fe1c642dSBill Krier  * NDR_DRC_OK. Setting the handle to zero appears to be standard
184fe1c642dSBill Krier  * behaviour and someone may rely on it, i.e. we do on the client side.
185fe1c642dSBill Krier  */
186fe1c642dSBill Krier static int
lsarpc_s_CloseHandle(void * arg,ndr_xa_t * mxa)187fe1c642dSBill Krier lsarpc_s_CloseHandle(void *arg, ndr_xa_t *mxa)
188fe1c642dSBill Krier {
189fe1c642dSBill Krier 	struct mslsa_CloseHandle *param = arg;
190fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
191fe1c642dSBill Krier 
192fe1c642dSBill Krier 	ndr_hdfree(mxa, id);
193fe1c642dSBill Krier 
194fe1c642dSBill Krier 	bzero(&param->result_handle, sizeof (param->result_handle));
195fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
196fe1c642dSBill Krier 	return (NDR_DRC_OK);
197fe1c642dSBill Krier }
198fe1c642dSBill Krier 
199fe1c642dSBill Krier /*
200fe1c642dSBill Krier  * lsarpc_s_QuerySecurityObject
201fe1c642dSBill Krier  */
202fe1c642dSBill Krier /*ARGSUSED*/
203fe1c642dSBill Krier static int
lsarpc_s_QuerySecurityObject(void * arg,ndr_xa_t * mxa)204fe1c642dSBill Krier lsarpc_s_QuerySecurityObject(void *arg, ndr_xa_t *mxa)
205fe1c642dSBill Krier {
206fe1c642dSBill Krier 	struct mslsa_QuerySecurityObject *param = arg;
207fe1c642dSBill Krier 
208fe1c642dSBill Krier 	bzero(param, sizeof (struct mslsa_QuerySecurityObject));
209fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
210fe1c642dSBill Krier 
211fe1c642dSBill Krier 	return (NDR_DRC_OK);
212fe1c642dSBill Krier }
213fe1c642dSBill Krier 
214fe1c642dSBill Krier /*
215fe1c642dSBill Krier  * lsarpc_s_EnumAccounts
216fe1c642dSBill Krier  *
217fe1c642dSBill Krier  * Enumerate the list of local accounts SIDs. The client should supply
218fe1c642dSBill Krier  * a valid OpenPolicy2 handle. The enum_context is used to support
219fe1c642dSBill Krier  * multiple enumeration calls to obtain the complete list of SIDs.
220fe1c642dSBill Krier  * It should be set to 0 on the first call and passed unchanged on
221fe1c642dSBill Krier  * subsequent calls until there are no more accounts - the server will
222148c5f43SAlan Wright  * return STATUS_NO_MORE_ENTRIES.
223fe1c642dSBill Krier  *
224fe1c642dSBill Krier  * For now just set the status to access-denied. Note that we still have
225fe1c642dSBill Krier  * to provide a valid address for enum_buf because it's a reference and
226fe1c642dSBill Krier  * the marshalling rules require that references must not be null.
227fe1c642dSBill Krier  * The enum_context is used to support multiple
228fe1c642dSBill Krier  */
229fe1c642dSBill Krier static int
lsarpc_s_EnumAccounts(void * arg,ndr_xa_t * mxa)230fe1c642dSBill Krier lsarpc_s_EnumAccounts(void *arg, ndr_xa_t *mxa)
231fe1c642dSBill Krier {
232fe1c642dSBill Krier 	struct mslsa_EnumerateAccounts *param = arg;
233fe1c642dSBill Krier 	struct mslsa_EnumAccountBuf *enum_buf;
234fe1c642dSBill Krier 
235fe1c642dSBill Krier 	bzero(param, sizeof (struct mslsa_EnumerateAccounts));
236fe1c642dSBill Krier 
237fe1c642dSBill Krier 	enum_buf = NDR_NEW(mxa, struct mslsa_EnumAccountBuf);
238fe1c642dSBill Krier 	if (enum_buf == NULL) {
239fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
240fe1c642dSBill Krier 		return (NDR_DRC_OK);
241fe1c642dSBill Krier 	}
242fe1c642dSBill Krier 
243fe1c642dSBill Krier 	bzero(enum_buf, sizeof (struct mslsa_EnumAccountBuf));
244fe1c642dSBill Krier 	param->enum_buf = enum_buf;
245fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
246fe1c642dSBill Krier 	return (NDR_DRC_OK);
247fe1c642dSBill Krier }
248fe1c642dSBill Krier 
249fe1c642dSBill Krier 
250fe1c642dSBill Krier /*
251fe1c642dSBill Krier  * lsarpc_s_EnumTrustedDomain
252fe1c642dSBill Krier  *
253fe1c642dSBill Krier  * This is the server side function for handling requests to enumerate
254fe1c642dSBill Krier  * the list of trusted domains: currently held in the NT domain database.
255fe1c642dSBill Krier  * This call requires an OpenPolicy2 handle. The enum_context is used to
256fe1c642dSBill Krier  * support multiple enumeration calls to obtain the complete list.
257fe1c642dSBill Krier  * It should be set to 0 on the first call and passed unchanged on
258fe1c642dSBill Krier  * subsequent calls until there are no more accounts - the server will
259148c5f43SAlan Wright  * return STATUS_NO_MORE_ENTRIES.
260fe1c642dSBill Krier  *
261fe1c642dSBill Krier  * For now just set the status to access-denied. Note that we still have
262fe1c642dSBill Krier  * to provide a valid address for enum_buf because it's a reference and
263fe1c642dSBill Krier  * the marshalling rules require that references must not be null.
264fe1c642dSBill Krier  */
265fe1c642dSBill Krier static int
lsarpc_s_EnumTrustedDomain(void * arg,ndr_xa_t * mxa)266fe1c642dSBill Krier lsarpc_s_EnumTrustedDomain(void *arg, ndr_xa_t *mxa)
267fe1c642dSBill Krier {
268fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomain *param = arg;
269fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomainBuf *enum_buf;
270fe1c642dSBill Krier 
271fe1c642dSBill Krier 	bzero(param, sizeof (struct mslsa_EnumTrustedDomain));
272fe1c642dSBill Krier 
273fe1c642dSBill Krier 	enum_buf = NDR_NEW(mxa, struct mslsa_EnumTrustedDomainBuf);
274fe1c642dSBill Krier 	if (enum_buf == NULL) {
275fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
276fe1c642dSBill Krier 		return (NDR_DRC_OK);
277fe1c642dSBill Krier 	}
278fe1c642dSBill Krier 
279fe1c642dSBill Krier 	bzero(enum_buf, sizeof (struct mslsa_EnumTrustedDomainBuf));
280fe1c642dSBill Krier 	param->enum_buf = enum_buf;
281fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
282fe1c642dSBill Krier 	return (NDR_DRC_OK);
283fe1c642dSBill Krier }
284fe1c642dSBill Krier 
285fe1c642dSBill Krier /*
286fe1c642dSBill Krier  * lsarpc_s_EnumTrustedDomainsEx
287fe1c642dSBill Krier  *
288fe1c642dSBill Krier  * This is the server side function for handling requests to enumerate
289fe1c642dSBill Krier  * the list of trusted domains: currently held in the NT domain database.
290fe1c642dSBill Krier  * This call requires an OpenPolicy2 handle. The enum_context is used to
291fe1c642dSBill Krier  * support multiple enumeration calls to obtain the complete list.
292fe1c642dSBill Krier  * It should be set to 0 on the first call and passed unchanged on
293fe1c642dSBill Krier  * subsequent calls until there are no more accounts - the server will
294148c5f43SAlan Wright  * return STATUS_NO_MORE_ENTRIES.
295fe1c642dSBill Krier  *
296fe1c642dSBill Krier  * For now just set the status to access-denied. Note that we still have
297fe1c642dSBill Krier  * to provide a valid address for enum_buf because it's a reference and
298fe1c642dSBill Krier  * the marshalling rules require that references must not be null.
299fe1c642dSBill Krier  */
300fe1c642dSBill Krier static int
lsarpc_s_EnumTrustedDomainsEx(void * arg,ndr_xa_t * mxa)301fe1c642dSBill Krier lsarpc_s_EnumTrustedDomainsEx(void *arg, ndr_xa_t *mxa)
302fe1c642dSBill Krier {
303fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomainEx *param = arg;
304fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomainBufEx *enum_buf;
305fe1c642dSBill Krier 
306fe1c642dSBill Krier 	bzero(param, sizeof (struct mslsa_EnumTrustedDomainEx));
307fe1c642dSBill Krier 
308fe1c642dSBill Krier 	enum_buf = NDR_NEW(mxa, struct mslsa_EnumTrustedDomainBufEx);
309fe1c642dSBill Krier 	if (enum_buf == NULL) {
310fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
311fe1c642dSBill Krier 		return (NDR_DRC_OK);
312fe1c642dSBill Krier 	}
313fe1c642dSBill Krier 
314fe1c642dSBill Krier 	bzero(enum_buf, sizeof (struct mslsa_EnumTrustedDomainBufEx));
315fe1c642dSBill Krier 	param->enum_buf = enum_buf;
316fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
317fe1c642dSBill Krier 	return (NDR_DRC_OK);
318fe1c642dSBill Krier }
319fe1c642dSBill Krier 
320fe1c642dSBill Krier /*
321fe1c642dSBill Krier  * lsarpc_s_OpenAccount
322fe1c642dSBill Krier  *
323fe1c642dSBill Krier  * This is a request to open an account handle.
324fe1c642dSBill Krier  */
325fe1c642dSBill Krier static int
lsarpc_s_OpenAccount(void * arg,ndr_xa_t * mxa)326fe1c642dSBill Krier lsarpc_s_OpenAccount(void *arg, ndr_xa_t *mxa)
327fe1c642dSBill Krier {
328fe1c642dSBill Krier 	struct mslsa_OpenAccount *param = arg;
329fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
330fe1c642dSBill Krier 	ndr_handle_t *hd;
331fe1c642dSBill Krier 
332fe1c642dSBill Krier 	hd = ndr_hdlookup(mxa, id);
333fe1c642dSBill Krier 	if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
334fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_OpenAccount));
335fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
336fe1c642dSBill Krier 		return (NDR_DRC_OK);
337fe1c642dSBill Krier 	}
338fe1c642dSBill Krier 
339fe1c642dSBill Krier 	if ((id = ndr_hdalloc(mxa, &lsarpc_key_account)) != NULL) {
340fe1c642dSBill Krier 		bcopy(id, &param->account_handle, sizeof (mslsa_handle_t));
341fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
342fe1c642dSBill Krier 	} else {
343fe1c642dSBill Krier 		bzero(&param->account_handle, sizeof (mslsa_handle_t));
344fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
345fe1c642dSBill Krier 	}
346fe1c642dSBill Krier 
347fe1c642dSBill Krier 	return (NDR_DRC_OK);
348fe1c642dSBill Krier }
349fe1c642dSBill Krier 
350fe1c642dSBill Krier 
351fe1c642dSBill Krier /*
352fe1c642dSBill Krier  * lsarpc_s_EnumPrivsAccount
353fe1c642dSBill Krier  *
354fe1c642dSBill Krier  * This is the server side function for handling requests for account
355fe1c642dSBill Krier  * privileges. For now just set the status to not-supported status and
356fe1c642dSBill Krier  * return NDR_DRC_OK. Note that we still have to provide a valid
357fe1c642dSBill Krier  * address for enum_buf because it's a reference and the marshalling
358fe1c642dSBill Krier  * rules require that references must not be null.
359fe1c642dSBill Krier  */
360fe1c642dSBill Krier /*ARGSUSED*/
361fe1c642dSBill Krier static int
lsarpc_s_EnumPrivsAccount(void * arg,ndr_xa_t * mxa)362fe1c642dSBill Krier lsarpc_s_EnumPrivsAccount(void *arg, ndr_xa_t *mxa)
363fe1c642dSBill Krier {
364fe1c642dSBill Krier 	struct mslsa_EnumPrivsAccount *param = arg;
365fe1c642dSBill Krier 
366fe1c642dSBill Krier 	bzero(param, sizeof (struct mslsa_EnumPrivsAccount));
367fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
368fe1c642dSBill Krier 	return (NDR_DRC_OK);
369fe1c642dSBill Krier }
370fe1c642dSBill Krier 
371fe1c642dSBill Krier /*
372fe1c642dSBill Krier  * lsarpc_s_LookupPrivValue
373fe1c642dSBill Krier  *
374fe1c642dSBill Krier  * Server side function used to map a privilege name to a locally unique
375fe1c642dSBill Krier  * identifier (LUID).
376fe1c642dSBill Krier  */
377fe1c642dSBill Krier /*ARGSUSED*/
378fe1c642dSBill Krier static int
lsarpc_s_LookupPrivValue(void * arg,ndr_xa_t * mxa)379fe1c642dSBill Krier lsarpc_s_LookupPrivValue(void *arg, ndr_xa_t *mxa)
380fe1c642dSBill Krier {
381fe1c642dSBill Krier 	struct mslsa_LookupPrivValue *param = arg;
382fe1c642dSBill Krier 	smb_privinfo_t *pi;
383fe1c642dSBill Krier 
384fe1c642dSBill Krier 	if ((pi = smb_priv_getbyname((char *)param->name.str)) == NULL) {
385fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivValue));
386fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
387fe1c642dSBill Krier 		return (NDR_DRC_OK);
388fe1c642dSBill Krier 	}
389fe1c642dSBill Krier 
390fe1c642dSBill Krier 	param->luid.low_part = pi->id;
391fe1c642dSBill Krier 	param->luid.high_part = 0;
392fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
393fe1c642dSBill Krier 	return (NDR_DRC_OK);
394fe1c642dSBill Krier }
395fe1c642dSBill Krier 
396fe1c642dSBill Krier /*
397fe1c642dSBill Krier  * lsarpc_s_LookupPrivName
398fe1c642dSBill Krier  *
399fe1c642dSBill Krier  * Server side function used to map a locally unique identifier (LUID)
400fe1c642dSBill Krier  * to the appropriate privilege name string.
401fe1c642dSBill Krier  */
402fe1c642dSBill Krier static int
lsarpc_s_LookupPrivName(void * arg,ndr_xa_t * mxa)403fe1c642dSBill Krier lsarpc_s_LookupPrivName(void *arg, ndr_xa_t *mxa)
404fe1c642dSBill Krier {
405fe1c642dSBill Krier 	struct mslsa_LookupPrivName *param = arg;
406fe1c642dSBill Krier 	smb_privinfo_t *pi;
407fe1c642dSBill Krier 	int rc;
408fe1c642dSBill Krier 
409fe1c642dSBill Krier 	if ((pi = smb_priv_getbyvalue(param->luid.low_part)) == NULL) {
410fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivName));
411fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
412fe1c642dSBill Krier 		return (NDR_DRC_OK);
413fe1c642dSBill Krier 	}
414fe1c642dSBill Krier 
415fe1c642dSBill Krier 	param->name = NDR_NEW(mxa, mslsa_string_t);
416fe1c642dSBill Krier 	if (param->name == NULL) {
417fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivName));
418fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
419fe1c642dSBill Krier 		return (NDR_DRC_OK);
420fe1c642dSBill Krier 	}
421fe1c642dSBill Krier 
422fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, pi->name, (ndr_mstring_t *)param->name);
423fe1c642dSBill Krier 	if (rc == -1) {
424fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivName));
425fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
426fe1c642dSBill Krier 		return (NDR_DRC_OK);
427fe1c642dSBill Krier 	}
428fe1c642dSBill Krier 
429fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
430fe1c642dSBill Krier 	return (NDR_DRC_OK);
431fe1c642dSBill Krier }
432fe1c642dSBill Krier 
433fe1c642dSBill Krier /*
434fe1c642dSBill Krier  * lsarpc_s_LookupPrivDisplayName
435fe1c642dSBill Krier  *
436fe1c642dSBill Krier  * This is the server side function for handling requests for account
437fe1c642dSBill Krier  * privileges. For now just set the status to not-supported status and
438fe1c642dSBill Krier  * return NDR_DRC_OK.
439fe1c642dSBill Krier  */
440fe1c642dSBill Krier static int
lsarpc_s_LookupPrivDisplayName(void * arg,ndr_xa_t * mxa)441fe1c642dSBill Krier lsarpc_s_LookupPrivDisplayName(void *arg, ndr_xa_t *mxa)
442fe1c642dSBill Krier {
443fe1c642dSBill Krier 	struct mslsa_LookupPrivDisplayName *param = arg;
444fe1c642dSBill Krier 	smb_privinfo_t *pi;
445fe1c642dSBill Krier 	int rc;
446fe1c642dSBill Krier 
447fe1c642dSBill Krier 	if ((pi = smb_priv_getbyname((char *)param->name.str)) == NULL) {
448fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
449fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
450fe1c642dSBill Krier 		return (NDR_DRC_OK);
451fe1c642dSBill Krier 	}
452fe1c642dSBill Krier 
453fe1c642dSBill Krier 	param->display_name = NDR_NEW(mxa, mslsa_string_t);
454fe1c642dSBill Krier 	if (param->display_name == NULL) {
455fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
456fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
457fe1c642dSBill Krier 		return (NDR_DRC_OK);
458fe1c642dSBill Krier 	}
459fe1c642dSBill Krier 
460fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, pi->display_name,
461fe1c642dSBill Krier 	    (ndr_mstring_t *)param->display_name);
462fe1c642dSBill Krier 	if (rc == -1) {
463fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
464fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
465fe1c642dSBill Krier 		return (NDR_DRC_OK);
466fe1c642dSBill Krier 	}
467fe1c642dSBill Krier 
468fe1c642dSBill Krier 	param->language_ret = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
469fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
470fe1c642dSBill Krier 	return (NDR_DRC_OK);
471fe1c642dSBill Krier }
472fe1c642dSBill Krier 
473fe1c642dSBill Krier static int
lsarpc_s_CreateSecret(void * arg,ndr_xa_t * mxa)474fe1c642dSBill Krier lsarpc_s_CreateSecret(void *arg, ndr_xa_t *mxa)
475fe1c642dSBill Krier {
476fe1c642dSBill Krier 	struct mslsa_CreateSecret *param = arg;
477fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
478fe1c642dSBill Krier 	ndr_handle_t *hd;
479fe1c642dSBill Krier 
480fe1c642dSBill Krier 	hd = ndr_hdlookup(mxa, id);
481fe1c642dSBill Krier 	if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
482fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_OpenAccount));
483fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
484fe1c642dSBill Krier 		return (NDR_DRC_OK);
485fe1c642dSBill Krier 	}
486fe1c642dSBill Krier 
487fe1c642dSBill Krier 	bzero(&param->secret_handle, sizeof (mslsa_handle_t));
488fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
489fe1c642dSBill Krier 	return (NDR_DRC_OK);
490fe1c642dSBill Krier }
491fe1c642dSBill Krier 
492fe1c642dSBill Krier static int
lsarpc_s_OpenSecret(void * arg,ndr_xa_t * mxa)493fe1c642dSBill Krier lsarpc_s_OpenSecret(void *arg, ndr_xa_t *mxa)
494fe1c642dSBill Krier {
495fe1c642dSBill Krier 	struct mslsa_OpenSecret *param = arg;
496fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
497fe1c642dSBill Krier 	ndr_handle_t *hd;
498fe1c642dSBill Krier 
499fe1c642dSBill Krier 	hd = ndr_hdlookup(mxa, id);
500fe1c642dSBill Krier 	if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
501fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_OpenAccount));
502fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
503fe1c642dSBill Krier 		return (NDR_DRC_OK);
504fe1c642dSBill Krier 	}
505fe1c642dSBill Krier 
506fe1c642dSBill Krier 	bzero(&param->secret_handle, sizeof (mslsa_handle_t));
507fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
508fe1c642dSBill Krier 	return (NDR_DRC_OK);
509fe1c642dSBill Krier }
510fe1c642dSBill Krier 
511fe1c642dSBill Krier /*
512fe1c642dSBill Krier  * lsarpc_s_GetConnectedUser
513fe1c642dSBill Krier  *
514fe1c642dSBill Krier  * Return the account name and NetBIOS domain name for the user making
515fe1c642dSBill Krier  * the request.  The hostname field should be ignored by the server.
516fe1c642dSBill Krier  */
517fe1c642dSBill Krier static int
lsarpc_s_GetConnectedUser(void * arg,ndr_xa_t * mxa)518fe1c642dSBill Krier lsarpc_s_GetConnectedUser(void *arg, ndr_xa_t *mxa)
519fe1c642dSBill Krier {
520fe1c642dSBill Krier 	struct mslsa_GetConnectedUser *param = arg;
521*cf115f36SGordon Ross 	smb_netuserinfo_t *user = mxa->pipe->np_user;
522fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
523fe1c642dSBill Krier 	smb_domainex_t di;
524fe1c642dSBill Krier 	int rc1;
525fe1c642dSBill Krier 	int rc2;
526fe1c642dSBill Krier 
527fe1c642dSBill Krier 	if (!smb_domain_getinfo(&di)) {
528fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_GetConnectedUser));
529fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
530fe1c642dSBill Krier 		param->status = status;
531fe1c642dSBill Krier 		return (NDR_DRC_OK);
532fe1c642dSBill Krier 	}
533fe1c642dSBill Krier 
534fe1c642dSBill Krier 	param->owner = NDR_NEW(mxa, struct mslsa_string_desc);
535fe1c642dSBill Krier 	param->domain = NDR_NEW(mxa, struct mslsa_DomainName);
536fe1c642dSBill Krier 	if (param->owner == NULL || param->domain == NULL) {
537fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
538fe1c642dSBill Krier 		param->status = status;
539fe1c642dSBill Krier 		return (NDR_DRC_OK);
540fe1c642dSBill Krier 	}
541fe1c642dSBill Krier 
542fe1c642dSBill Krier 	param->domain->name = NDR_NEW(mxa, struct mslsa_string_desc);
543fe1c642dSBill Krier 	if (param->domain->name == NULL) {
544fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
545fe1c642dSBill Krier 		param->status = status;
546fe1c642dSBill Krier 		return (NDR_DRC_OK);
547fe1c642dSBill Krier 	}
548fe1c642dSBill Krier 
549fe1c642dSBill Krier 	rc1 = NDR_MSTRING(mxa, user->ui_account,
550fe1c642dSBill Krier 	    (ndr_mstring_t *)param->owner);
551fe1c642dSBill Krier 	rc2 = NDR_MSTRING(mxa, user->ui_domain,
552fe1c642dSBill Krier 	    (ndr_mstring_t *)param->domain->name);
553fe1c642dSBill Krier 
554fe1c642dSBill Krier 	if (rc1 == -1 || rc2 == -1)
555fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
556fe1c642dSBill Krier 
557fe1c642dSBill Krier 	param->status = status;
558fe1c642dSBill Krier 	return (NDR_DRC_OK);
559fe1c642dSBill Krier }
560fe1c642dSBill Krier 
561fe1c642dSBill Krier 
562fe1c642dSBill Krier /*
563fe1c642dSBill Krier  * lsarpc_s_QueryInfoPolicy
564fe1c642dSBill Krier  *
565fe1c642dSBill Krier  * This is the server side function for handling LSA information policy
566fe1c642dSBill Krier  * queries. Currently, we only support primary domain and account
567fe1c642dSBill Krier  * domain queries. This is just a front end to switch on the request
568fe1c642dSBill Krier  * and hand it off to the appropriate function to actually deal with
569fe1c642dSBill Krier  * obtaining and building the response.
570fe1c642dSBill Krier  */
571fe1c642dSBill Krier static int
lsarpc_s_QueryInfoPolicy(void * arg,ndr_xa_t * mxa)572fe1c642dSBill Krier lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa)
573fe1c642dSBill Krier {
574fe1c642dSBill Krier 	struct mslsa_QueryInfoPolicy *param = arg;
575fe1c642dSBill Krier 	union mslsa_PolicyInfoResUnion *ru = &param->ru;
576fe1c642dSBill Krier 	int security_mode;
577fe1c642dSBill Krier 	DWORD status;
578fe1c642dSBill Krier 
579fe1c642dSBill Krier 	param->switch_value = param->info_class;
580fe1c642dSBill Krier 
581fe1c642dSBill Krier 	switch (param->info_class) {
582fe1c642dSBill Krier 	case MSLSA_POLICY_AUDIT_EVENTS_INFO:
583fe1c642dSBill Krier 		ru->audit_events.enabled = 0;
584fe1c642dSBill Krier 		ru->audit_events.count = 1;
585fe1c642dSBill Krier 		ru->audit_events.settings
586fe1c642dSBill Krier 		    = NDR_MALLOC(mxa, sizeof (DWORD));
587fe1c642dSBill Krier 		bzero(ru->audit_events.settings, sizeof (DWORD));
588fe1c642dSBill Krier 		status = NT_STATUS_SUCCESS;
589fe1c642dSBill Krier 		break;
590fe1c642dSBill Krier 
591fe1c642dSBill Krier 	case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
592fe1c642dSBill Krier 		status = lsarpc_s_PrimaryDomainInfo(&ru->pd_info, mxa);
593fe1c642dSBill Krier 		break;
594fe1c642dSBill Krier 
595fe1c642dSBill Krier 	case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
596fe1c642dSBill Krier 		status = lsarpc_s_AccountDomainInfo(&ru->ad_info, mxa);
597fe1c642dSBill Krier 		break;
598fe1c642dSBill Krier 
599fe1c642dSBill Krier 	case MSLSA_POLICY_SERVER_ROLE_INFO:
600fe1c642dSBill Krier 		security_mode = smb_config_get_secmode();
601fe1c642dSBill Krier 
602fe1c642dSBill Krier 		if (security_mode == SMB_SECMODE_DOMAIN)
603fe1c642dSBill Krier 			ru->server_role.role = LSA_ROLE_MEMBER_SERVER;
604fe1c642dSBill Krier 		else
605fe1c642dSBill Krier 			ru->server_role.role = LSA_ROLE_STANDALONE_SERVER;
606fe1c642dSBill Krier 
607fe1c642dSBill Krier 		ru->server_role.pad = 0;
608fe1c642dSBill Krier 		status = NT_STATUS_SUCCESS;
609fe1c642dSBill Krier 		break;
610fe1c642dSBill Krier 
611fe1c642dSBill Krier 	default:
612fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_QueryInfoPolicy));
613fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_INFO_CLASS);
614fe1c642dSBill Krier 		return (NDR_DRC_OK);
615fe1c642dSBill Krier 	}
616fe1c642dSBill Krier 
617fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS)
618fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
619fe1c642dSBill Krier 	else
620fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
621fe1c642dSBill Krier 	param->address = (DWORD)(uintptr_t)ru;
622fe1c642dSBill Krier 
623fe1c642dSBill Krier 	return (NDR_DRC_OK);
624fe1c642dSBill Krier }
625fe1c642dSBill Krier 
626fe1c642dSBill Krier 
627fe1c642dSBill Krier /*
628fe1c642dSBill Krier  * lsarpc_s_PrimaryDomainInfo
629fe1c642dSBill Krier  *
630fe1c642dSBill Krier  * Service primary domain policy queries.  In domain mode, return the
631fe1c642dSBill Krier  * primary domain name and SID.   In workgroup mode, return the local
632fe1c642dSBill Krier  * hostname and local domain SID.
633fe1c642dSBill Krier  *
634fe1c642dSBill Krier  * Note: info is zeroed on entry to ensure the SID and name do not
635fe1c642dSBill Krier  * contain spurious values if an error is returned.
636fe1c642dSBill Krier  */
637fe1c642dSBill Krier static DWORD
lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo * info,ndr_xa_t * mxa)638fe1c642dSBill Krier lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *info,
639fe1c642dSBill Krier     ndr_xa_t *mxa)
640fe1c642dSBill Krier {
641fe1c642dSBill Krier 	smb_domain_t di;
642fe1c642dSBill Krier 	boolean_t found;
643fe1c642dSBill Krier 	int rc;
644fe1c642dSBill Krier 
645fe1c642dSBill Krier 	bzero(info, sizeof (struct mslsa_PrimaryDomainInfo));
646fe1c642dSBill Krier 
647fe1c642dSBill Krier 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
648fe1c642dSBill Krier 		found = smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di);
649fe1c642dSBill Krier 	else
650fe1c642dSBill Krier 		found = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &di);
651fe1c642dSBill Krier 
652fe1c642dSBill Krier 	if (!found)
653fe1c642dSBill Krier 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
654fe1c642dSBill Krier 
655fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
656fe1c642dSBill Krier 	info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
657fe1c642dSBill Krier 
658fe1c642dSBill Krier 	if ((rc == -1) || (info->sid == NULL))
659fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
660fe1c642dSBill Krier 
661fe1c642dSBill Krier 	return (NT_STATUS_SUCCESS);
662fe1c642dSBill Krier }
663fe1c642dSBill Krier 
664fe1c642dSBill Krier 
665fe1c642dSBill Krier /*
666fe1c642dSBill Krier  * lsarpc_s_AccountDomainInfo
667fe1c642dSBill Krier  *
668fe1c642dSBill Krier  * Service account domain policy queries.  We return our local domain
669fe1c642dSBill Krier  * information so that the client knows who to query for information
670fe1c642dSBill Krier  * on local names and SIDs.  The domain name is the local hostname.
671fe1c642dSBill Krier  *
672fe1c642dSBill Krier  * Note: info is zeroed on entry to ensure the SID and name do not
673fe1c642dSBill Krier  * contain spurious values if an error is returned.
674fe1c642dSBill Krier  */
675fe1c642dSBill Krier static DWORD
lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo * info,ndr_xa_t * mxa)676fe1c642dSBill Krier lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *info,
677fe1c642dSBill Krier     ndr_xa_t *mxa)
678fe1c642dSBill Krier {
679fe1c642dSBill Krier 	smb_domain_t di;
680fe1c642dSBill Krier 	int rc;
681fe1c642dSBill Krier 
682fe1c642dSBill Krier 	bzero(info, sizeof (struct mslsa_AccountDomainInfo));
683fe1c642dSBill Krier 
684fe1c642dSBill Krier 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
685fe1c642dSBill Krier 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
686fe1c642dSBill Krier 
687fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
688fe1c642dSBill Krier 	info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
689fe1c642dSBill Krier 
690fe1c642dSBill Krier 	if ((rc == -1) || (info->sid == NULL))
691fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
692fe1c642dSBill Krier 
693fe1c642dSBill Krier 	return (NT_STATUS_SUCCESS);
694fe1c642dSBill Krier }
695fe1c642dSBill Krier 
696fe1c642dSBill Krier /*
697fe1c642dSBill Krier  * lsarpc_s_LookupNames
698fe1c642dSBill Krier  *
699fe1c642dSBill Krier  * This is the service side function for handling name lookup requests.
700fe1c642dSBill Krier  * Currently, we only support lookups of a single name. This is also a
701fe1c642dSBill Krier  * pass through interface so all we do is act as a proxy between the
702fe1c642dSBill Krier  * client and the DC.
703fe1c642dSBill Krier  */
704fe1c642dSBill Krier static int
lsarpc_s_LookupNames(void * arg,ndr_xa_t * mxa)705fe1c642dSBill Krier lsarpc_s_LookupNames(void *arg, ndr_xa_t *mxa)
706fe1c642dSBill Krier {
707fe1c642dSBill Krier 	struct mslsa_LookupNames *param = arg;
708fe1c642dSBill Krier 	struct mslsa_rid_entry *rids;
709fe1c642dSBill Krier 	struct mslsa_domain_table *domain_table;
710fe1c642dSBill Krier 	struct mslsa_domain_entry *domain_entry;
711fe1c642dSBill Krier 	smb_account_t account;
712fe1c642dSBill Krier 	uint32_t status;
713fe1c642dSBill Krier 	char *accname;
714fe1c642dSBill Krier 	int rc = 0;
715fe1c642dSBill Krier 
716fe1c642dSBill Krier 	if (param->name_table->n_entry != 1)
717fe1c642dSBill Krier 		return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
718fe1c642dSBill Krier 
719fe1c642dSBill Krier 	rids = NDR_NEW(mxa, struct mslsa_rid_entry);
720fe1c642dSBill Krier 	domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
721fe1c642dSBill Krier 	domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
722fe1c642dSBill Krier 
723fe1c642dSBill Krier 	if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
724fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupNames));
725fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
726fe1c642dSBill Krier 		return (NDR_DRC_OK);
727fe1c642dSBill Krier 	}
728fe1c642dSBill Krier 
729fe1c642dSBill Krier 	accname = (char *)param->name_table->names->str;
730fe1c642dSBill Krier 	status = lsa_lookup_name(accname, SidTypeUnknown, &account);
731fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS) {
732fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupNames));
733fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
734fe1c642dSBill Krier 		return (NDR_DRC_OK);
735fe1c642dSBill Krier 	}
736fe1c642dSBill Krier 
737fe1c642dSBill Krier 	/*
738fe1c642dSBill Krier 	 * Set up the rid table.
739fe1c642dSBill Krier 	 */
740fe1c642dSBill Krier 	rids[0].sid_name_use = account.a_type;
741fe1c642dSBill Krier 	rids[0].rid = account.a_rid;
742fe1c642dSBill Krier 	rids[0].domain_index = 0;
743fe1c642dSBill Krier 	param->translated_sids.n_entry = 1;
744fe1c642dSBill Krier 	param->translated_sids.rids = rids;
745fe1c642dSBill Krier 
746fe1c642dSBill Krier 	/*
747fe1c642dSBill Krier 	 * Set up the domain table.
748fe1c642dSBill Krier 	 */
749fe1c642dSBill Krier 	domain_table->entries = domain_entry;
750fe1c642dSBill Krier 	domain_table->n_entry = 1;
751fe1c642dSBill Krier 	domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
752fe1c642dSBill Krier 
753fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, account.a_domain,
754fe1c642dSBill Krier 	    (ndr_mstring_t *)&domain_entry->domain_name);
755fe1c642dSBill Krier 	domain_entry->domain_sid =
756fe1c642dSBill Krier 	    (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
757fe1c642dSBill Krier 
758fe1c642dSBill Krier 	if (rc == -1 || domain_entry->domain_sid == NULL) {
759fe1c642dSBill Krier 		smb_account_free(&account);
760fe1c642dSBill Krier 		bzero(param, sizeof (struct mslsa_LookupNames));
761fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
762fe1c642dSBill Krier 		return (NDR_DRC_OK);
763fe1c642dSBill Krier 	}
764fe1c642dSBill Krier 
765fe1c642dSBill Krier 	param->domain_table = domain_table;
766fe1c642dSBill Krier 	param->mapped_count = 1;
767fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
768fe1c642dSBill Krier 
769fe1c642dSBill Krier 	smb_account_free(&account);
770fe1c642dSBill Krier 	return (NDR_DRC_OK);
771fe1c642dSBill Krier }
772fe1c642dSBill Krier 
773fe1c642dSBill Krier /*
774fe1c642dSBill Krier  * lsarpc_s_LookupSids
775fe1c642dSBill Krier  *
776fe1c642dSBill Krier  * This is the service side function for handling sid lookup requests.
777fe1c642dSBill Krier  * We have to set up both the name table and the domain table in the
778fe1c642dSBill Krier  * response. For each SID, we check for UNIX domain (local lookup) or
779fe1c642dSBill Krier  * NT domain (DC lookup) and call the appropriate lookup function. This
780fe1c642dSBill Krier  * should resolve the SID to a name. Then we need to update the domain
781fe1c642dSBill Krier  * table and make the name entry point at the appropriate domain table
782fe1c642dSBill Krier  * entry.
783fe1c642dSBill Krier  *
784fe1c642dSBill Krier  *
785fe1c642dSBill Krier  * This RPC should behave as if LookupOptions is LSA_LOOKUP_OPT_ALL and
786fe1c642dSBill Krier  * ClientRevision is LSA_CLIENT_REVISION_NT.
787fe1c642dSBill Krier  *
788fe1c642dSBill Krier  * On success return 0. Otherwise return an RPC specific error code.
789fe1c642dSBill Krier  */
790fd9ee8b5Sjoyce mcintosh 
791fe1c642dSBill Krier static int
lsarpc_s_LookupSids(void * arg,ndr_xa_t * mxa)792fe1c642dSBill Krier lsarpc_s_LookupSids(void *arg, ndr_xa_t *mxa)
793fe1c642dSBill Krier {
794fe1c642dSBill Krier 	struct mslsa_LookupSids *param = arg;
795fe1c642dSBill Krier 	struct mslsa_domain_table *domain_table;
796fe1c642dSBill Krier 	struct mslsa_domain_entry *domain_entry;
797fe1c642dSBill Krier 	struct mslsa_name_entry *names;
798fe1c642dSBill Krier 	struct mslsa_name_entry *name;
799fe1c642dSBill Krier 	smb_account_t account;
800fe1c642dSBill Krier 	smb_sid_t *sid;
801fe1c642dSBill Krier 	DWORD n_entry;
802fd9ee8b5Sjoyce mcintosh 	DWORD n_mapped;
803fd9ee8b5Sjoyce mcintosh 	char sidstr[SMB_SID_STRSZ];
804fe1c642dSBill Krier 	int result;
805fe1c642dSBill Krier 	int i;
806fe1c642dSBill Krier 
807fd9ee8b5Sjoyce mcintosh 	bzero(&account, sizeof (smb_account_t));
808fd9ee8b5Sjoyce mcintosh 	n_mapped = 0;
809fe1c642dSBill Krier 	n_entry = param->lup_sid_table.n_entry;
810fd9ee8b5Sjoyce mcintosh 
811fe1c642dSBill Krier 	names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry);
812fe1c642dSBill Krier 	domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
813fe1c642dSBill Krier 	domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
814fe1c642dSBill Krier 	    MLSVC_DOMAIN_MAX);
815fe1c642dSBill Krier 
816fd9ee8b5Sjoyce mcintosh 	if (names == NULL || domain_table == NULL || domain_entry == NULL)
817fd9ee8b5Sjoyce mcintosh 		goto lookup_sid_failed;
818fe1c642dSBill Krier 
819fe1c642dSBill Krier 	domain_table->entries = domain_entry;
820fe1c642dSBill Krier 	domain_table->n_entry = 0;
821fe1c642dSBill Krier 	domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
822fe1c642dSBill Krier 
823fe1c642dSBill Krier 	name = names;
824fe1c642dSBill Krier 	for (i = 0; i < n_entry; ++i, name++) {
825fd9ee8b5Sjoyce mcintosh 		bzero(name, sizeof (struct mslsa_name_entry));
826fe1c642dSBill Krier 		sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
827fe1c642dSBill Krier 
828fe1c642dSBill Krier 		result = lsa_lookup_sid(sid, &account);
829fd9ee8b5Sjoyce mcintosh 		if ((result != NT_STATUS_SUCCESS) ||
830fd9ee8b5Sjoyce mcintosh 		    (account.a_name == NULL) || (*account.a_name == '\0')) {
831fd9ee8b5Sjoyce mcintosh 			account.a_type = SidTypeUnknown;
832fd9ee8b5Sjoyce mcintosh 			smb_sid_tostr(sid, sidstr);
833fd9ee8b5Sjoyce mcintosh 
834fd9ee8b5Sjoyce mcintosh 			if (NDR_MSTRING(mxa, sidstr,
835fd9ee8b5Sjoyce mcintosh 			    (ndr_mstring_t *)&name->name) == -1)
836fe1c642dSBill Krier 				goto lookup_sid_failed;
837fe1c642dSBill Krier 
838fd9ee8b5Sjoyce mcintosh 		} else {
839fe1c642dSBill Krier 			if (NDR_MSTRING(mxa, account.a_name,
840fd9ee8b5Sjoyce mcintosh 			    (ndr_mstring_t *)&name->name) == -1)
841fe1c642dSBill Krier 				goto lookup_sid_failed;
842fd9ee8b5Sjoyce mcintosh 
843fd9ee8b5Sjoyce mcintosh 			++n_mapped;
844fe1c642dSBill Krier 		}
845fd9ee8b5Sjoyce mcintosh 
846fe1c642dSBill Krier 		name->sid_name_use = account.a_type;
847fe1c642dSBill Krier 
848fe1c642dSBill Krier 		result = lsarpc_s_UpdateDomainTable(mxa, &account,
849fe1c642dSBill Krier 		    domain_table, &name->domain_ix);
850fd9ee8b5Sjoyce mcintosh 		if (result == -1)
851fe1c642dSBill Krier 			goto lookup_sid_failed;
852fe1c642dSBill Krier 
853fe1c642dSBill Krier 		smb_account_free(&account);
854fe1c642dSBill Krier 	}
855fe1c642dSBill Krier 
856fe1c642dSBill Krier 	param->domain_table = domain_table;
857fe1c642dSBill Krier 	param->name_table.n_entry = n_entry;
858fe1c642dSBill Krier 	param->name_table.entries = names;
859fd9ee8b5Sjoyce mcintosh 	param->mapped_count = n_mapped;
860fd9ee8b5Sjoyce mcintosh 
861fd9ee8b5Sjoyce mcintosh 	if (n_mapped == n_entry)
862fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_SUCCESS;
863fd9ee8b5Sjoyce mcintosh 	else if (n_mapped == 0)
864fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_NONE_MAPPED;
865fd9ee8b5Sjoyce mcintosh 	else
866fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_SOME_NOT_MAPPED;
867fe1c642dSBill Krier 
868fe1c642dSBill Krier 	return (NDR_DRC_OK);
869fe1c642dSBill Krier 
870fe1c642dSBill Krier lookup_sid_failed:
871fe1c642dSBill Krier 	smb_account_free(&account);
872fd9ee8b5Sjoyce mcintosh 	bzero(param, sizeof (struct mslsa_LookupSids));
873fd9ee8b5Sjoyce mcintosh 	return (NDR_DRC_FAULT_OUT_OF_MEMORY);
874fe1c642dSBill Krier }
875fe1c642dSBill Krier 
876fe1c642dSBill Krier /*
877fe1c642dSBill Krier  * lsarpc_s_UpdateDomainTable
878fe1c642dSBill Krier  *
879fe1c642dSBill Krier  * This routine is responsible for maintaining the domain table which
880fe1c642dSBill Krier  * will be returned from a SID lookup. Whenever a name is added to the
881fe1c642dSBill Krier  * name table, this function should be called with the corresponding
882fe1c642dSBill Krier  * domain name. If the domain information is not already in the table,
883fe1c642dSBill Krier  * it is added. On success return 0; Otherwise -1 is returned.
884fe1c642dSBill Krier  */
885fe1c642dSBill Krier static int
lsarpc_s_UpdateDomainTable(ndr_xa_t * mxa,smb_account_t * account,struct mslsa_domain_table * domain_table,DWORD * domain_idx)886fe1c642dSBill Krier lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
887fe1c642dSBill Krier     smb_account_t *account, struct mslsa_domain_table *domain_table,
888fe1c642dSBill Krier     DWORD *domain_idx)
889fe1c642dSBill Krier {
890fe1c642dSBill Krier 	struct mslsa_domain_entry *dentry;
891fe1c642dSBill Krier 	DWORD n_entry;
892fe1c642dSBill Krier 	DWORD i;
893fe1c642dSBill Krier 	int rc;
894fe1c642dSBill Krier 
895fe1c642dSBill Krier 	if (account->a_type == SidTypeUnknown ||
896fe1c642dSBill Krier 	    account->a_type == SidTypeInvalid) {
897fe1c642dSBill Krier 		/*
898fe1c642dSBill Krier 		 * These types don't need to reference an entry in the
899fe1c642dSBill Krier 		 * domain table. So return -1.
900fe1c642dSBill Krier 		 */
901fe1c642dSBill Krier 		*domain_idx = (DWORD)-1;
902fe1c642dSBill Krier 		return (0);
903fe1c642dSBill Krier 	}
904fe1c642dSBill Krier 
905fe1c642dSBill Krier 	if ((dentry = domain_table->entries) == NULL)
906fe1c642dSBill Krier 		return (-1);
907fe1c642dSBill Krier 
908fe1c642dSBill Krier 	if ((n_entry = domain_table->n_entry) >= MLSVC_DOMAIN_MAX)
909fe1c642dSBill Krier 		return (-1);
910fe1c642dSBill Krier 
911fe1c642dSBill Krier 	for (i = 0; i < n_entry; ++i) {
912fe1c642dSBill Krier 		if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid,
913fe1c642dSBill Krier 		    account->a_domsid)) {
914fe1c642dSBill Krier 			*domain_idx = i;
915fe1c642dSBill Krier 			return (0);
916fe1c642dSBill Krier 		}
917fe1c642dSBill Krier 	}
918fe1c642dSBill Krier 
919fe1c642dSBill Krier 	if (i == MLSVC_DOMAIN_MAX)
920fe1c642dSBill Krier 		return (-1);
921fe1c642dSBill Krier 
922fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, account->a_domain,
923fe1c642dSBill Krier 	    (ndr_mstring_t *)&dentry[i].domain_name);
924fe1c642dSBill Krier 	dentry[i].domain_sid =
925fe1c642dSBill Krier 	    (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid);
926fe1c642dSBill Krier 
927fe1c642dSBill Krier 	if (rc == -1 || dentry[i].domain_sid == NULL)
928fe1c642dSBill Krier 		return (-1);
929fe1c642dSBill Krier 
930fe1c642dSBill Krier 	++domain_table->n_entry;
931fe1c642dSBill Krier 	*domain_idx = i;
932fe1c642dSBill Krier 	return (0);
933fe1c642dSBill Krier }
934fe1c642dSBill Krier 
935fe1c642dSBill Krier /*
936fe1c642dSBill Krier  * lsarpc_s_LookupSids2
937fe1c642dSBill Krier  *
938fe1c642dSBill Krier  * Other than the use of lsar_lookup_sids2 and lsar_name_entry2, this
939fe1c642dSBill Krier  * is identical to lsarpc_s_LookupSids.
940fe1c642dSBill Krier  *
941fe1c642dSBill Krier  * Ignore lookup_level, it is reserved and should be zero.
942fe1c642dSBill Krier  */
943fe1c642dSBill Krier static int
lsarpc_s_LookupSids2(void * arg,ndr_xa_t * mxa)944fe1c642dSBill Krier lsarpc_s_LookupSids2(void *arg, ndr_xa_t *mxa)
945fe1c642dSBill Krier {
946fe1c642dSBill Krier 	struct lsar_lookup_sids2 *param = arg;
947fe1c642dSBill Krier 	struct lsar_name_entry2 *names;
948fe1c642dSBill Krier 	struct lsar_name_entry2 *name;
949fe1c642dSBill Krier 	struct mslsa_domain_table *domain_table;
950fe1c642dSBill Krier 	struct mslsa_domain_entry *domain_entry;
951fe1c642dSBill Krier 	smb_account_t account;
952fe1c642dSBill Krier 	smb_sid_t *sid;
953fe1c642dSBill Krier 	DWORD n_entry;
954fd9ee8b5Sjoyce mcintosh 	DWORD n_mapped;
955fd9ee8b5Sjoyce mcintosh 	char sidstr[SMB_SID_STRSZ];
956fe1c642dSBill Krier 	int result;
957fe1c642dSBill Krier 	int i;
958fe1c642dSBill Krier 
959fd9ee8b5Sjoyce mcintosh 	bzero(&account, sizeof (smb_account_t));
960fd9ee8b5Sjoyce mcintosh 	n_mapped = 0;
961fe1c642dSBill Krier 	n_entry = param->lup_sid_table.n_entry;
962fd9ee8b5Sjoyce mcintosh 
963fe1c642dSBill Krier 	names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry);
964fe1c642dSBill Krier 	domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
965fe1c642dSBill Krier 	domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
966fe1c642dSBill Krier 	    MLSVC_DOMAIN_MAX);
967fe1c642dSBill Krier 
968fd9ee8b5Sjoyce mcintosh 	if (names == NULL || domain_table == NULL || domain_entry == NULL)
969fd9ee8b5Sjoyce mcintosh 		goto lookup_sid_failed;
970fe1c642dSBill Krier 
971fe1c642dSBill Krier 	domain_table->entries = domain_entry;
972fe1c642dSBill Krier 	domain_table->n_entry = 0;
973fe1c642dSBill Krier 	domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
974fe1c642dSBill Krier 
975fe1c642dSBill Krier 	name = names;
976fe1c642dSBill Krier 	for (i = 0; i < n_entry; ++i, name++) {
977fe1c642dSBill Krier 		bzero(name, sizeof (struct lsar_name_entry2));
978fe1c642dSBill Krier 		sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
979fe1c642dSBill Krier 
980fe1c642dSBill Krier 		result = lsa_lookup_sid(sid, &account);
981fd9ee8b5Sjoyce mcintosh 		if ((result != NT_STATUS_SUCCESS) ||
982fd9ee8b5Sjoyce mcintosh 		    (account.a_name == NULL) || (*account.a_name == '\0')) {
983fd9ee8b5Sjoyce mcintosh 			account.a_type = SidTypeUnknown;
984fd9ee8b5Sjoyce mcintosh 			smb_sid_tostr(sid, sidstr);
985fd9ee8b5Sjoyce mcintosh 
986fd9ee8b5Sjoyce mcintosh 			if (NDR_MSTRING(mxa, sidstr,
987fd9ee8b5Sjoyce mcintosh 			    (ndr_mstring_t *)&name->name) == -1)
988fe1c642dSBill Krier 				goto lookup_sid_failed;
989fe1c642dSBill Krier 
990fd9ee8b5Sjoyce mcintosh 		} else {
991fe1c642dSBill Krier 			if (NDR_MSTRING(mxa, account.a_name,
992fd9ee8b5Sjoyce mcintosh 			    (ndr_mstring_t *)&name->name) == -1)
993fe1c642dSBill Krier 				goto lookup_sid_failed;
994fd9ee8b5Sjoyce mcintosh 
995fd9ee8b5Sjoyce mcintosh 			++n_mapped;
996fe1c642dSBill Krier 		}
997fd9ee8b5Sjoyce mcintosh 
998fe1c642dSBill Krier 		name->sid_name_use = account.a_type;
999fe1c642dSBill Krier 
1000fe1c642dSBill Krier 		result = lsarpc_s_UpdateDomainTable(mxa, &account,
1001fe1c642dSBill Krier 		    domain_table, &name->domain_ix);
1002fd9ee8b5Sjoyce mcintosh 		if (result == -1)
1003fe1c642dSBill Krier 			goto lookup_sid_failed;
1004fe1c642dSBill Krier 
1005fe1c642dSBill Krier 		smb_account_free(&account);
1006fe1c642dSBill Krier 	}
1007fe1c642dSBill Krier 
1008fe1c642dSBill Krier 	param->domain_table = domain_table;
1009fe1c642dSBill Krier 	param->name_table.n_entry = n_entry;
1010fe1c642dSBill Krier 	param->name_table.entries = names;
1011fd9ee8b5Sjoyce mcintosh 	param->mapped_count = n_mapped;
1012fd9ee8b5Sjoyce mcintosh 
1013fd9ee8b5Sjoyce mcintosh 	if (n_mapped == n_entry)
1014fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_SUCCESS;
1015fd9ee8b5Sjoyce mcintosh 	else if (n_mapped == 0)
1016fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_NONE_MAPPED;
1017fd9ee8b5Sjoyce mcintosh 	else
1018fd9ee8b5Sjoyce mcintosh 		param->status = NT_STATUS_SOME_NOT_MAPPED;
1019fe1c642dSBill Krier 
1020fe1c642dSBill Krier 	return (NDR_DRC_OK);
1021fe1c642dSBill Krier 
1022fe1c642dSBill Krier lookup_sid_failed:
1023fe1c642dSBill Krier 	smb_account_free(&account);
1024fd9ee8b5Sjoyce mcintosh 	bzero(param, sizeof (struct lsar_lookup_sids2));
1025fd9ee8b5Sjoyce mcintosh 	return (NDR_DRC_FAULT_OUT_OF_MEMORY);
1026fe1c642dSBill Krier }
1027fe1c642dSBill Krier 
1028fe1c642dSBill Krier /*
1029fe1c642dSBill Krier  * LookupSids3 is only valid on domain controllers.
1030fe1c642dSBill Krier  * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1031fe1c642dSBill Krier  */
1032fe1c642dSBill Krier /*ARGSUSED*/
1033fe1c642dSBill Krier static int
lsarpc_s_LookupSids3(void * arg,ndr_xa_t * mxa)1034fe1c642dSBill Krier lsarpc_s_LookupSids3(void *arg, ndr_xa_t *mxa)
1035fe1c642dSBill Krier {
1036fe1c642dSBill Krier 	struct lsar_lookup_sids3 *param = arg;
1037fe1c642dSBill Krier 
1038fe1c642dSBill Krier 	bzero(param, sizeof (struct lsar_lookup_sids3));
1039fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1040fe1c642dSBill Krier 	return (NDR_DRC_OK);
1041fe1c642dSBill Krier }
1042fe1c642dSBill Krier 
1043fe1c642dSBill Krier /*
1044fe1c642dSBill Krier  * lsarpc_s_LookupNames2
1045fe1c642dSBill Krier  *
1046fe1c642dSBill Krier  * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1047fe1c642dSBill Krier  * is identical to lsarpc_s_LookupNames.
1048fe1c642dSBill Krier  *
1049fe1c642dSBill Krier  * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1050fe1c642dSBill Krier  * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1051fe1c642dSBill Krier  */
1052fe1c642dSBill Krier static int
lsarpc_s_LookupNames2(void * arg,ndr_xa_t * mxa)1053fe1c642dSBill Krier lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
1054fe1c642dSBill Krier {
1055fe1c642dSBill Krier 	struct lsar_LookupNames2 *param = arg;
1056fe1c642dSBill Krier 	struct lsar_rid_entry2 *rids;
1057fe1c642dSBill Krier 	struct mslsa_domain_table *domain_table;
1058fe1c642dSBill Krier 	struct mslsa_domain_entry *domain_entry;
1059fe1c642dSBill Krier 	smb_account_t account;
1060fe1c642dSBill Krier 	uint32_t status;
1061fe1c642dSBill Krier 	char *accname;
1062fe1c642dSBill Krier 	int rc = 0;
1063fe1c642dSBill Krier 
1064fe1c642dSBill Krier 	if (param->name_table->n_entry != 1)
1065fe1c642dSBill Krier 		return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1066fe1c642dSBill Krier 
1067fe1c642dSBill Krier 	if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1068fe1c642dSBill Krier 	    param->lookup_level != LSA_LOOKUP_WKSTA) {
1069fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames2));
1070fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1071fe1c642dSBill Krier 		return (NDR_DRC_OK);
1072fe1c642dSBill Krier 	}
1073fe1c642dSBill Krier 
1074fe1c642dSBill Krier 	rids = NDR_NEW(mxa, struct lsar_rid_entry2);
1075fe1c642dSBill Krier 	domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1076fe1c642dSBill Krier 	domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1077fe1c642dSBill Krier 
1078fe1c642dSBill Krier 	if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
1079fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames2));
1080fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1081fe1c642dSBill Krier 		return (NDR_DRC_OK);
1082fe1c642dSBill Krier 	}
1083fe1c642dSBill Krier 
1084fe1c642dSBill Krier 	accname = (char *)param->name_table->names->str;
1085fe1c642dSBill Krier 	status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1086fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS) {
1087fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames2));
1088fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
1089fe1c642dSBill Krier 		return (NDR_DRC_OK);
1090fe1c642dSBill Krier 	}
1091fe1c642dSBill Krier 
1092fe1c642dSBill Krier 	/*
1093fe1c642dSBill Krier 	 * Set up the rid table.
1094fe1c642dSBill Krier 	 */
1095fe1c642dSBill Krier 	bzero(rids, sizeof (struct lsar_rid_entry2));
1096fe1c642dSBill Krier 	rids[0].sid_name_use = account.a_type;
1097fe1c642dSBill Krier 	rids[0].rid = account.a_rid;
1098fe1c642dSBill Krier 	rids[0].domain_index = 0;
1099fe1c642dSBill Krier 	param->translated_sids.n_entry = 1;
1100fe1c642dSBill Krier 	param->translated_sids.rids = rids;
1101fe1c642dSBill Krier 
1102fe1c642dSBill Krier 	/*
1103fe1c642dSBill Krier 	 * Set up the domain table.
1104fe1c642dSBill Krier 	 */
1105fe1c642dSBill Krier 	domain_table->entries = domain_entry;
1106fe1c642dSBill Krier 	domain_table->n_entry = 1;
1107fe1c642dSBill Krier 	domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1108fe1c642dSBill Krier 
1109fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, account.a_domain,
1110fe1c642dSBill Krier 	    (ndr_mstring_t *)&domain_entry->domain_name);
1111fe1c642dSBill Krier 
1112fe1c642dSBill Krier 	domain_entry->domain_sid =
1113fe1c642dSBill Krier 	    (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1114fe1c642dSBill Krier 
1115fe1c642dSBill Krier 	if (rc == -1 || domain_entry->domain_sid == NULL) {
1116fe1c642dSBill Krier 		smb_account_free(&account);
1117fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames2));
1118fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1119fe1c642dSBill Krier 		return (NDR_DRC_OK);
1120fe1c642dSBill Krier 	}
1121fe1c642dSBill Krier 
1122fe1c642dSBill Krier 	param->domain_table = domain_table;
1123fe1c642dSBill Krier 	param->mapped_count = 1;
1124fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
1125fe1c642dSBill Krier 
1126fe1c642dSBill Krier 	smb_account_free(&account);
1127fe1c642dSBill Krier 	return (NDR_DRC_OK);
1128fe1c642dSBill Krier }
1129fe1c642dSBill Krier 
1130fe1c642dSBill Krier /*
1131fe1c642dSBill Krier  * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1132fe1c642dSBill Krier  * is identical to lsarpc_s_LookupNames.
1133fe1c642dSBill Krier  *
1134fe1c642dSBill Krier  * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1135fe1c642dSBill Krier  * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1136fe1c642dSBill Krier  */
1137fe1c642dSBill Krier static int
lsarpc_s_LookupNames3(void * arg,ndr_xa_t * mxa)1138fe1c642dSBill Krier lsarpc_s_LookupNames3(void *arg, ndr_xa_t *mxa)
1139fe1c642dSBill Krier {
1140fe1c642dSBill Krier 	struct lsar_LookupNames3	*param = arg;
1141fe1c642dSBill Krier 	struct lsar_translated_sid_ex2	*sids;
1142fe1c642dSBill Krier 	struct mslsa_domain_table	*domain_table;
1143fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
1144fe1c642dSBill Krier 	smb_account_t			account;
1145fe1c642dSBill Krier 	uint32_t			status;
1146fe1c642dSBill Krier 	char				*accname;
1147fe1c642dSBill Krier 	int				rc = 0;
1148fe1c642dSBill Krier 
1149fe1c642dSBill Krier 	if (param->name_table->n_entry != 1)
1150fe1c642dSBill Krier 		return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1151fe1c642dSBill Krier 
1152fe1c642dSBill Krier 	if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1153fe1c642dSBill Krier 	    param->lookup_level != LSA_LOOKUP_WKSTA) {
1154fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames3));
1155fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1156fe1c642dSBill Krier 		return (NDR_DRC_OK);
1157fe1c642dSBill Krier 	}
1158fe1c642dSBill Krier 
1159fe1c642dSBill Krier 	sids = NDR_NEW(mxa, struct lsar_translated_sid_ex2);
1160fe1c642dSBill Krier 	domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1161fe1c642dSBill Krier 	domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1162fe1c642dSBill Krier 
1163fe1c642dSBill Krier 	if (sids == NULL || domain_table == NULL || domain_entry == NULL) {
1164fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames3));
1165fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1166fe1c642dSBill Krier 		return (NDR_DRC_OK);
1167fe1c642dSBill Krier 	}
1168fe1c642dSBill Krier 
1169fe1c642dSBill Krier 	accname = (char *)param->name_table->names->str;
1170fe1c642dSBill Krier 	status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1171fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS) {
1172fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames3));
1173fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
1174fe1c642dSBill Krier 		return (NDR_DRC_OK);
1175fe1c642dSBill Krier 	}
1176fe1c642dSBill Krier 
1177fe1c642dSBill Krier 	/*
1178fe1c642dSBill Krier 	 * Set up the SID table.
1179fe1c642dSBill Krier 	 */
1180fe1c642dSBill Krier 	bzero(sids, sizeof (struct lsar_translated_sid_ex2));
1181fe1c642dSBill Krier 	sids[0].sid_name_use = account.a_type;
1182fe1c642dSBill Krier 	sids[0].sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_sid);
1183fe1c642dSBill Krier 	sids[0].domain_index = 0;
1184fe1c642dSBill Krier 	param->translated_sids.n_entry = 1;
1185fe1c642dSBill Krier 	param->translated_sids.sids = sids;
1186fe1c642dSBill Krier 
1187fe1c642dSBill Krier 	/*
1188fe1c642dSBill Krier 	 * Set up the domain table.
1189fe1c642dSBill Krier 	 */
1190fe1c642dSBill Krier 	domain_table->entries = domain_entry;
1191fe1c642dSBill Krier 	domain_table->n_entry = 1;
1192fe1c642dSBill Krier 	domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1193fe1c642dSBill Krier 
1194fe1c642dSBill Krier 	rc = NDR_MSTRING(mxa, account.a_domain,
1195fe1c642dSBill Krier 	    (ndr_mstring_t *)&domain_entry->domain_name);
1196fe1c642dSBill Krier 
1197fe1c642dSBill Krier 	domain_entry->domain_sid =
1198fe1c642dSBill Krier 	    (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1199fe1c642dSBill Krier 
1200fe1c642dSBill Krier 	if (rc == -1 || domain_entry->domain_sid == NULL) {
1201fe1c642dSBill Krier 		smb_account_free(&account);
1202fe1c642dSBill Krier 		bzero(param, sizeof (struct lsar_LookupNames3));
1203fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1204fe1c642dSBill Krier 		return (NDR_DRC_OK);
1205fe1c642dSBill Krier 	}
1206fe1c642dSBill Krier 
1207fe1c642dSBill Krier 	param->domain_table = domain_table;
1208fe1c642dSBill Krier 	param->mapped_count = 1;
1209fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
1210fe1c642dSBill Krier 
1211fe1c642dSBill Krier 	smb_account_free(&account);
1212fe1c642dSBill Krier 	return (NDR_DRC_OK);
1213fe1c642dSBill Krier }
1214fe1c642dSBill Krier 
1215fe1c642dSBill Krier /*
1216fe1c642dSBill Krier  * LookupNames4 is only valid on domain controllers.
1217fe1c642dSBill Krier  * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1218fe1c642dSBill Krier  */
1219fe1c642dSBill Krier /*ARGSUSED*/
1220fe1c642dSBill Krier static int
lsarpc_s_LookupNames4(void * arg,ndr_xa_t * mxa)1221fe1c642dSBill Krier lsarpc_s_LookupNames4(void *arg, ndr_xa_t *mxa)
1222fe1c642dSBill Krier {
1223fe1c642dSBill Krier 	struct lsar_LookupNames4 *param = arg;
1224fe1c642dSBill Krier 
1225fe1c642dSBill Krier 	bzero(param, sizeof (struct lsar_LookupNames4));
1226fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1227fe1c642dSBill Krier 	return (NDR_DRC_OK);
1228fe1c642dSBill Krier }
1229fe1c642dSBill Krier 
1230fe1c642dSBill Krier /*
1231fe1c642dSBill Krier  * There is a bug in the way that ndrgen and the marshalling code handles
1232fe1c642dSBill Krier  * unions so we need to fix some of the data offsets at runtime. The
1233fe1c642dSBill Krier  * following macros and the fixup functions handle the corrections.
1234fe1c642dSBill Krier  */
1235fe1c642dSBill Krier 
1236fe1c642dSBill Krier DECL_FIXUP_STRUCT(mslsa_PolicyInfoResUnion);
1237fe1c642dSBill Krier DECL_FIXUP_STRUCT(mslsa_PolicyInfoRes);
1238fe1c642dSBill Krier DECL_FIXUP_STRUCT(mslsa_QueryInfoPolicy);
1239fe1c642dSBill Krier void
fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy * val)1240fe1c642dSBill Krier fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy *val)
1241fe1c642dSBill Krier {
1242fe1c642dSBill Krier 	unsigned short size1 = 0;
1243fe1c642dSBill Krier 	unsigned short size2 = 0;
1244fe1c642dSBill Krier 	unsigned short size3 = 0;
1245fe1c642dSBill Krier 
1246fe1c642dSBill Krier 	switch (val->info_class) {
1247fe1c642dSBill Krier 		case MSLSA_POLICY_AUDIT_EVENTS_INFO:
1248fe1c642dSBill Krier 			size1 = sizeof (struct mslsa_AuditEventsInfo);
1249fe1c642dSBill Krier 			break;
1250fe1c642dSBill Krier 
1251fe1c642dSBill Krier 		case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
1252fe1c642dSBill Krier 			size1 = sizeof (struct mslsa_PrimaryDomainInfo);
1253fe1c642dSBill Krier 			break;
1254fe1c642dSBill Krier 
1255fe1c642dSBill Krier 		case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
1256fe1c642dSBill Krier 			size1 = sizeof (struct mslsa_AccountDomainInfo);
1257fe1c642dSBill Krier 			break;
1258fe1c642dSBill Krier 
1259fe1c642dSBill Krier 		case MSLSA_POLICY_SERVER_ROLE_INFO:
1260fe1c642dSBill Krier 			size1 = sizeof (struct mslsa_ServerRoleInfo);
1261fe1c642dSBill Krier 			break;
1262fe1c642dSBill Krier 
1263fe1c642dSBill Krier 		case MSLSA_POLICY_DNS_DOMAIN_INFO:
1264fe1c642dSBill Krier 			size1 = sizeof (struct mslsa_DnsDomainInfo);
1265fe1c642dSBill Krier 			break;
1266fe1c642dSBill Krier 
1267fe1c642dSBill Krier 		default:
1268fe1c642dSBill Krier 			return;
1269fe1c642dSBill Krier 	};
1270fe1c642dSBill Krier 
1271fe1c642dSBill Krier 	size2 = size1 + (2 * sizeof (DWORD));
1272fe1c642dSBill Krier 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1273fe1c642dSBill Krier 
1274fe1c642dSBill Krier 	FIXUP_PDU_SIZE(mslsa_PolicyInfoResUnion, size1);
1275fe1c642dSBill Krier 	FIXUP_PDU_SIZE(mslsa_PolicyInfoRes, size2);
1276fe1c642dSBill Krier 	FIXUP_PDU_SIZE(mslsa_QueryInfoPolicy, size3);
1277fe1c642dSBill Krier }
1278