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