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