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 <libmlrpc/libmlrpc.h>
37 #include <smbsrv/libsmb.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 * Note: MacOS uses this, whether we're a domain member or not.
518 */
519 static int
lsarpc_s_GetConnectedUser(void * arg,ndr_xa_t * mxa)520 lsarpc_s_GetConnectedUser(void *arg, ndr_xa_t *mxa)
521 {
522 struct mslsa_GetConnectedUser *param = arg;
523 smb_netuserinfo_t *user = mxa->pipe->np_user;
524 DWORD status = NT_STATUS_SUCCESS;
525 int rc1;
526 int rc2;
527
528 param->owner = NDR_NEW(mxa, struct mslsa_string_desc);
529 param->domain = NDR_NEW(mxa, struct mslsa_DomainName);
530 if (param->owner == NULL || param->domain == NULL) {
531 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
532 param->status = status;
533 return (NDR_DRC_OK);
534 }
535
536 param->domain->name = NDR_NEW(mxa, struct mslsa_string_desc);
537 if (param->domain->name == NULL) {
538 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
539 param->status = status;
540 return (NDR_DRC_OK);
541 }
542
543 rc1 = NDR_MSTRING(mxa, user->ui_account,
544 (ndr_mstring_t *)param->owner);
545 rc2 = NDR_MSTRING(mxa, user->ui_domain,
546 (ndr_mstring_t *)param->domain->name);
547
548 if (rc1 == -1 || rc2 == -1)
549 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
550
551 param->status = status;
552 return (NDR_DRC_OK);
553 }
554
555
556 /*
557 * lsarpc_s_QueryInfoPolicy
558 *
559 * This is the server side function for handling LSA information policy
560 * queries. Currently, we only support primary domain and account
561 * domain queries. This is just a front end to switch on the request
562 * and hand it off to the appropriate function to actually deal with
563 * obtaining and building the response.
564 */
565 static int
lsarpc_s_QueryInfoPolicy(void * arg,ndr_xa_t * mxa)566 lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa)
567 {
568 struct mslsa_QueryInfoPolicy *param = arg;
569 union mslsa_PolicyInfoResUnion *ru = ¶m->ru;
570 int security_mode;
571 DWORD status;
572
573 param->switch_value = param->info_class;
574
575 switch (param->info_class) {
576 case MSLSA_POLICY_AUDIT_EVENTS_INFO:
577 ru->audit_events.enabled = 0;
578 ru->audit_events.count = 1;
579 ru->audit_events.settings
580 = NDR_MALLOC(mxa, sizeof (DWORD));
581 bzero(ru->audit_events.settings, sizeof (DWORD));
582 status = NT_STATUS_SUCCESS;
583 break;
584
585 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
586 status = lsarpc_s_PrimaryDomainInfo(&ru->pd_info, mxa);
587 break;
588
589 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
590 status = lsarpc_s_AccountDomainInfo(&ru->ad_info, mxa);
591 break;
592
593 case MSLSA_POLICY_SERVER_ROLE_INFO:
594 security_mode = smb_config_get_secmode();
595
596 if (security_mode == SMB_SECMODE_DOMAIN)
597 ru->server_role.role = LSA_ROLE_MEMBER_SERVER;
598 else
599 ru->server_role.role = LSA_ROLE_STANDALONE_SERVER;
600
601 ru->server_role.pad = 0;
602 status = NT_STATUS_SUCCESS;
603 break;
604
605 default:
606 bzero(param, sizeof (struct mslsa_QueryInfoPolicy));
607 param->status = NT_SC_ERROR(NT_STATUS_INVALID_INFO_CLASS);
608 return (NDR_DRC_OK);
609 }
610
611 if (status != NT_STATUS_SUCCESS)
612 param->status = NT_SC_ERROR(status);
613 else
614 param->status = NT_STATUS_SUCCESS;
615 param->address = (DWORD)(uintptr_t)ru;
616
617 return (NDR_DRC_OK);
618 }
619
620
621 /*
622 * lsarpc_s_PrimaryDomainInfo
623 *
624 * Service primary domain policy queries. In domain mode, return the
625 * primary domain name and SID. In workgroup mode, return the local
626 * hostname and local domain SID.
627 *
628 * Note: info is zeroed on entry to ensure the SID and name do not
629 * contain spurious values if an error is returned.
630 */
631 static DWORD
lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo * info,ndr_xa_t * mxa)632 lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *info,
633 ndr_xa_t *mxa)
634 {
635 smb_domain_t di;
636 boolean_t found;
637 int rc;
638
639 bzero(info, sizeof (struct mslsa_PrimaryDomainInfo));
640
641 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
642 found = smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di);
643 else
644 found = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &di);
645
646 if (!found)
647 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
648
649 rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
650 info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
651
652 if ((rc == -1) || (info->sid == NULL))
653 return (NT_STATUS_NO_MEMORY);
654
655 return (NT_STATUS_SUCCESS);
656 }
657
658
659 /*
660 * lsarpc_s_AccountDomainInfo
661 *
662 * Service account domain policy queries. We return our local domain
663 * information so that the client knows who to query for information
664 * on local names and SIDs. The domain name is the local hostname.
665 *
666 * Note: info is zeroed on entry to ensure the SID and name do not
667 * contain spurious values if an error is returned.
668 */
669 static DWORD
lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo * info,ndr_xa_t * mxa)670 lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *info,
671 ndr_xa_t *mxa)
672 {
673 smb_domain_t di;
674 int rc;
675
676 bzero(info, sizeof (struct mslsa_AccountDomainInfo));
677
678 if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
679 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
680
681 rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
682 info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
683
684 if ((rc == -1) || (info->sid == NULL))
685 return (NT_STATUS_NO_MEMORY);
686
687 return (NT_STATUS_SUCCESS);
688 }
689
690 /*
691 * lsarpc_s_LookupNames
692 *
693 * This is the service side function for handling name lookup requests.
694 * Currently, we only support lookups of a single name. This is also a
695 * pass through interface so all we do is act as a proxy between the
696 * client and the DC.
697 */
698 static int
lsarpc_s_LookupNames(void * arg,ndr_xa_t * mxa)699 lsarpc_s_LookupNames(void *arg, ndr_xa_t *mxa)
700 {
701 struct mslsa_LookupNames *param = arg;
702 struct mslsa_rid_entry *rids;
703 struct mslsa_domain_table *domain_table;
704 struct mslsa_domain_entry *domain_entry;
705 smb_account_t account;
706 uint32_t status;
707 char *accname;
708 int rc = 0;
709
710 if (param->name_table->n_entry != 1)
711 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
712
713 rids = NDR_NEW(mxa, struct mslsa_rid_entry);
714 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
715 domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
716
717 if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
718 bzero(param, sizeof (struct mslsa_LookupNames));
719 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
720 return (NDR_DRC_OK);
721 }
722
723 accname = (char *)param->name_table->names->str;
724 status = lsa_lookup_name(accname, SidTypeUnknown, &account);
725 if (status != NT_STATUS_SUCCESS) {
726 bzero(param, sizeof (struct mslsa_LookupNames));
727 param->status = NT_SC_ERROR(status);
728 return (NDR_DRC_OK);
729 }
730
731 /*
732 * Set up the rid table.
733 */
734 rids[0].sid_name_use = account.a_type;
735 rids[0].rid = account.a_rid;
736 rids[0].domain_index = 0;
737 param->translated_sids.n_entry = 1;
738 param->translated_sids.rids = rids;
739
740 /*
741 * Set up the domain table.
742 */
743 domain_table->entries = domain_entry;
744 domain_table->n_entry = 1;
745 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
746
747 rc = NDR_MSTRING(mxa, account.a_domain,
748 (ndr_mstring_t *)&domain_entry->domain_name);
749 domain_entry->domain_sid =
750 (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
751
752 if (rc == -1 || domain_entry->domain_sid == NULL) {
753 smb_account_free(&account);
754 bzero(param, sizeof (struct mslsa_LookupNames));
755 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
756 return (NDR_DRC_OK);
757 }
758
759 param->domain_table = domain_table;
760 param->mapped_count = 1;
761 param->status = NT_STATUS_SUCCESS;
762
763 smb_account_free(&account);
764 return (NDR_DRC_OK);
765 }
766
767 /*
768 * lsarpc_s_LookupSids
769 *
770 * This is the service side function for handling sid lookup requests.
771 * We have to set up both the name table and the domain table in the
772 * response. For each SID, we check for UNIX domain (local lookup) or
773 * NT domain (DC lookup) and call the appropriate lookup function. This
774 * should resolve the SID to a name. Then we need to update the domain
775 * table and make the name entry point at the appropriate domain table
776 * entry.
777 *
778 *
779 * This RPC should behave as if LookupOptions is LSA_LOOKUP_OPT_ALL and
780 * ClientRevision is LSA_CLIENT_REVISION_NT.
781 *
782 * On success return 0. Otherwise return an RPC specific error code.
783 */
784
785 static int
lsarpc_s_LookupSids(void * arg,ndr_xa_t * mxa)786 lsarpc_s_LookupSids(void *arg, ndr_xa_t *mxa)
787 {
788 struct mslsa_LookupSids *param = arg;
789 struct mslsa_domain_table *domain_table;
790 struct mslsa_domain_entry *domain_entry;
791 struct mslsa_name_entry *names;
792 struct mslsa_name_entry *name;
793 smb_account_t account;
794 smb_sid_t *sid;
795 DWORD n_entry;
796 DWORD n_mapped;
797 char sidstr[SMB_SID_STRSZ];
798 int result;
799 int i;
800
801 bzero(&account, sizeof (smb_account_t));
802 n_mapped = 0;
803 n_entry = param->lup_sid_table.n_entry;
804
805 names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry);
806 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
807 domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
808 MLSVC_DOMAIN_MAX);
809
810 if (names == NULL || domain_table == NULL || domain_entry == NULL)
811 goto lookup_sid_failed;
812
813 domain_table->entries = domain_entry;
814 domain_table->n_entry = 0;
815 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
816
817 name = names;
818 for (i = 0; i < n_entry; ++i, name++) {
819 bzero(name, sizeof (struct mslsa_name_entry));
820 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
821
822 result = lsa_lookup_sid(sid, &account);
823 if ((result != NT_STATUS_SUCCESS) ||
824 (account.a_name == NULL) || (*account.a_name == '\0')) {
825 account.a_type = SidTypeUnknown;
826 smb_sid_tostr(sid, sidstr);
827
828 if (NDR_MSTRING(mxa, sidstr,
829 (ndr_mstring_t *)&name->name) == -1)
830 goto lookup_sid_failed;
831
832 } else {
833 if (NDR_MSTRING(mxa, account.a_name,
834 (ndr_mstring_t *)&name->name) == -1)
835 goto lookup_sid_failed;
836
837 ++n_mapped;
838 }
839
840 name->sid_name_use = account.a_type;
841
842 result = lsarpc_s_UpdateDomainTable(mxa, &account,
843 domain_table, &name->domain_ix);
844 if (result == -1)
845 goto lookup_sid_failed;
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_mapped;
854
855 if (n_mapped == n_entry)
856 param->status = NT_STATUS_SUCCESS;
857 else if (n_mapped == 0)
858 param->status = NT_STATUS_NONE_MAPPED;
859 else
860 param->status = NT_STATUS_SOME_NOT_MAPPED;
861
862 return (NDR_DRC_OK);
863
864 lookup_sid_failed:
865 smb_account_free(&account);
866 bzero(param, sizeof (struct mslsa_LookupSids));
867 return (NDR_DRC_FAULT_OUT_OF_MEMORY);
868 }
869
870 /*
871 * lsarpc_s_UpdateDomainTable
872 *
873 * This routine is responsible for maintaining the domain table which
874 * will be returned from a SID lookup. Whenever a name is added to the
875 * name table, this function should be called with the corresponding
876 * domain name. If the domain information is not already in the table,
877 * it is added. On success return 0; Otherwise -1 is returned.
878 */
879 static int
lsarpc_s_UpdateDomainTable(ndr_xa_t * mxa,smb_account_t * account,struct mslsa_domain_table * domain_table,DWORD * domain_idx)880 lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
881 smb_account_t *account, struct mslsa_domain_table *domain_table,
882 DWORD *domain_idx)
883 {
884 struct mslsa_domain_entry *dentry;
885 DWORD n_entry;
886 DWORD i;
887 int rc;
888
889 if (account->a_type == SidTypeUnknown ||
890 account->a_type == SidTypeInvalid) {
891 /*
892 * These types don't need to reference an entry in the
893 * domain table. So return -1.
894 */
895 *domain_idx = (DWORD)-1;
896 return (0);
897 }
898
899 if ((dentry = domain_table->entries) == NULL)
900 return (-1);
901
902 if ((n_entry = domain_table->n_entry) >= MLSVC_DOMAIN_MAX)
903 return (-1);
904
905 for (i = 0; i < n_entry; ++i) {
906 if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid,
907 account->a_domsid)) {
908 *domain_idx = i;
909 return (0);
910 }
911 }
912
913 if (i == MLSVC_DOMAIN_MAX)
914 return (-1);
915
916 rc = NDR_MSTRING(mxa, account->a_domain,
917 (ndr_mstring_t *)&dentry[i].domain_name);
918 dentry[i].domain_sid =
919 (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid);
920
921 if (rc == -1 || dentry[i].domain_sid == NULL)
922 return (-1);
923
924 ++domain_table->n_entry;
925 *domain_idx = i;
926 return (0);
927 }
928
929 /*
930 * lsarpc_s_LookupSids2
931 *
932 * Other than the use of lsar_lookup_sids2 and lsar_name_entry2, this
933 * is identical to lsarpc_s_LookupSids.
934 *
935 * Ignore lookup_level, it is reserved and should be zero.
936 */
937 static int
lsarpc_s_LookupSids2(void * arg,ndr_xa_t * mxa)938 lsarpc_s_LookupSids2(void *arg, ndr_xa_t *mxa)
939 {
940 struct lsar_lookup_sids2 *param = arg;
941 struct lsar_name_entry2 *names;
942 struct lsar_name_entry2 *name;
943 struct mslsa_domain_table *domain_table;
944 struct mslsa_domain_entry *domain_entry;
945 smb_account_t account;
946 smb_sid_t *sid;
947 DWORD n_entry;
948 DWORD n_mapped;
949 char sidstr[SMB_SID_STRSZ];
950 int result;
951 int i;
952
953 bzero(&account, sizeof (smb_account_t));
954 n_mapped = 0;
955 n_entry = param->lup_sid_table.n_entry;
956
957 names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry);
958 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
959 domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
960 MLSVC_DOMAIN_MAX);
961
962 if (names == NULL || domain_table == NULL || domain_entry == NULL)
963 goto lookup_sid_failed;
964
965 domain_table->entries = domain_entry;
966 domain_table->n_entry = 0;
967 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
968
969 name = names;
970 for (i = 0; i < n_entry; ++i, name++) {
971 bzero(name, sizeof (struct lsar_name_entry2));
972 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
973
974 result = lsa_lookup_sid(sid, &account);
975 if ((result != NT_STATUS_SUCCESS) ||
976 (account.a_name == NULL) || (*account.a_name == '\0')) {
977 account.a_type = SidTypeUnknown;
978 smb_sid_tostr(sid, sidstr);
979
980 if (NDR_MSTRING(mxa, sidstr,
981 (ndr_mstring_t *)&name->name) == -1)
982 goto lookup_sid_failed;
983
984 } else {
985 if (NDR_MSTRING(mxa, account.a_name,
986 (ndr_mstring_t *)&name->name) == -1)
987 goto lookup_sid_failed;
988
989 ++n_mapped;
990 }
991
992 name->sid_name_use = account.a_type;
993
994 result = lsarpc_s_UpdateDomainTable(mxa, &account,
995 domain_table, &name->domain_ix);
996 if (result == -1)
997 goto lookup_sid_failed;
998
999 smb_account_free(&account);
1000 }
1001
1002 param->domain_table = domain_table;
1003 param->name_table.n_entry = n_entry;
1004 param->name_table.entries = names;
1005 param->mapped_count = n_mapped;
1006
1007 if (n_mapped == n_entry)
1008 param->status = NT_STATUS_SUCCESS;
1009 else if (n_mapped == 0)
1010 param->status = NT_STATUS_NONE_MAPPED;
1011 else
1012 param->status = NT_STATUS_SOME_NOT_MAPPED;
1013
1014 return (NDR_DRC_OK);
1015
1016 lookup_sid_failed:
1017 smb_account_free(&account);
1018 bzero(param, sizeof (struct lsar_lookup_sids2));
1019 return (NDR_DRC_FAULT_OUT_OF_MEMORY);
1020 }
1021
1022 /*
1023 * LookupSids3 is only valid on domain controllers.
1024 * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1025 */
1026 /*ARGSUSED*/
1027 static int
lsarpc_s_LookupSids3(void * arg,ndr_xa_t * mxa)1028 lsarpc_s_LookupSids3(void *arg, ndr_xa_t *mxa)
1029 {
1030 struct lsar_lookup_sids3 *param = arg;
1031
1032 bzero(param, sizeof (struct lsar_lookup_sids3));
1033 param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1034 return (NDR_DRC_OK);
1035 }
1036
1037 /*
1038 * lsarpc_s_LookupNames2
1039 *
1040 * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1041 * is identical to lsarpc_s_LookupNames.
1042 *
1043 * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1044 * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1045 */
1046 static int
lsarpc_s_LookupNames2(void * arg,ndr_xa_t * mxa)1047 lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
1048 {
1049 struct lsar_LookupNames2 *param = arg;
1050 struct lsar_rid_entry2 *rids;
1051 struct mslsa_domain_table *domain_table;
1052 struct mslsa_domain_entry *domain_entry;
1053 smb_account_t account;
1054 uint32_t status;
1055 char *accname;
1056 int rc = 0;
1057
1058 if (param->name_table->n_entry != 1)
1059 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1060
1061 if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1062 param->lookup_level != LSA_LOOKUP_WKSTA) {
1063 bzero(param, sizeof (struct lsar_LookupNames2));
1064 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1065 return (NDR_DRC_OK);
1066 }
1067
1068 rids = NDR_NEW(mxa, struct lsar_rid_entry2);
1069 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1070 domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1071
1072 if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
1073 bzero(param, sizeof (struct lsar_LookupNames2));
1074 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1075 return (NDR_DRC_OK);
1076 }
1077
1078 accname = (char *)param->name_table->names->str;
1079 status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1080 if (status != NT_STATUS_SUCCESS) {
1081 bzero(param, sizeof (struct lsar_LookupNames2));
1082 param->status = NT_SC_ERROR(status);
1083 return (NDR_DRC_OK);
1084 }
1085
1086 /*
1087 * Set up the rid table.
1088 */
1089 bzero(rids, sizeof (struct lsar_rid_entry2));
1090 rids[0].sid_name_use = account.a_type;
1091 rids[0].rid = account.a_rid;
1092 rids[0].domain_index = 0;
1093 param->translated_sids.n_entry = 1;
1094 param->translated_sids.rids = rids;
1095
1096 /*
1097 * Set up the domain table.
1098 */
1099 domain_table->entries = domain_entry;
1100 domain_table->n_entry = 1;
1101 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1102
1103 rc = NDR_MSTRING(mxa, account.a_domain,
1104 (ndr_mstring_t *)&domain_entry->domain_name);
1105
1106 domain_entry->domain_sid =
1107 (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1108
1109 if (rc == -1 || domain_entry->domain_sid == NULL) {
1110 smb_account_free(&account);
1111 bzero(param, sizeof (struct lsar_LookupNames2));
1112 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1113 return (NDR_DRC_OK);
1114 }
1115
1116 param->domain_table = domain_table;
1117 param->mapped_count = 1;
1118 param->status = NT_STATUS_SUCCESS;
1119
1120 smb_account_free(&account);
1121 return (NDR_DRC_OK);
1122 }
1123
1124 /*
1125 * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1126 * is identical to lsarpc_s_LookupNames.
1127 *
1128 * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1129 * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1130 */
1131 static int
lsarpc_s_LookupNames3(void * arg,ndr_xa_t * mxa)1132 lsarpc_s_LookupNames3(void *arg, ndr_xa_t *mxa)
1133 {
1134 struct lsar_LookupNames3 *param = arg;
1135 struct lsar_translated_sid_ex2 *sids;
1136 struct mslsa_domain_table *domain_table;
1137 struct mslsa_domain_entry *domain_entry;
1138 smb_account_t account;
1139 uint32_t status;
1140 char *accname;
1141 int rc = 0;
1142
1143 if (param->name_table->n_entry != 1)
1144 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1145
1146 if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1147 param->lookup_level != LSA_LOOKUP_WKSTA) {
1148 bzero(param, sizeof (struct lsar_LookupNames3));
1149 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1150 return (NDR_DRC_OK);
1151 }
1152
1153 sids = NDR_NEW(mxa, struct lsar_translated_sid_ex2);
1154 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1155 domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1156
1157 if (sids == NULL || domain_table == NULL || domain_entry == NULL) {
1158 bzero(param, sizeof (struct lsar_LookupNames3));
1159 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1160 return (NDR_DRC_OK);
1161 }
1162
1163 accname = (char *)param->name_table->names->str;
1164 status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1165 if (status != NT_STATUS_SUCCESS) {
1166 bzero(param, sizeof (struct lsar_LookupNames3));
1167 param->status = NT_SC_ERROR(status);
1168 return (NDR_DRC_OK);
1169 }
1170
1171 /*
1172 * Set up the SID table.
1173 */
1174 bzero(sids, sizeof (struct lsar_translated_sid_ex2));
1175 sids[0].sid_name_use = account.a_type;
1176 sids[0].sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_sid);
1177 sids[0].domain_index = 0;
1178 param->translated_sids.n_entry = 1;
1179 param->translated_sids.sids = sids;
1180
1181 /*
1182 * Set up the domain table.
1183 */
1184 domain_table->entries = domain_entry;
1185 domain_table->n_entry = 1;
1186 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1187
1188 rc = NDR_MSTRING(mxa, account.a_domain,
1189 (ndr_mstring_t *)&domain_entry->domain_name);
1190
1191 domain_entry->domain_sid =
1192 (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1193
1194 if (rc == -1 || domain_entry->domain_sid == NULL) {
1195 smb_account_free(&account);
1196 bzero(param, sizeof (struct lsar_LookupNames3));
1197 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1198 return (NDR_DRC_OK);
1199 }
1200
1201 param->domain_table = domain_table;
1202 param->mapped_count = 1;
1203 param->status = NT_STATUS_SUCCESS;
1204
1205 smb_account_free(&account);
1206 return (NDR_DRC_OK);
1207 }
1208
1209 /*
1210 * LookupNames4 is only valid on domain controllers.
1211 * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1212 */
1213 /*ARGSUSED*/
1214 static int
lsarpc_s_LookupNames4(void * arg,ndr_xa_t * mxa)1215 lsarpc_s_LookupNames4(void *arg, ndr_xa_t *mxa)
1216 {
1217 struct lsar_LookupNames4 *param = arg;
1218
1219 bzero(param, sizeof (struct lsar_LookupNames4));
1220 param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1221 return (NDR_DRC_OK);
1222 }
1223
1224 /*
1225 * There is a bug in the way that ndrgen and the marshalling code handles
1226 * unions so we need to fix some of the data offsets at runtime. The
1227 * following macros and the fixup functions handle the corrections.
1228 */
1229
1230 DECL_FIXUP_STRUCT(mslsa_PolicyInfoResUnion);
1231 DECL_FIXUP_STRUCT(mslsa_PolicyInfoRes);
1232 DECL_FIXUP_STRUCT(mslsa_QueryInfoPolicy);
1233 void
fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy * val)1234 fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy *val)
1235 {
1236 unsigned short size1 = 0;
1237 unsigned short size2 = 0;
1238 unsigned short size3 = 0;
1239
1240 switch (val->info_class) {
1241 case MSLSA_POLICY_AUDIT_EVENTS_INFO:
1242 size1 = sizeof (struct mslsa_AuditEventsInfo);
1243 break;
1244
1245 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
1246 size1 = sizeof (struct mslsa_PrimaryDomainInfo);
1247 break;
1248
1249 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
1250 size1 = sizeof (struct mslsa_AccountDomainInfo);
1251 break;
1252
1253 case MSLSA_POLICY_SERVER_ROLE_INFO:
1254 size1 = sizeof (struct mslsa_ServerRoleInfo);
1255 break;
1256
1257 case MSLSA_POLICY_DNS_DOMAIN_INFO:
1258 size1 = sizeof (struct mslsa_DnsDomainInfo);
1259 break;
1260
1261 default:
1262 return;
1263 };
1264
1265 size2 = size1 + (2 * sizeof (DWORD));
1266 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1267
1268 FIXUP_PDU_SIZE(mslsa_PolicyInfoResUnion, size1);
1269 FIXUP_PDU_SIZE(mslsa_PolicyInfoRes, size2);
1270 FIXUP_PDU_SIZE(mslsa_QueryInfoPolicy, size3);
1271 }
1272