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
lsarpc_initialize(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
lsarpc_call_stub(ndr_xa_t * mxa)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
lsarpc_s_OpenDomainHandle(void * arg,ndr_xa_t * mxa)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, ¶m->domain_handle, sizeof (mslsa_handle_t));
168 param->status = NT_STATUS_SUCCESS;
169 } else {
170 bzero(¶m->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
lsarpc_s_CloseHandle(void * arg,ndr_xa_t * mxa)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 *)¶m->handle;
190
191 ndr_hdfree(mxa, id);
192
193 bzero(¶m->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
lsarpc_s_QuerySecurityObject(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumAccounts(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumTrustedDomain(void * arg,ndr_xa_t * mxa)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
lsarpc_s_EnumTrustedDomainsEx(void * arg,ndr_xa_t * mxa)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
lsarpc_s_OpenAccount(void * arg,ndr_xa_t * mxa)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 *)¶m->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, ¶m->account_handle, sizeof (mslsa_handle_t));
340 param->status = NT_STATUS_SUCCESS;
341 } else {
342 bzero(¶m->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
lsarpc_s_EnumPrivsAccount(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivValue(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivName(void * arg,ndr_xa_t * mxa)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
lsarpc_s_LookupPrivDisplayName(void * arg,ndr_xa_t * mxa)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
lsarpc_s_CreateSecret(void * arg,ndr_xa_t * mxa)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 *)¶m->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(¶m->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
lsarpc_s_OpenSecret(void * arg,ndr_xa_t * mxa)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 *)¶m->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(¶m->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
lsarpc_s_GetConnectedUser(void * arg,ndr_xa_t * mxa)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
lsarpc_s_QueryInfoPolicy(void * arg,ndr_xa_t * mxa)571 lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa)
572 {
573 struct mslsa_QueryInfoPolicy *param = arg;
574 union mslsa_PolicyInfoResUnion *ru = ¶m->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
lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo * info,ndr_xa_t * mxa)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
lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo * info,ndr_xa_t * mxa)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
lsarpc_s_LookupNames(void * arg,ndr_xa_t * mxa)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
790 static int
lsarpc_s_LookupSids(void * arg,ndr_xa_t * mxa)791 lsarpc_s_LookupSids(void *arg, ndr_xa_t *mxa)
792 {
793 struct mslsa_LookupSids *param = arg;
794 struct mslsa_domain_table *domain_table;
795 struct mslsa_domain_entry *domain_entry;
796 struct mslsa_name_entry *names;
797 struct mslsa_name_entry *name;
798 smb_account_t account;
799 smb_sid_t *sid;
800 DWORD n_entry;
801 DWORD n_mapped;
802 char sidstr[SMB_SID_STRSZ];
803 int result;
804 int i;
805
806 bzero(&account, sizeof (smb_account_t));
807 n_mapped = 0;
808 n_entry = param->lup_sid_table.n_entry;
809
810 names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry);
811 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
812 domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
813 MLSVC_DOMAIN_MAX);
814
815 if (names == NULL || domain_table == NULL || domain_entry == NULL)
816 goto lookup_sid_failed;
817
818 domain_table->entries = domain_entry;
819 domain_table->n_entry = 0;
820 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
821
822 name = names;
823 for (i = 0; i < n_entry; ++i, name++) {
824 bzero(name, sizeof (struct mslsa_name_entry));
825 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
826
827 result = lsa_lookup_sid(sid, &account);
828 if ((result != NT_STATUS_SUCCESS) ||
829 (account.a_name == NULL) || (*account.a_name == '\0')) {
830 account.a_type = SidTypeUnknown;
831 smb_sid_tostr(sid, sidstr);
832
833 if (NDR_MSTRING(mxa, sidstr,
834 (ndr_mstring_t *)&name->name) == -1)
835 goto lookup_sid_failed;
836
837 } else {
838 if (NDR_MSTRING(mxa, account.a_name,
839 (ndr_mstring_t *)&name->name) == -1)
840 goto lookup_sid_failed;
841
842 ++n_mapped;
843 }
844
845 name->sid_name_use = account.a_type;
846
847 result = lsarpc_s_UpdateDomainTable(mxa, &account,
848 domain_table, &name->domain_ix);
849 if (result == -1)
850 goto lookup_sid_failed;
851
852 smb_account_free(&account);
853 }
854
855 param->domain_table = domain_table;
856 param->name_table.n_entry = n_entry;
857 param->name_table.entries = names;
858 param->mapped_count = n_mapped;
859
860 if (n_mapped == n_entry)
861 param->status = NT_STATUS_SUCCESS;
862 else if (n_mapped == 0)
863 param->status = NT_STATUS_NONE_MAPPED;
864 else
865 param->status = NT_STATUS_SOME_NOT_MAPPED;
866
867 return (NDR_DRC_OK);
868
869 lookup_sid_failed:
870 smb_account_free(&account);
871 bzero(param, sizeof (struct mslsa_LookupSids));
872 return (NDR_DRC_FAULT_OUT_OF_MEMORY);
873 }
874
875 /*
876 * lsarpc_s_UpdateDomainTable
877 *
878 * This routine is responsible for maintaining the domain table which
879 * will be returned from a SID lookup. Whenever a name is added to the
880 * name table, this function should be called with the corresponding
881 * domain name. If the domain information is not already in the table,
882 * it is added. On success return 0; Otherwise -1 is returned.
883 */
884 static int
lsarpc_s_UpdateDomainTable(ndr_xa_t * mxa,smb_account_t * account,struct mslsa_domain_table * domain_table,DWORD * domain_idx)885 lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
886 smb_account_t *account, struct mslsa_domain_table *domain_table,
887 DWORD *domain_idx)
888 {
889 struct mslsa_domain_entry *dentry;
890 DWORD n_entry;
891 DWORD i;
892 int rc;
893
894 if (account->a_type == SidTypeUnknown ||
895 account->a_type == SidTypeInvalid) {
896 /*
897 * These types don't need to reference an entry in the
898 * domain table. So return -1.
899 */
900 *domain_idx = (DWORD)-1;
901 return (0);
902 }
903
904 if ((dentry = domain_table->entries) == NULL)
905 return (-1);
906
907 if ((n_entry = domain_table->n_entry) >= MLSVC_DOMAIN_MAX)
908 return (-1);
909
910 for (i = 0; i < n_entry; ++i) {
911 if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid,
912 account->a_domsid)) {
913 *domain_idx = i;
914 return (0);
915 }
916 }
917
918 if (i == MLSVC_DOMAIN_MAX)
919 return (-1);
920
921 rc = NDR_MSTRING(mxa, account->a_domain,
922 (ndr_mstring_t *)&dentry[i].domain_name);
923 dentry[i].domain_sid =
924 (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid);
925
926 if (rc == -1 || dentry[i].domain_sid == NULL)
927 return (-1);
928
929 ++domain_table->n_entry;
930 *domain_idx = i;
931 return (0);
932 }
933
934 /*
935 * lsarpc_s_LookupSids2
936 *
937 * Other than the use of lsar_lookup_sids2 and lsar_name_entry2, this
938 * is identical to lsarpc_s_LookupSids.
939 *
940 * Ignore lookup_level, it is reserved and should be zero.
941 */
942 static int
lsarpc_s_LookupSids2(void * arg,ndr_xa_t * mxa)943 lsarpc_s_LookupSids2(void *arg, ndr_xa_t *mxa)
944 {
945 struct lsar_lookup_sids2 *param = arg;
946 struct lsar_name_entry2 *names;
947 struct lsar_name_entry2 *name;
948 struct mslsa_domain_table *domain_table;
949 struct mslsa_domain_entry *domain_entry;
950 smb_account_t account;
951 smb_sid_t *sid;
952 DWORD n_entry;
953 DWORD n_mapped;
954 char sidstr[SMB_SID_STRSZ];
955 int result;
956 int i;
957
958 bzero(&account, sizeof (smb_account_t));
959 n_mapped = 0;
960 n_entry = param->lup_sid_table.n_entry;
961
962 names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry);
963 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
964 domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
965 MLSVC_DOMAIN_MAX);
966
967 if (names == NULL || domain_table == NULL || domain_entry == NULL)
968 goto lookup_sid_failed;
969
970 domain_table->entries = domain_entry;
971 domain_table->n_entry = 0;
972 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
973
974 name = names;
975 for (i = 0; i < n_entry; ++i, name++) {
976 bzero(name, sizeof (struct lsar_name_entry2));
977 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
978
979 result = lsa_lookup_sid(sid, &account);
980 if ((result != NT_STATUS_SUCCESS) ||
981 (account.a_name == NULL) || (*account.a_name == '\0')) {
982 account.a_type = SidTypeUnknown;
983 smb_sid_tostr(sid, sidstr);
984
985 if (NDR_MSTRING(mxa, sidstr,
986 (ndr_mstring_t *)&name->name) == -1)
987 goto lookup_sid_failed;
988
989 } else {
990 if (NDR_MSTRING(mxa, account.a_name,
991 (ndr_mstring_t *)&name->name) == -1)
992 goto lookup_sid_failed;
993
994 ++n_mapped;
995 }
996
997 name->sid_name_use = account.a_type;
998
999 result = lsarpc_s_UpdateDomainTable(mxa, &account,
1000 domain_table, &name->domain_ix);
1001 if (result == -1)
1002 goto lookup_sid_failed;
1003
1004 smb_account_free(&account);
1005 }
1006
1007 param->domain_table = domain_table;
1008 param->name_table.n_entry = n_entry;
1009 param->name_table.entries = names;
1010 param->mapped_count = n_mapped;
1011
1012 if (n_mapped == n_entry)
1013 param->status = NT_STATUS_SUCCESS;
1014 else if (n_mapped == 0)
1015 param->status = NT_STATUS_NONE_MAPPED;
1016 else
1017 param->status = NT_STATUS_SOME_NOT_MAPPED;
1018
1019 return (NDR_DRC_OK);
1020
1021 lookup_sid_failed:
1022 smb_account_free(&account);
1023 bzero(param, sizeof (struct lsar_lookup_sids2));
1024 return (NDR_DRC_FAULT_OUT_OF_MEMORY);
1025 }
1026
1027 /*
1028 * LookupSids3 is only valid on domain controllers.
1029 * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1030 */
1031 /*ARGSUSED*/
1032 static int
lsarpc_s_LookupSids3(void * arg,ndr_xa_t * mxa)1033 lsarpc_s_LookupSids3(void *arg, ndr_xa_t *mxa)
1034 {
1035 struct lsar_lookup_sids3 *param = arg;
1036
1037 bzero(param, sizeof (struct lsar_lookup_sids3));
1038 param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1039 return (NDR_DRC_OK);
1040 }
1041
1042 /*
1043 * lsarpc_s_LookupNames2
1044 *
1045 * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1046 * is identical to lsarpc_s_LookupNames.
1047 *
1048 * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1049 * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1050 */
1051 static int
lsarpc_s_LookupNames2(void * arg,ndr_xa_t * mxa)1052 lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
1053 {
1054 struct lsar_LookupNames2 *param = arg;
1055 struct lsar_rid_entry2 *rids;
1056 struct mslsa_domain_table *domain_table;
1057 struct mslsa_domain_entry *domain_entry;
1058 smb_account_t account;
1059 uint32_t status;
1060 char *accname;
1061 int rc = 0;
1062
1063 if (param->name_table->n_entry != 1)
1064 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1065
1066 if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1067 param->lookup_level != LSA_LOOKUP_WKSTA) {
1068 bzero(param, sizeof (struct lsar_LookupNames2));
1069 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1070 return (NDR_DRC_OK);
1071 }
1072
1073 rids = NDR_NEW(mxa, struct lsar_rid_entry2);
1074 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1075 domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1076
1077 if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
1078 bzero(param, sizeof (struct lsar_LookupNames2));
1079 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1080 return (NDR_DRC_OK);
1081 }
1082
1083 accname = (char *)param->name_table->names->str;
1084 status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1085 if (status != NT_STATUS_SUCCESS) {
1086 bzero(param, sizeof (struct lsar_LookupNames2));
1087 param->status = NT_SC_ERROR(status);
1088 return (NDR_DRC_OK);
1089 }
1090
1091 /*
1092 * Set up the rid table.
1093 */
1094 bzero(rids, sizeof (struct lsar_rid_entry2));
1095 rids[0].sid_name_use = account.a_type;
1096 rids[0].rid = account.a_rid;
1097 rids[0].domain_index = 0;
1098 param->translated_sids.n_entry = 1;
1099 param->translated_sids.rids = rids;
1100
1101 /*
1102 * Set up the domain table.
1103 */
1104 domain_table->entries = domain_entry;
1105 domain_table->n_entry = 1;
1106 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1107
1108 rc = NDR_MSTRING(mxa, account.a_domain,
1109 (ndr_mstring_t *)&domain_entry->domain_name);
1110
1111 domain_entry->domain_sid =
1112 (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1113
1114 if (rc == -1 || domain_entry->domain_sid == NULL) {
1115 smb_account_free(&account);
1116 bzero(param, sizeof (struct lsar_LookupNames2));
1117 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1118 return (NDR_DRC_OK);
1119 }
1120
1121 param->domain_table = domain_table;
1122 param->mapped_count = 1;
1123 param->status = NT_STATUS_SUCCESS;
1124
1125 smb_account_free(&account);
1126 return (NDR_DRC_OK);
1127 }
1128
1129 /*
1130 * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1131 * is identical to lsarpc_s_LookupNames.
1132 *
1133 * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1134 * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1135 */
1136 static int
lsarpc_s_LookupNames3(void * arg,ndr_xa_t * mxa)1137 lsarpc_s_LookupNames3(void *arg, ndr_xa_t *mxa)
1138 {
1139 struct lsar_LookupNames3 *param = arg;
1140 struct lsar_translated_sid_ex2 *sids;
1141 struct mslsa_domain_table *domain_table;
1142 struct mslsa_domain_entry *domain_entry;
1143 smb_account_t account;
1144 uint32_t status;
1145 char *accname;
1146 int rc = 0;
1147
1148 if (param->name_table->n_entry != 1)
1149 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1150
1151 if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1152 param->lookup_level != LSA_LOOKUP_WKSTA) {
1153 bzero(param, sizeof (struct lsar_LookupNames3));
1154 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1155 return (NDR_DRC_OK);
1156 }
1157
1158 sids = NDR_NEW(mxa, struct lsar_translated_sid_ex2);
1159 domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1160 domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1161
1162 if (sids == NULL || domain_table == NULL || domain_entry == NULL) {
1163 bzero(param, sizeof (struct lsar_LookupNames3));
1164 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1165 return (NDR_DRC_OK);
1166 }
1167
1168 accname = (char *)param->name_table->names->str;
1169 status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1170 if (status != NT_STATUS_SUCCESS) {
1171 bzero(param, sizeof (struct lsar_LookupNames3));
1172 param->status = NT_SC_ERROR(status);
1173 return (NDR_DRC_OK);
1174 }
1175
1176 /*
1177 * Set up the SID table.
1178 */
1179 bzero(sids, sizeof (struct lsar_translated_sid_ex2));
1180 sids[0].sid_name_use = account.a_type;
1181 sids[0].sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_sid);
1182 sids[0].domain_index = 0;
1183 param->translated_sids.n_entry = 1;
1184 param->translated_sids.sids = sids;
1185
1186 /*
1187 * Set up the domain table.
1188 */
1189 domain_table->entries = domain_entry;
1190 domain_table->n_entry = 1;
1191 domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1192
1193 rc = NDR_MSTRING(mxa, account.a_domain,
1194 (ndr_mstring_t *)&domain_entry->domain_name);
1195
1196 domain_entry->domain_sid =
1197 (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1198
1199 if (rc == -1 || domain_entry->domain_sid == NULL) {
1200 smb_account_free(&account);
1201 bzero(param, sizeof (struct lsar_LookupNames3));
1202 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1203 return (NDR_DRC_OK);
1204 }
1205
1206 param->domain_table = domain_table;
1207 param->mapped_count = 1;
1208 param->status = NT_STATUS_SUCCESS;
1209
1210 smb_account_free(&account);
1211 return (NDR_DRC_OK);
1212 }
1213
1214 /*
1215 * LookupNames4 is only valid on domain controllers.
1216 * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1217 */
1218 /*ARGSUSED*/
1219 static int
lsarpc_s_LookupNames4(void * arg,ndr_xa_t * mxa)1220 lsarpc_s_LookupNames4(void *arg, ndr_xa_t *mxa)
1221 {
1222 struct lsar_LookupNames4 *param = arg;
1223
1224 bzero(param, sizeof (struct lsar_LookupNames4));
1225 param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1226 return (NDR_DRC_OK);
1227 }
1228
1229 /*
1230 * There is a bug in the way that ndrgen and the marshalling code handles
1231 * unions so we need to fix some of the data offsets at runtime. The
1232 * following macros and the fixup functions handle the corrections.
1233 */
1234
1235 DECL_FIXUP_STRUCT(mslsa_PolicyInfoResUnion);
1236 DECL_FIXUP_STRUCT(mslsa_PolicyInfoRes);
1237 DECL_FIXUP_STRUCT(mslsa_QueryInfoPolicy);
1238 void
fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy * val)1239 fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy *val)
1240 {
1241 unsigned short size1 = 0;
1242 unsigned short size2 = 0;
1243 unsigned short size3 = 0;
1244
1245 switch (val->info_class) {
1246 case MSLSA_POLICY_AUDIT_EVENTS_INFO:
1247 size1 = sizeof (struct mslsa_AuditEventsInfo);
1248 break;
1249
1250 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
1251 size1 = sizeof (struct mslsa_PrimaryDomainInfo);
1252 break;
1253
1254 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
1255 size1 = sizeof (struct mslsa_AccountDomainInfo);
1256 break;
1257
1258 case MSLSA_POLICY_SERVER_ROLE_INFO:
1259 size1 = sizeof (struct mslsa_ServerRoleInfo);
1260 break;
1261
1262 case MSLSA_POLICY_DNS_DOMAIN_INFO:
1263 size1 = sizeof (struct mslsa_DnsDomainInfo);
1264 break;
1265
1266 default:
1267 return;
1268 };
1269
1270 size2 = size1 + (2 * sizeof (DWORD));
1271 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1272
1273 FIXUP_PDU_SIZE(mslsa_PolicyInfoResUnion, size1);
1274 FIXUP_PDU_SIZE(mslsa_PolicyInfoRes, size2);
1275 FIXUP_PDU_SIZE(mslsa_QueryInfoPolicy, size3);
1276 }
1277