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