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
lsarpc_initialize(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
lsarpc_call_stub(ndr_xa_t * mxa)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
lsarpc_s_OpenDomainHandle(void * arg,ndr_xa_t * mxa)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, ¶m->domain_handle, sizeof (mslsa_handle_t));
169 param->status = NT_STATUS_SUCCESS;
170 } else {
171 bzero(¶m->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
lsarpc_s_CloseHandle(void * arg,ndr_xa_t * mxa)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 *)¶m->handle;
191
192 ndr_hdfree(mxa, id);
193
194 bzero(¶m->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
lsarpc_s_QuerySecurityObject(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumAccounts(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumTrustedDomain(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumTrustedDomainsEx(void * arg,ndr_xa_t * mxa)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
lsarpc_s_OpenAccount(void * arg,ndr_xa_t * mxa)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 *)¶m->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, ¶m->account_handle, sizeof (mslsa_handle_t));
341 param->status = NT_STATUS_SUCCESS;
342 } else {
343 bzero(¶m->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
lsarpc_s_EnumPrivsAccount(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivValue(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivName(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivDisplayName(void * arg,ndr_xa_t * mxa)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
lsarpc_s_CreateSecret(void * arg,ndr_xa_t * mxa)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 *)¶m->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(¶m->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
lsarpc_s_OpenSecret(void * arg,ndr_xa_t * mxa)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 *)¶m->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(¶m->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
lsarpc_s_GetConnectedUser(void * arg,ndr_xa_t * mxa)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
lsarpc_s_QueryInfoPolicy(void * arg,ndr_xa_t * mxa)572 lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa)
573 {
574 struct mslsa_QueryInfoPolicy *param = arg;
575 union mslsa_PolicyInfoResUnion *ru = ¶m->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
lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo * info,ndr_xa_t * mxa)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
lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo * info,ndr_xa_t * mxa)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
lsarpc_s_LookupNames(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupSids(void * arg,ndr_xa_t * mxa)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
lsarpc_s_UpdateDomainTable(ndr_xa_t * mxa,smb_account_t * account,struct mslsa_domain_table * domain_table,DWORD * domain_idx)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
lsarpc_s_LookupSids2(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupSids3(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupNames2(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupNames3(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupNames4(void * arg,ndr_xa_t * mxa)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
fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy * val)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