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 2015 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * Local Security Authority RPC (LSAR) client-side interface.
29 */
30
31 #include <sys/errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <strings.h>
35
36 #include <smbsrv/libsmb.h>
37 #include <smbsrv/libmlsvc.h>
38 #include <smbsrv/smbinfo.h>
39 #include <smbsrv/ntaccess.h>
40 #include <smbsrv/ntlocale.h>
41 #include <smbsrv/string.h>
42 #include <lsalib.h>
43
44 /*
45 * The maximum number of bytes we are prepared to deal with in a
46 * response.
47 */
48 #define MLSVC_MAX_RESPONSE_LEN 1024
49
50 /*
51 * This structure is used when looking up names. We only lookup one
52 * name at a time but the structure will allow for more.
53 */
54 typedef struct lsa_names {
55 uint32_t n_entry;
56 mslsa_string_t name[8];
57 } lsa_names_t;
58
59 typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *,
60 smb_account_t *);
61
62 static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *,
63 smb_account_t *);
64 static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *,
65 smb_account_t *);
66 static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *,
67 smb_account_t *);
68 static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *,
69 smb_account_t *);
70 static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *,
71 smb_account_t *account);
72
73 static char *lsar_get_username(const char *);
74 static void smb_account_trace(const smb_account_t *);
75
76 static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
77 smb_trusted_domains_t *);
78 static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
79 smb_trusted_domains_t *);
80
81 /*
82 * lsar_open
83 *
84 * This is a wrapper round lsar_open_policy2 to ensure that we connect
85 * using the appropriate domain information.
86 *
87 * If username argument is NULL, an anonymous connection will be established.
88 * Otherwise, an authenticated connection will be established.
89 *
90 * Returns 0 or NT status (Raw, not LSA-ized)
91 */
92 DWORD
lsar_open(char * server,char * domain,char * username,mlsvc_handle_t * domain_handle)93 lsar_open(char *server, char *domain, char *username,
94 mlsvc_handle_t *domain_handle)
95 {
96 DWORD status;
97
98 if (server == NULL || domain == NULL)
99 return (NT_STATUS_INTERNAL_ERROR);
100
101 if (username == NULL)
102 username = MLSVC_ANON_USER;
103
104 status = lsar_open_policy2(server, domain, username, domain_handle);
105
106 return (status);
107 }
108
109 /*
110 * lsar_open_policy2
111 *
112 * Obtain an LSA policy handle. A policy handle is required to access
113 * LSA resources on a remote server. The server name supplied here does
114 * not need the double backslash prefix; it is added here. Call this
115 * function via lsar_open to ensure that the appropriate connection is
116 * in place.
117 *
118 * Returns 0 or NT status (Raw, not LSA-ized)
119 */
120 DWORD
lsar_open_policy2(char * server,char * domain,char * user,mlsvc_handle_t * lsa_handle)121 lsar_open_policy2(char *server, char *domain, char *user,
122 mlsvc_handle_t *lsa_handle)
123 {
124 struct mslsa_OpenPolicy2 arg;
125 DWORD status;
126 int opnum;
127 int len;
128
129 status = ndr_rpc_bind(lsa_handle, server, domain, user, "LSARPC");
130 if (status != 0)
131 return (status);
132
133 opnum = LSARPC_OPNUM_OpenPolicy2;
134 bzero(&arg, sizeof (struct mslsa_OpenPolicy2));
135
136 len = strlen(server) + 4;
137 arg.servername = ndr_rpc_malloc(lsa_handle, len);
138 if (arg.servername == NULL) {
139 status = NT_STATUS_NO_MEMORY;
140 goto out;
141 }
142
143 (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
144 arg.attributes.length = sizeof (struct mslsa_object_attributes);
145 arg.desiredAccess = MAXIMUM_ALLOWED;
146
147 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
148 status = RPC_NT_CALL_FAILED;
149 goto out;
150 }
151 status = arg.status;
152 if (status == NT_STATUS_SUCCESS) {
153 (void) memcpy(&lsa_handle->handle, &arg.domain_handle,
154 sizeof (ndr_hdid_t));
155
156 if (ndr_is_null_handle(lsa_handle))
157 status = NT_STATUS_INVALID_PARAMETER;
158 }
159
160 ndr_rpc_release(lsa_handle);
161
162 out:
163 if (status != NT_STATUS_SUCCESS)
164 ndr_rpc_unbind(lsa_handle);
165 return (status);
166 }
167
168 /*
169 * lsar_open_account
170 *
171 * Obtain an LSA account handle. The lsa_handle must be a valid handle
172 * obtained via lsar_open_policy2. The main thing to remember here is
173 * to set up the context in the lsa_account_handle. I'm not sure what
174 * the requirements are for desired access. Some values require admin
175 * access.
176 *
177 * Returns 0 on success. Otherwise non-zero to indicate a failure.
178 */
179 int
lsar_open_account(mlsvc_handle_t * lsa_handle,struct mslsa_sid * sid,mlsvc_handle_t * lsa_account_handle)180 lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
181 mlsvc_handle_t *lsa_account_handle)
182 {
183 struct mslsa_OpenAccount arg;
184 int opnum;
185 int rc;
186
187 if (ndr_is_null_handle(lsa_handle) || sid == NULL)
188 return (-1);
189
190 opnum = LSARPC_OPNUM_OpenAccount;
191 bzero(&arg, sizeof (struct mslsa_OpenAccount));
192
193 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
194 arg.sid = sid;
195 arg.access_mask = STANDARD_RIGHTS_REQUIRED
196 #if 0
197 | POLICY_VIEW_AUDIT_INFORMATION
198 | POLICY_GET_PRIVATE_INFORMATION
199 | POLICY_TRUST_ADMIN
200 #endif
201 | POLICY_VIEW_LOCAL_INFORMATION;
202
203 if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0)
204 return (-1);
205
206 if (arg.status != 0) {
207 rc = -1;
208 } else {
209 ndr_inherit_handle(lsa_account_handle, lsa_handle);
210
211 (void) memcpy(&lsa_account_handle->handle,
212 &arg.account_handle, sizeof (ndr_hdid_t));
213
214 if (ndr_is_null_handle(lsa_account_handle))
215 rc = -1;
216 }
217
218 ndr_rpc_release(lsa_handle);
219 return (rc);
220 }
221
222 /*
223 * lsar_close
224 *
225 * Close the LSA connection associated with the handle. The lsa_handle
226 * must be a valid handle obtained via a call to lsar_open_policy2 or
227 * lsar_open_account. On success the handle will be zeroed out to
228 * ensure that it is not used again. If this is the top level handle
229 * (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
230 *
231 * Returns 0 on success. Otherwise non-zero to indicate a failure.
232 */
233 int
lsar_close(mlsvc_handle_t * lsa_handle)234 lsar_close(mlsvc_handle_t *lsa_handle)
235 {
236 struct mslsa_CloseHandle arg;
237 int opnum;
238
239 if (ndr_is_null_handle(lsa_handle))
240 return (-1);
241
242 opnum = LSARPC_OPNUM_CloseHandle;
243 bzero(&arg, sizeof (struct mslsa_CloseHandle));
244 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
245
246 (void) ndr_rpc_call(lsa_handle, opnum, &arg);
247 ndr_rpc_release(lsa_handle);
248
249 if (ndr_is_bind_handle(lsa_handle))
250 ndr_rpc_unbind(lsa_handle);
251
252 bzero(lsa_handle, sizeof (mlsvc_handle_t));
253 return (0);
254 }
255
256 /*
257 * lsar_query_security_desc
258 *
259 * Don't use this call yet. It is just a place holder for now.
260 */
261 int
lsar_query_security_desc(mlsvc_handle_t * lsa_handle)262 lsar_query_security_desc(mlsvc_handle_t *lsa_handle)
263 {
264 struct mslsa_QuerySecurityObject arg;
265 int rc;
266 int opnum;
267
268 opnum = LSARPC_OPNUM_QuerySecurityObject;
269
270 bzero(&arg, sizeof (struct mslsa_QuerySecurityObject));
271 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
272
273 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
274 ndr_rpc_release(lsa_handle);
275 return (rc);
276 }
277
278 /*
279 * lsar_query_info_policy
280 *
281 * The general purpose of this function is to allow various pieces of
282 * information to be queried on the domain controller. The only
283 * information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO
284 * and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO.
285 *
286 * On success, the return code will be 0 and the user_info structure
287 * will be set up. The sid_name_use field will be set to SidTypeDomain
288 * indicating that the domain name and domain sid fields are vaild. If
289 * the infoClass returned from the server is not one of the supported
290 * values, the sid_name_use willbe set to SidTypeUnknown. If the RPC
291 * fails, a negative error code will be returned, in which case the
292 * user_info will not have been updated.
293 */
294 DWORD
lsar_query_info_policy(mlsvc_handle_t * lsa_handle,WORD infoClass,smb_domain_t * info)295 lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
296 smb_domain_t *info)
297 {
298 struct mslsa_QueryInfoPolicy arg;
299 struct mslsa_PrimaryDomainInfo *pd_info;
300 struct mslsa_AccountDomainInfo *ad_info;
301 struct mslsa_DnsDomainInfo *dns_info;
302 char guid_str[UUID_PRINTABLE_STRING_LENGTH];
303 char sidstr[SMB_SID_STRSZ];
304 int opnum;
305 DWORD status;
306
307 if (lsa_handle == NULL || info == NULL)
308 return (NT_STATUS_INVALID_PARAMETER);
309
310 opnum = LSARPC_OPNUM_QueryInfoPolicy;
311
312 bzero(info, sizeof (smb_domain_t));
313 bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy));
314 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
315
316 arg.info_class = infoClass;
317
318 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
319 status = NT_STATUS_INVALID_PARAMETER;
320 } else if (arg.status != 0) {
321 ndr_rpc_status(lsa_handle, opnum, arg.status);
322 status = NT_SC_VALUE(arg.status);
323 } else {
324
325 switch (infoClass) {
326 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
327 pd_info = &arg.ru.pd_info;
328
329 smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr);
330 info->di_type = SMB_DOMAIN_PRIMARY;
331 smb_domain_set_basic_info(sidstr,
332 (char *)pd_info->name.str, "", info);
333
334 status = NT_STATUS_SUCCESS;
335 break;
336
337 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
338 ad_info = &arg.ru.ad_info;
339
340 smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr);
341 info->di_type = SMB_DOMAIN_ACCOUNT;
342 smb_domain_set_basic_info(sidstr,
343 (char *)ad_info->name.str, "", info);
344
345 status = NT_STATUS_SUCCESS;
346 break;
347
348 case MSLSA_POLICY_DNS_DOMAIN_INFO:
349 dns_info = &arg.ru.dns_info;
350 ndr_uuid_unparse((ndr_uuid_t *)&dns_info->guid,
351 guid_str);
352 smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr);
353
354 info->di_type = SMB_DOMAIN_PRIMARY;
355 smb_domain_set_dns_info(sidstr,
356 (char *)dns_info->nb_domain.str,
357 (char *)dns_info->dns_domain.str,
358 (char *)dns_info->forest.str,
359 guid_str, info);
360 status = NT_STATUS_SUCCESS;
361 break;
362
363 default:
364 status = NT_STATUS_INVALID_INFO_CLASS;
365 break;
366 }
367 }
368
369 ndr_rpc_release(lsa_handle);
370 return (status);
371 }
372
373 /*
374 * Lookup a name and obtain the sid/rid.
375 * This is a wrapper for the various lookup sid RPCs.
376 */
377 uint32_t
lsar_lookup_names(mlsvc_handle_t * lsa_handle,char * name,smb_account_t * info)378 lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
379 {
380 static lsar_nameop_t ops[] = {
381 lsar_lookup_names3,
382 lsar_lookup_names2,
383 lsar_lookup_names1
384 };
385
386 const srvsvc_server_info_t *svinfo;
387 lsa_names_t names;
388 char *p;
389 uint32_t length;
390 uint32_t status = NT_STATUS_INVALID_PARAMETER;
391 int n_op = (sizeof (ops) / sizeof (ops[0]));
392 int i;
393
394 if (lsa_handle == NULL || name == NULL || info == NULL)
395 return (NT_STATUS_INVALID_PARAMETER);
396
397 bzero(info, sizeof (smb_account_t));
398
399 svinfo = ndr_rpc_server_info(lsa_handle);
400 if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
401 svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
402 /*
403 * Windows 2000 doesn't like an LSA lookup for
404 * DOMAIN\Administrator.
405 */
406 if ((p = strchr(name, '\\')) != 0) {
407 ++p;
408
409 if (strcasecmp(p, "administrator") == 0)
410 name = p;
411 }
412
413 }
414
415 length = smb_wcequiv_strlen(name);
416 names.name[0].length = length;
417 names.name[0].allosize = length;
418 names.name[0].str = (unsigned char *)name;
419 names.n_entry = 1;
420
421 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
422 for (i = 0; i < n_op; ++i) {
423 ndr_rpc_set_nonull(lsa_handle);
424 status = (*ops[i])(lsa_handle, &names, info);
425
426 if (status != NT_STATUS_INVALID_PARAMETER)
427 break;
428 }
429 } else {
430 ndr_rpc_set_nonull(lsa_handle);
431 status = lsar_lookup_names1(lsa_handle, &names, info);
432 }
433
434 if (status == NT_STATUS_SUCCESS) {
435 info->a_name = lsar_get_username(name);
436
437 if (!smb_account_validate(info)) {
438 smb_account_free(info);
439 status = NT_STATUS_NO_MEMORY;
440 } else {
441 smb_account_trace(info);
442 }
443 }
444
445 return (status);
446 }
447
448 /*
449 * The name may be in one of the following forms:
450 *
451 * domain\username
452 * domain/username
453 * username
454 * username@domain
455 *
456 * Return a strdup'd copy of the username. The caller is responsible
457 * for freeing the allocated memory.
458 */
459 static char *
lsar_get_username(const char * name)460 lsar_get_username(const char *name)
461 {
462 char tmp[MAXNAMELEN];
463 char *dp = NULL;
464 char *np = NULL;
465
466 (void) strlcpy(tmp, name, MAXNAMELEN);
467 smb_name_parse(tmp, &np, &dp);
468
469 if (dp != NULL && np != NULL)
470 return (strdup(np));
471 else
472 return (strdup(name));
473 }
474
475 /*
476 * lsar_lookup_names1
477 *
478 * Lookup a name and obtain the domain and user rid.
479 *
480 * Note: NT returns an error if the mapped_count is non-zero when the RPC
481 * is called.
482 *
483 * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
484 */
485 static uint32_t
lsar_lookup_names1(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)486 lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
487 smb_account_t *info)
488 {
489 struct mslsa_LookupNames arg;
490 struct mslsa_rid_entry *rid_entry;
491 struct mslsa_domain_entry *domain_entry;
492 uint32_t status = NT_STATUS_SUCCESS;
493 char *domname;
494 int opnum = LSARPC_OPNUM_LookupNames;
495
496 bzero(&arg, sizeof (struct mslsa_LookupNames));
497 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
498 arg.lookup_level = LSA_LOOKUP_WKSTA;
499 arg.name_table = (struct mslsa_lup_name_table *)names;
500
501 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
502 ndr_rpc_release(lsa_handle);
503 return (NT_STATUS_INVALID_PARAMETER);
504 }
505
506 if (arg.status != NT_STATUS_SUCCESS) {
507 ndr_rpc_status(lsa_handle, opnum, arg.status);
508 ndr_rpc_release(lsa_handle);
509 return (NT_SC_VALUE(arg.status));
510 }
511
512 if (arg.mapped_count == 0) {
513 ndr_rpc_release(lsa_handle);
514 return (NT_STATUS_NONE_MAPPED);
515 }
516
517 rid_entry = &arg.translated_sids.rids[0];
518 if (rid_entry->domain_index != 0) {
519 ndr_rpc_release(lsa_handle);
520 return (NT_STATUS_NONE_MAPPED);
521 }
522
523 domain_entry = &arg.domain_table->entries[0];
524
525 info->a_type = rid_entry->sid_name_use;
526 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
527 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
528 info->a_domain = strdup(domname);
529 info->a_rid = rid_entry->rid;
530 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
531
532 ndr_rpc_release(lsa_handle);
533 return (status);
534 }
535
536 /*
537 * lsar_lookup_names2
538 */
539 static uint32_t
lsar_lookup_names2(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)540 lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
541 smb_account_t *info)
542 {
543 struct lsar_LookupNames2 arg;
544 struct lsar_rid_entry2 *rid_entry;
545 struct mslsa_domain_entry *domain_entry;
546 uint32_t status = NT_STATUS_SUCCESS;
547 char *domname;
548 int opnum = LSARPC_OPNUM_LookupNames2;
549
550 bzero(&arg, sizeof (struct lsar_LookupNames2));
551 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
552 arg.lookup_level = LSA_LOOKUP_WKSTA;
553 arg.client_revision = LSA_CLIENT_REVISION_AD;
554 arg.name_table = (struct mslsa_lup_name_table *)names;
555
556 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
557 ndr_rpc_release(lsa_handle);
558 return (NT_STATUS_INVALID_PARAMETER);
559 }
560
561 if (arg.status != NT_STATUS_SUCCESS) {
562 ndr_rpc_status(lsa_handle, opnum, arg.status);
563 ndr_rpc_release(lsa_handle);
564 return (NT_SC_VALUE(arg.status));
565 }
566
567 if (arg.mapped_count == 0) {
568 ndr_rpc_release(lsa_handle);
569 return (NT_STATUS_NONE_MAPPED);
570 }
571
572 rid_entry = &arg.translated_sids.rids[0];
573 if (rid_entry->domain_index != 0) {
574 ndr_rpc_release(lsa_handle);
575 return (NT_STATUS_NONE_MAPPED);
576 }
577
578 domain_entry = &arg.domain_table->entries[0];
579
580 info->a_type = rid_entry->sid_name_use;
581 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
582 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
583 info->a_domain = strdup(domname);
584 info->a_rid = rid_entry->rid;
585 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
586
587 ndr_rpc_release(lsa_handle);
588 return (status);
589 }
590
591 /*
592 * lsar_lookup_names3
593 */
594 static uint32_t
lsar_lookup_names3(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)595 lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
596 smb_account_t *info)
597 {
598 struct lsar_LookupNames3 arg;
599 lsar_translated_sid_ex2_t *sid_entry;
600 struct mslsa_domain_entry *domain_entry;
601 uint32_t status = NT_STATUS_SUCCESS;
602 char *domname;
603 int opnum = LSARPC_OPNUM_LookupNames3;
604
605 bzero(&arg, sizeof (struct lsar_LookupNames3));
606 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
607 arg.lookup_level = LSA_LOOKUP_WKSTA;
608 arg.client_revision = LSA_CLIENT_REVISION_AD;
609 arg.name_table = (struct mslsa_lup_name_table *)names;
610
611 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
612 ndr_rpc_release(lsa_handle);
613 return (NT_STATUS_INVALID_PARAMETER);
614 }
615
616 if (arg.status != NT_STATUS_SUCCESS) {
617 ndr_rpc_status(lsa_handle, opnum, arg.status);
618 ndr_rpc_release(lsa_handle);
619 return (NT_SC_VALUE(arg.status));
620 }
621
622 if (arg.mapped_count == 0) {
623 ndr_rpc_release(lsa_handle);
624 return (NT_STATUS_NONE_MAPPED);
625 }
626
627 sid_entry = &arg.translated_sids.sids[0];
628 if (sid_entry->domain_index != 0) {
629 ndr_rpc_release(lsa_handle);
630 return (NT_STATUS_NONE_MAPPED);
631 }
632
633 domain_entry = &arg.domain_table->entries[0];
634
635 info->a_type = sid_entry->sid_name_use;
636 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
637 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
638 info->a_domain = strdup(domname);
639 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
640 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
641
642 ndr_rpc_release(lsa_handle);
643 return (status);
644 }
645
646 /*
647 * lsar_lookup_names4
648 *
649 * This function is only valid if the remote RPC server is a domain
650 * controller and requires the security extensions defined in MS-RPCE.
651 *
652 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
653 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
654 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
655 */
656 static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_names4(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)657 lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
658 smb_account_t *info)
659 {
660 struct lsar_LookupNames4 arg;
661 lsar_translated_sid_ex2_t *sid_entry;
662 struct mslsa_domain_entry *domain_entry;
663 uint32_t status = NT_STATUS_SUCCESS;
664 char *domname;
665 int opnum = LSARPC_OPNUM_LookupNames4;
666
667 bzero(&arg, sizeof (struct lsar_LookupNames4));
668 arg.lookup_level = LSA_LOOKUP_WKSTA;
669 arg.client_revision = LSA_CLIENT_REVISION_AD;
670 arg.name_table = (struct mslsa_lup_name_table *)names;
671
672 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
673 ndr_rpc_release(lsa_handle);
674 return (NT_STATUS_INVALID_PARAMETER);
675 }
676
677 if (arg.status != NT_STATUS_SUCCESS) {
678 ndr_rpc_status(lsa_handle, opnum, arg.status);
679 ndr_rpc_release(lsa_handle);
680 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
681 arg.status == NT_STATUS_INVALID_SERVER_STATE)
682 return (NT_STATUS_INVALID_PARAMETER);
683 return (NT_SC_VALUE(arg.status));
684 }
685
686 if (arg.mapped_count == 0) {
687 ndr_rpc_release(lsa_handle);
688 return (NT_STATUS_NONE_MAPPED);
689 }
690
691 sid_entry = &arg.translated_sids.sids[0];
692 if (sid_entry->domain_index != 0) {
693 ndr_rpc_release(lsa_handle);
694 return (NT_STATUS_NONE_MAPPED);
695 }
696
697 domain_entry = &arg.domain_table->entries[0];
698
699 info->a_type = sid_entry->sid_name_use;
700 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
701 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
702 info->a_domain = strdup(domname);
703 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
704 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
705
706 ndr_rpc_release(lsa_handle);
707 return (status);
708 }
709
710 /*
711 * Lookup a sid and obtain the domain sid and account name.
712 * This is a wrapper for the various lookup sid RPCs.
713 */
714 uint32_t
lsar_lookup_sids(mlsvc_handle_t * lsa_handle,smb_sid_t * sid,smb_account_t * account)715 lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid,
716 smb_account_t *account)
717 {
718 char sidbuf[SMB_SID_STRSZ];
719 uint32_t status;
720
721 if (lsa_handle == NULL || sid == NULL || account == NULL)
722 return (NT_STATUS_INVALID_PARAMETER);
723
724 bzero(account, sizeof (smb_account_t));
725 bzero(sidbuf, SMB_SID_STRSZ);
726 smb_sid_tostr(sid, sidbuf);
727 smb_tracef("%s", sidbuf);
728
729 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
730 status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid,
731 account);
732 else
733 status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
734 account);
735
736 if (status == NT_STATUS_SUCCESS) {
737 if (!smb_account_validate(account)) {
738 smb_account_free(account);
739 status = NT_STATUS_NO_MEMORY;
740 } else {
741 smb_account_trace(account);
742 }
743 }
744
745 return (status);
746 }
747
748 /*
749 * lsar_lookup_sids1
750 */
751 static uint32_t
lsar_lookup_sids1(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)752 lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
753 smb_account_t *account)
754 {
755 struct mslsa_LookupSids arg;
756 struct mslsa_lup_sid_entry sid_entry;
757 struct mslsa_name_entry *name_entry;
758 struct mslsa_domain_entry *domain_entry;
759 uint32_t status = NT_STATUS_SUCCESS;
760 char *name;
761 int opnum = LSARPC_OPNUM_LookupSids;
762
763 bzero(&arg, sizeof (struct mslsa_LookupSids));
764 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
765 arg.lookup_level = LSA_LOOKUP_WKSTA;
766
767 sid_entry.psid = sid;
768 arg.lup_sid_table.n_entry = 1;
769 arg.lup_sid_table.entries = &sid_entry;
770
771 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
772 ndr_rpc_release(lsa_handle);
773 return (NT_STATUS_INVALID_PARAMETER);
774 }
775
776 if (arg.status != NT_STATUS_SUCCESS) {
777 ndr_rpc_status(lsa_handle, opnum, arg.status);
778 ndr_rpc_release(lsa_handle);
779 return (NT_SC_VALUE(arg.status));
780 }
781
782 if (arg.mapped_count == 0) {
783 ndr_rpc_release(lsa_handle);
784 return (NT_STATUS_NONE_MAPPED);
785 }
786
787 name_entry = &arg.name_table.entries[0];
788 if (name_entry->domain_ix != 0) {
789 ndr_rpc_release(lsa_handle);
790 return (NT_STATUS_NONE_MAPPED);
791 }
792
793 name = (char *)name_entry->name.str;
794 account->a_name = (name) ? strdup(name) : strdup("");
795 account->a_type = name_entry->sid_name_use;
796 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
797 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
798
799 domain_entry = &arg.domain_table->entries[0];
800 if ((name = (char *)domain_entry->domain_name.str) != NULL)
801 account->a_domain = strdup(name);
802 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
803
804 ndr_rpc_release(lsa_handle);
805 return (status);
806 }
807
808 /*
809 * lsar_lookup_sids2
810 */
811 static uint32_t
lsar_lookup_sids2(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)812 lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
813 smb_account_t *account)
814 {
815 struct lsar_lookup_sids2 arg;
816 struct lsar_name_entry2 *name_entry;
817 struct mslsa_lup_sid_entry sid_entry;
818 struct mslsa_domain_entry *domain_entry;
819 uint32_t status = NT_STATUS_SUCCESS;
820 char *name;
821 int opnum = LSARPC_OPNUM_LookupSids2;
822
823 bzero(&arg, sizeof (struct lsar_lookup_sids2));
824 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
825
826 sid_entry.psid = sid;
827 arg.lup_sid_table.n_entry = 1;
828 arg.lup_sid_table.entries = &sid_entry;
829 arg.lookup_level = LSA_LOOKUP_WKSTA;
830 arg.client_revision = LSA_CLIENT_REVISION_AD;
831
832 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
833 ndr_rpc_release(lsa_handle);
834 return (NT_STATUS_INVALID_PARAMETER);
835 }
836
837 if (arg.status != NT_STATUS_SUCCESS) {
838 ndr_rpc_status(lsa_handle, opnum, arg.status);
839 ndr_rpc_release(lsa_handle);
840 return (NT_SC_VALUE(arg.status));
841 }
842
843 if (arg.mapped_count == 0) {
844 ndr_rpc_release(lsa_handle);
845 return (NT_STATUS_NONE_MAPPED);
846 }
847
848 name_entry = &arg.name_table.entries[0];
849 if (name_entry->domain_ix != 0) {
850 ndr_rpc_release(lsa_handle);
851 return (NT_STATUS_NONE_MAPPED);
852 }
853
854 name = (char *)name_entry->name.str;
855 account->a_name = (name) ? strdup(name) : strdup("");
856 account->a_type = name_entry->sid_name_use;
857 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
858 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
859
860 domain_entry = &arg.domain_table->entries[0];
861 if ((name = (char *)domain_entry->domain_name.str) != NULL)
862 account->a_domain = strdup(name);
863 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
864
865 ndr_rpc_release(lsa_handle);
866 return (status);
867 }
868
869 /*
870 * lsar_lookup_sids3
871 *
872 * This function is only valid if the remote RPC server is a domain
873 * controller and requires the security extensions defined in MS-RPCE.
874 *
875 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
876 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
877 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
878 */
879 static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_sids3(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)880 lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
881 smb_account_t *account)
882 {
883 struct lsar_lookup_sids3 arg;
884 lsar_translated_name_ex_t *name_entry;
885 struct mslsa_lup_sid_entry sid_entry;
886 struct mslsa_domain_entry *domain_entry;
887 uint32_t status = NT_STATUS_SUCCESS;
888 char *name;
889 int opnum = LSARPC_OPNUM_LookupSids3;
890
891 bzero(&arg, sizeof (struct lsar_lookup_sids3));
892
893 sid_entry.psid = sid;
894 arg.lup_sid_table.n_entry = 1;
895 arg.lup_sid_table.entries = &sid_entry;
896 arg.lookup_level = LSA_LOOKUP_WKSTA;
897 arg.client_revision = LSA_CLIENT_REVISION_AD;
898
899 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
900 ndr_rpc_release(lsa_handle);
901 return (NT_STATUS_INVALID_PARAMETER);
902 }
903
904 if (arg.status != NT_STATUS_SUCCESS) {
905 ndr_rpc_status(lsa_handle, opnum, arg.status);
906 ndr_rpc_release(lsa_handle);
907 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
908 arg.status == NT_STATUS_INVALID_SERVER_STATE)
909 return (NT_STATUS_INVALID_PARAMETER);
910 return (NT_SC_VALUE(arg.status));
911 }
912
913 if (arg.mapped_count == 0) {
914 ndr_rpc_release(lsa_handle);
915 return (NT_STATUS_NONE_MAPPED);
916 }
917
918 name_entry = &arg.name_table.entries[0];
919 if (name_entry->domain_ix != 0) {
920 ndr_rpc_release(lsa_handle);
921 return (NT_STATUS_NONE_MAPPED);
922 }
923
924 name = (char *)name_entry->name.str;
925 account->a_name = (name) ? strdup(name) : strdup("");
926 account->a_type = name_entry->sid_name_use;
927 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
928 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
929
930 domain_entry = &arg.domain_table->entries[0];
931 if ((name = (char *)domain_entry->domain_name.str) != NULL)
932 account->a_domain = strdup(name);
933 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
934
935 ndr_rpc_release(lsa_handle);
936 return (status);
937 }
938
939 /*
940 * lsar_enum_accounts
941 *
942 * Enumerate the list of accounts (i.e. SIDs). Use the handle returned
943 * from lsa_open_policy2. The enum_context is used to support multiple
944 * calls to this enumeration function. It should be set to 0 on the
945 * first call. It will be updated by the domain controller and should
946 * simply be passed unchanged to subsequent calls until there are no
947 * more accounts. A warning status of 0x1A indicates that no more data
948 * is available. The list of accounts will be returned in accounts.
949 * This list is dynamically allocated using malloc, it should be freed
950 * by the caller when it is no longer required.
951 */
952 DWORD
lsar_enum_accounts(mlsvc_handle_t * lsa_handle,DWORD * enum_context,struct mslsa_EnumAccountBuf * accounts)953 lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
954 struct mslsa_EnumAccountBuf *accounts)
955 {
956 struct mslsa_EnumerateAccounts arg;
957 struct mslsa_AccountInfo *info;
958 int opnum;
959 int rc;
960 DWORD status;
961 DWORD n_entries;
962 DWORD i;
963 int nbytes;
964
965 if (lsa_handle == NULL || enum_context == NULL || accounts == NULL)
966 return (NT_STATUS_INTERNAL_ERROR);
967
968 accounts->entries_read = 0;
969 accounts->info = 0;
970
971 opnum = LSARPC_OPNUM_EnumerateAccounts;
972
973 bzero(&arg, sizeof (struct mslsa_EnumerateAccounts));
974 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
975 arg.enum_context = *enum_context;
976 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
977
978 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
979 if (rc == 0) {
980 status = arg.status;
981 if (arg.status != 0) {
982 if (arg.status == NT_STATUS_NO_MORE_ENTRIES) {
983 *enum_context = arg.enum_context;
984 } else {
985 ndr_rpc_status(lsa_handle, opnum, arg.status);
986 }
987 } else if (arg.enum_buf->entries_read != 0) {
988 n_entries = arg.enum_buf->entries_read;
989 nbytes = n_entries * sizeof (struct mslsa_AccountInfo);
990
991 if ((info = malloc(nbytes)) == NULL) {
992 ndr_rpc_release(lsa_handle);
993 return (NT_STATUS_NO_MEMORY);
994 }
995
996 for (i = 0; i < n_entries; ++i)
997 info[i].sid = (lsa_sid_t *)smb_sid_dup(
998 (smb_sid_t *)arg.enum_buf->info[i].sid);
999
1000 accounts->entries_read = n_entries;
1001 accounts->info = info;
1002 *enum_context = arg.enum_context;
1003 }
1004 } else {
1005 status = NT_STATUS_INVALID_PARAMETER;
1006 }
1007
1008 ndr_rpc_release(lsa_handle);
1009 return (status);
1010 }
1011
1012 /*
1013 * lsar_enum_trusted_domains
1014 *
1015 * Enumerate the list of trusted domains. Use the handle returned from
1016 * lsa_open_policy2. The enum_context is used to support multiple calls
1017 * to this enumeration function. It should be set to 0 on the first
1018 * call. It will be updated by the domain controller and should simply
1019 * be passed unchanged to subsequent calls until there are no more
1020 * domains.
1021 *
1022 * The trusted domains aren't actually returned here. They are added
1023 * to the NT domain database. After all of the trusted domains have
1024 * been discovered, the database can be interrogated to find all of
1025 * the trusted domains.
1026 */
1027 DWORD
lsar_enum_trusted_domains(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1028 lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1029 smb_trusted_domains_t *list)
1030 {
1031 struct mslsa_EnumTrustedDomain arg;
1032 int opnum;
1033 DWORD status;
1034
1035 if (list == NULL)
1036 return (NT_STATUS_INVALID_PARAMETER);
1037
1038 opnum = LSARPC_OPNUM_EnumTrustedDomain;
1039
1040 bzero(list, sizeof (smb_trusted_domains_t));
1041 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain));
1042 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1043 arg.enum_context = *enum_context;
1044 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1045
1046 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1047 status = NT_STATUS_INVALID_PARAMETER;
1048 } else if (arg.status != 0) {
1049 *enum_context = arg.enum_context;
1050 status = NT_SC_VALUE(arg.status);
1051
1052 /*
1053 * STATUS_NO_MORE_ENTRIES provides call
1054 * status but does not indicate an error.
1055 */
1056 if (status != NT_STATUS_NO_MORE_ENTRIES)
1057 ndr_rpc_status(lsa_handle, opnum, arg.status);
1058 } else if (arg.enum_buf->entries_read == 0) {
1059 *enum_context = arg.enum_context;
1060 status = 0;
1061 } else {
1062 lsar_set_trusted_domains(arg.enum_buf, list);
1063 *enum_context = arg.enum_context;
1064 status = 0;
1065 }
1066
1067 ndr_rpc_release(lsa_handle);
1068 return (status);
1069 }
1070
1071 DWORD
lsar_enum_trusted_domains_ex(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1072 lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1073 smb_trusted_domains_t *list)
1074 {
1075 struct mslsa_EnumTrustedDomainEx arg;
1076 int opnum;
1077 DWORD status;
1078
1079 if (list == NULL)
1080 return (NT_STATUS_INVALID_PARAMETER);
1081
1082 opnum = LSARPC_OPNUM_EnumTrustedDomainsEx;
1083
1084 bzero(list, sizeof (smb_trusted_domains_t));
1085 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx));
1086 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1087 arg.enum_context = *enum_context;
1088 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1089
1090 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1091 status = NT_STATUS_INVALID_PARAMETER;
1092 } else if (arg.status != 0) {
1093 *enum_context = arg.enum_context;
1094 status = NT_SC_VALUE(arg.status);
1095
1096 /*
1097 * STATUS_NO_MORE_ENTRIES provides call
1098 * status but does not indicate an error.
1099 */
1100 if (status != NT_STATUS_NO_MORE_ENTRIES)
1101 ndr_rpc_status(lsa_handle, opnum, arg.status);
1102 } else if (arg.enum_buf->entries_read == 0) {
1103 *enum_context = arg.enum_context;
1104 status = 0;
1105 } else {
1106 lsar_set_trusted_domains_ex(arg.enum_buf, list);
1107 *enum_context = arg.enum_context;
1108 status = 0;
1109 }
1110
1111 ndr_rpc_release(lsa_handle);
1112 return (status);
1113 }
1114
1115 /*
1116 * lsar_enum_privs_account
1117 *
1118 * Privileges enum? Need an account handle.
1119 */
1120 /*ARGSUSED*/
1121 int
lsar_enum_privs_account(mlsvc_handle_t * account_handle,smb_account_t * account)1122 lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
1123 {
1124 struct mslsa_EnumPrivsAccount arg;
1125 int opnum;
1126 int rc;
1127
1128 opnum = LSARPC_OPNUM_EnumPrivsAccount;
1129
1130 bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount));
1131 (void) memcpy(&arg.account_handle, &account_handle->handle,
1132 sizeof (mslsa_handle_t));
1133
1134 rc = ndr_rpc_call(account_handle, opnum, &arg);
1135 if ((rc == 0) && (arg.status != 0)) {
1136 ndr_rpc_status(account_handle, opnum, arg.status);
1137 rc = -1;
1138 }
1139 ndr_rpc_release(account_handle);
1140 return (rc);
1141 }
1142
1143 /*
1144 * lsar_lookup_priv_value
1145 *
1146 * Map a privilege name to a local unique id (LUID). Privilege names
1147 * are consistent across the network. LUIDs are machine specific.
1148 * This function provides the means to map a privilege name to the
1149 * LUID used by a remote server to represent it. The handle here is
1150 * a policy handle.
1151 */
1152 int
lsar_lookup_priv_value(mlsvc_handle_t * lsa_handle,char * name,struct ms_luid * luid)1153 lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
1154 struct ms_luid *luid)
1155 {
1156 struct mslsa_LookupPrivValue arg;
1157 int opnum;
1158 int rc;
1159 size_t length;
1160
1161 if (lsa_handle == NULL || name == NULL || luid == NULL)
1162 return (-1);
1163
1164 opnum = LSARPC_OPNUM_LookupPrivValue;
1165
1166 bzero(&arg, sizeof (struct mslsa_LookupPrivValue));
1167 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1168
1169 length = smb_wcequiv_strlen(name);
1170 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
1171 length += sizeof (smb_wchar_t);
1172
1173 arg.name.length = length;
1174 arg.name.allosize = length;
1175 arg.name.str = (unsigned char *)name;
1176
1177 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1178 if (rc == 0) {
1179 if (arg.status != 0)
1180 rc = -1;
1181 else
1182 (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid));
1183 }
1184
1185 ndr_rpc_release(lsa_handle);
1186 return (rc);
1187 }
1188
1189 /*
1190 * lsar_lookup_priv_name
1191 *
1192 * Map a local unique id (LUID) to a privilege name. Privilege names
1193 * are consistent across the network. LUIDs are machine specific.
1194 * This function the means to map the LUID used by a remote server to
1195 * the appropriate privilege name. The handle here is a policy handle.
1196 */
1197 int
lsar_lookup_priv_name(mlsvc_handle_t * lsa_handle,struct ms_luid * luid,char * name,int namelen)1198 lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid,
1199 char *name, int namelen)
1200 {
1201 struct mslsa_LookupPrivName arg;
1202 int opnum;
1203 int rc;
1204
1205 if (lsa_handle == NULL || luid == NULL || name == NULL)
1206 return (-1);
1207
1208 opnum = LSARPC_OPNUM_LookupPrivName;
1209
1210 bzero(&arg, sizeof (struct mslsa_LookupPrivName));
1211 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1212 (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid));
1213
1214 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1215 if (rc == 0) {
1216 if (arg.status != 0)
1217 rc = -1;
1218 else
1219 (void) strlcpy(name, (char const *)arg.name->str,
1220 namelen);
1221 }
1222
1223 ndr_rpc_release(lsa_handle);
1224 return (rc);
1225 }
1226
1227 /*
1228 * lsar_lookup_priv_display_name
1229 *
1230 * Map a privilege name to a privilege display name. The input handle
1231 * should be an LSA policy handle and the name would normally be one
1232 * of the privileges defined in smb_privilege.h
1233 *
1234 * There's something peculiar about the return status from NT servers,
1235 * it's not always present. So for now, I'm ignoring the status in the
1236 * RPC response.
1237 *
1238 * Returns NT status codes.
1239 */
1240 DWORD
lsar_lookup_priv_display_name(mlsvc_handle_t * lsa_handle,char * name,char * display_name,int display_len)1241 lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
1242 char *display_name, int display_len)
1243 {
1244 struct mslsa_LookupPrivDisplayName arg;
1245 int opnum;
1246 size_t length;
1247 DWORD status;
1248
1249 if (lsa_handle == NULL || name == NULL || display_name == NULL)
1250 return (NT_STATUS_INVALID_PARAMETER);
1251
1252 opnum = LSARPC_OPNUM_LookupPrivDisplayName;
1253
1254 bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName));
1255 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1256
1257 length = smb_wcequiv_strlen(name);
1258 arg.name.length = length;
1259 arg.name.allosize = length;
1260 arg.name.str = (unsigned char *)name;
1261
1262 arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
1263 arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
1264
1265 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0)
1266 status = NT_STATUS_INVALID_PARAMETER;
1267 #if 0
1268 else if (arg.status != 0)
1269 status = NT_SC_VALUE(arg.status);
1270 #endif
1271 else {
1272 (void) strlcpy(display_name,
1273 (char const *)arg.display_name->str, display_len);
1274 status = NT_STATUS_SUCCESS;
1275 }
1276
1277 ndr_rpc_release(lsa_handle);
1278 return (status);
1279 }
1280
1281 static void
lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx * enum_buf,smb_trusted_domains_t * list)1282 lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf,
1283 smb_trusted_domains_t *list)
1284 {
1285 char sidstr[SMB_SID_STRSZ];
1286 int i;
1287
1288 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1289 return;
1290
1291 list->td_num = 0;
1292 list->td_domains = calloc(enum_buf->entries_read,
1293 sizeof (smb_domain_t));
1294
1295 if (list->td_domains == NULL)
1296 return;
1297
1298 list->td_num = enum_buf->entries_read;
1299 for (i = 0; i < list->td_num; i++) {
1300 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1301 smb_domain_set_trust_info(
1302 sidstr,
1303 (char *)enum_buf->info[i].nb_name.str,
1304 (char *)enum_buf->info[i].dns_name.str,
1305 enum_buf->info[i].trust_direction,
1306 enum_buf->info[i].trust_type,
1307 enum_buf->info[i].trust_attrs,
1308 &list->td_domains[i]);
1309 }
1310 }
1311
1312 static void
lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf * enum_buf,smb_trusted_domains_t * list)1313 lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
1314 smb_trusted_domains_t *list)
1315 {
1316 char sidstr[SMB_SID_STRSZ];
1317 int i;
1318
1319 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1320 return;
1321
1322 list->td_num = 0;
1323 list->td_domains = calloc(enum_buf->entries_read,
1324 sizeof (smb_domain_t));
1325
1326 if (list->td_domains == NULL)
1327 return;
1328
1329 list->td_num = enum_buf->entries_read;
1330 for (i = 0; i < list->td_num; i++) {
1331 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1332 smb_domain_set_trust_info(
1333 sidstr, (char *)enum_buf->info[i].name.str,
1334 "", 0, 0, 0, &list->td_domains[i]);
1335 }
1336 }
1337
1338 static void
smb_account_trace(const smb_account_t * info)1339 smb_account_trace(const smb_account_t *info)
1340 {
1341 char sidbuf[SMB_SID_STRSZ];
1342
1343 bzero(sidbuf, SMB_SID_STRSZ);
1344 smb_sid_tostr(info->a_sid, sidbuf);
1345
1346 smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name,
1347 sidbuf, info->a_rid, smb_sid_type2str(info->a_type));
1348 }
1349