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