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