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 2018 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 <smb/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 lsa_names_t names;
387 char *p;
388 uint32_t length;
389 uint32_t status = NT_STATUS_INVALID_PARAMETER;
390 int n_op = (sizeof (ops) / sizeof (ops[0]));
391 int i;
392
393 if (lsa_handle == NULL || name == NULL || info == NULL)
394 return (NT_STATUS_INVALID_PARAMETER);
395
396 bzero(info, sizeof (smb_account_t));
397
398 /*
399 * Windows 2000 (or later) doesn't like an LSA lookup for
400 * DOMAIN\Administrator.
401 */
402 if ((p = strchr(name, '\\')) != 0) {
403 ++p;
404
405 if (strcasecmp(p, "administrator") == 0)
406 name = p;
407 }
408
409 length = smb_wcequiv_strlen(name);
410 names.name[0].length = length;
411 names.name[0].allosize = length;
412 names.name[0].str = (unsigned char *)name;
413 names.n_entry = 1;
414
415 for (i = 0; i < n_op; ++i) {
416 ndr_rpc_set_nonull(lsa_handle);
417 status = (*ops[i])(lsa_handle, &names, info);
418
419 if (status != NT_STATUS_INVALID_PARAMETER)
420 break;
421 }
422
423 if (status == NT_STATUS_SUCCESS) {
424 info->a_name = lsar_get_username(name);
425
426 if (!smb_account_validate(info)) {
427 smb_account_free(info);
428 status = NT_STATUS_NO_MEMORY;
429 } else {
430 smb_account_trace(info);
431 }
432 }
433
434 return (status);
435 }
436
437 /*
438 * The name may be in one of the following forms:
439 *
440 * domain\username
441 * domain/username
442 * username
443 * username@domain
444 *
445 * Return a strdup'd copy of the username. The caller is responsible
446 * for freeing the allocated memory.
447 */
448 static char *
lsar_get_username(const char * name)449 lsar_get_username(const char *name)
450 {
451 char tmp[MAXNAMELEN];
452 char *dp = NULL;
453 char *np = NULL;
454
455 (void) strlcpy(tmp, name, MAXNAMELEN);
456 smb_name_parse(tmp, &np, &dp);
457
458 if (dp != NULL && np != NULL)
459 return (strdup(np));
460 else
461 return (strdup(name));
462 }
463
464 /*
465 * lsar_lookup_names1
466 *
467 * Lookup a name and obtain the domain and user rid.
468 *
469 * Note: NT returns an error if the mapped_count is non-zero when the RPC
470 * is called.
471 *
472 * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
473 */
474 static uint32_t
lsar_lookup_names1(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)475 lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
476 smb_account_t *info)
477 {
478 struct mslsa_LookupNames arg;
479 struct mslsa_rid_entry *rid_entry;
480 struct mslsa_domain_entry *domain_entry;
481 uint32_t status = NT_STATUS_SUCCESS;
482 char *domname;
483 int opnum = LSARPC_OPNUM_LookupNames;
484
485 bzero(&arg, sizeof (struct mslsa_LookupNames));
486 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
487 arg.lookup_level = LSA_LOOKUP_WKSTA;
488 arg.name_table = (struct mslsa_lup_name_table *)names;
489
490 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
491 ndr_rpc_release(lsa_handle);
492 return (NT_STATUS_INVALID_PARAMETER);
493 }
494
495 if (arg.status != NT_STATUS_SUCCESS) {
496 ndr_rpc_status(lsa_handle, opnum, arg.status);
497 ndr_rpc_release(lsa_handle);
498 return (NT_SC_VALUE(arg.status));
499 }
500
501 if (arg.mapped_count == 0) {
502 ndr_rpc_release(lsa_handle);
503 return (NT_STATUS_NONE_MAPPED);
504 }
505
506 rid_entry = &arg.translated_sids.rids[0];
507 if (rid_entry->domain_index != 0) {
508 ndr_rpc_release(lsa_handle);
509 return (NT_STATUS_NONE_MAPPED);
510 }
511
512 domain_entry = &arg.domain_table->entries[0];
513
514 info->a_type = rid_entry->sid_name_use;
515 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
516 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
517 info->a_domain = strdup(domname);
518 info->a_rid = rid_entry->rid;
519 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
520
521 ndr_rpc_release(lsa_handle);
522 return (status);
523 }
524
525 /*
526 * lsar_lookup_names2
527 */
528 static uint32_t
lsar_lookup_names2(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)529 lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
530 smb_account_t *info)
531 {
532 struct lsar_LookupNames2 arg;
533 struct lsar_rid_entry2 *rid_entry;
534 struct mslsa_domain_entry *domain_entry;
535 uint32_t status = NT_STATUS_SUCCESS;
536 char *domname;
537 int opnum = LSARPC_OPNUM_LookupNames2;
538
539 bzero(&arg, sizeof (struct lsar_LookupNames2));
540 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
541 arg.lookup_level = LSA_LOOKUP_WKSTA;
542 arg.client_revision = LSA_CLIENT_REVISION_AD;
543 arg.name_table = (struct mslsa_lup_name_table *)names;
544
545 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
546 ndr_rpc_release(lsa_handle);
547 return (NT_STATUS_INVALID_PARAMETER);
548 }
549
550 if (arg.status != NT_STATUS_SUCCESS) {
551 ndr_rpc_status(lsa_handle, opnum, arg.status);
552 ndr_rpc_release(lsa_handle);
553 return (NT_SC_VALUE(arg.status));
554 }
555
556 if (arg.mapped_count == 0) {
557 ndr_rpc_release(lsa_handle);
558 return (NT_STATUS_NONE_MAPPED);
559 }
560
561 rid_entry = &arg.translated_sids.rids[0];
562 if (rid_entry->domain_index != 0) {
563 ndr_rpc_release(lsa_handle);
564 return (NT_STATUS_NONE_MAPPED);
565 }
566
567 domain_entry = &arg.domain_table->entries[0];
568
569 info->a_type = rid_entry->sid_name_use;
570 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
571 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
572 info->a_domain = strdup(domname);
573 info->a_rid = rid_entry->rid;
574 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
575
576 ndr_rpc_release(lsa_handle);
577 return (status);
578 }
579
580 /*
581 * lsar_lookup_names3
582 */
583 static uint32_t
lsar_lookup_names3(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)584 lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
585 smb_account_t *info)
586 {
587 struct lsar_LookupNames3 arg;
588 lsar_translated_sid_ex2_t *sid_entry;
589 struct mslsa_domain_entry *domain_entry;
590 uint32_t status = NT_STATUS_SUCCESS;
591 char *domname;
592 int opnum = LSARPC_OPNUM_LookupNames3;
593
594 bzero(&arg, sizeof (struct lsar_LookupNames3));
595 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
596 arg.lookup_level = LSA_LOOKUP_WKSTA;
597 arg.client_revision = LSA_CLIENT_REVISION_AD;
598 arg.name_table = (struct mslsa_lup_name_table *)names;
599
600 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
601 ndr_rpc_release(lsa_handle);
602 return (NT_STATUS_INVALID_PARAMETER);
603 }
604
605 if (arg.status != NT_STATUS_SUCCESS) {
606 ndr_rpc_status(lsa_handle, opnum, arg.status);
607 ndr_rpc_release(lsa_handle);
608 return (NT_SC_VALUE(arg.status));
609 }
610
611 if (arg.mapped_count == 0) {
612 ndr_rpc_release(lsa_handle);
613 return (NT_STATUS_NONE_MAPPED);
614 }
615
616 sid_entry = &arg.translated_sids.sids[0];
617 if (sid_entry->domain_index != 0) {
618 ndr_rpc_release(lsa_handle);
619 return (NT_STATUS_NONE_MAPPED);
620 }
621
622 domain_entry = &arg.domain_table->entries[0];
623
624 info->a_type = sid_entry->sid_name_use;
625 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
626 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
627 info->a_domain = strdup(domname);
628 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
629 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
630
631 ndr_rpc_release(lsa_handle);
632 return (status);
633 }
634
635 /*
636 * lsar_lookup_names4
637 *
638 * This function is only valid if the remote RPC server is a domain
639 * controller and requires the security extensions defined in MS-RPCE.
640 *
641 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
642 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
643 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
644 */
645 static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_names4(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)646 lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
647 smb_account_t *info)
648 {
649 struct lsar_LookupNames4 arg;
650 lsar_translated_sid_ex2_t *sid_entry;
651 struct mslsa_domain_entry *domain_entry;
652 uint32_t status = NT_STATUS_SUCCESS;
653 char *domname;
654 int opnum = LSARPC_OPNUM_LookupNames4;
655
656 bzero(&arg, sizeof (struct lsar_LookupNames4));
657 arg.lookup_level = LSA_LOOKUP_WKSTA;
658 arg.client_revision = LSA_CLIENT_REVISION_AD;
659 arg.name_table = (struct mslsa_lup_name_table *)names;
660
661 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
662 ndr_rpc_release(lsa_handle);
663 return (NT_STATUS_INVALID_PARAMETER);
664 }
665
666 if (arg.status != NT_STATUS_SUCCESS) {
667 ndr_rpc_status(lsa_handle, opnum, arg.status);
668 ndr_rpc_release(lsa_handle);
669 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
670 arg.status == NT_STATUS_INVALID_SERVER_STATE)
671 return (NT_STATUS_INVALID_PARAMETER);
672 return (NT_SC_VALUE(arg.status));
673 }
674
675 if (arg.mapped_count == 0) {
676 ndr_rpc_release(lsa_handle);
677 return (NT_STATUS_NONE_MAPPED);
678 }
679
680 sid_entry = &arg.translated_sids.sids[0];
681 if (sid_entry->domain_index != 0) {
682 ndr_rpc_release(lsa_handle);
683 return (NT_STATUS_NONE_MAPPED);
684 }
685
686 domain_entry = &arg.domain_table->entries[0];
687
688 info->a_type = sid_entry->sid_name_use;
689 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
690 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
691 info->a_domain = strdup(domname);
692 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
693 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
694
695 ndr_rpc_release(lsa_handle);
696 return (status);
697 }
698
699 /*
700 * Lookup a sid and obtain the domain sid and account name.
701 * This is a wrapper for the various lookup sid RPCs.
702 */
703 uint32_t
lsar_lookup_sids(mlsvc_handle_t * lsa_handle,smb_sid_t * sid,smb_account_t * account)704 lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid,
705 smb_account_t *account)
706 {
707 char sidbuf[SMB_SID_STRSZ];
708 uint32_t status;
709
710 if (lsa_handle == NULL || sid == NULL || account == NULL)
711 return (NT_STATUS_INVALID_PARAMETER);
712
713 bzero(account, sizeof (smb_account_t));
714 bzero(sidbuf, SMB_SID_STRSZ);
715 smb_sid_tostr(sid, sidbuf);
716 smb_tracef("%s", sidbuf);
717
718 status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account);
719 if (status == RPC_NT_PROCNUM_OUT_OF_RANGE)
720 status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
721 account);
722
723 if (status == NT_STATUS_SUCCESS) {
724 if (!smb_account_validate(account)) {
725 smb_account_free(account);
726 status = NT_STATUS_NO_MEMORY;
727 } else {
728 smb_account_trace(account);
729 }
730 }
731
732 return (status);
733 }
734
735 /*
736 * lsar_lookup_sids1
737 */
738 static uint32_t
lsar_lookup_sids1(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)739 lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
740 smb_account_t *account)
741 {
742 struct mslsa_LookupSids arg;
743 struct mslsa_lup_sid_entry sid_entry;
744 struct mslsa_name_entry *name_entry;
745 struct mslsa_domain_entry *domain_entry;
746 uint32_t status = NT_STATUS_SUCCESS;
747 char *name;
748 int opnum = LSARPC_OPNUM_LookupSids;
749
750 bzero(&arg, sizeof (struct mslsa_LookupSids));
751 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
752 arg.lookup_level = LSA_LOOKUP_WKSTA;
753
754 sid_entry.psid = sid;
755 arg.lup_sid_table.n_entry = 1;
756 arg.lup_sid_table.entries = &sid_entry;
757
758 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
759 ndr_rpc_release(lsa_handle);
760 return (NT_STATUS_INVALID_PARAMETER);
761 }
762
763 if (arg.status != NT_STATUS_SUCCESS) {
764 ndr_rpc_status(lsa_handle, opnum, arg.status);
765 ndr_rpc_release(lsa_handle);
766 return (NT_SC_VALUE(arg.status));
767 }
768
769 if (arg.mapped_count == 0) {
770 ndr_rpc_release(lsa_handle);
771 return (NT_STATUS_NONE_MAPPED);
772 }
773
774 name_entry = &arg.name_table.entries[0];
775 if (name_entry->domain_ix != 0) {
776 ndr_rpc_release(lsa_handle);
777 return (NT_STATUS_NONE_MAPPED);
778 }
779
780 name = (char *)name_entry->name.str;
781 account->a_name = (name) ? strdup(name) : strdup("");
782 account->a_type = name_entry->sid_name_use;
783 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
784 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
785
786 domain_entry = &arg.domain_table->entries[0];
787 if ((name = (char *)domain_entry->domain_name.str) != NULL)
788 account->a_domain = strdup(name);
789 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
790
791 ndr_rpc_release(lsa_handle);
792 return (status);
793 }
794
795 /*
796 * lsar_lookup_sids2
797 */
798 static uint32_t
lsar_lookup_sids2(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)799 lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
800 smb_account_t *account)
801 {
802 struct lsar_lookup_sids2 arg;
803 struct lsar_name_entry2 *name_entry;
804 struct mslsa_lup_sid_entry sid_entry;
805 struct mslsa_domain_entry *domain_entry;
806 uint32_t status = NT_STATUS_SUCCESS;
807 char *name;
808 int opnum = LSARPC_OPNUM_LookupSids2;
809
810 bzero(&arg, sizeof (struct lsar_lookup_sids2));
811 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
812
813 sid_entry.psid = sid;
814 arg.lup_sid_table.n_entry = 1;
815 arg.lup_sid_table.entries = &sid_entry;
816 arg.lookup_level = LSA_LOOKUP_WKSTA;
817 arg.client_revision = LSA_CLIENT_REVISION_AD;
818
819 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
820 ndr_rpc_release(lsa_handle);
821 return (NT_STATUS_INVALID_PARAMETER);
822 }
823
824 if (arg.status != NT_STATUS_SUCCESS) {
825 ndr_rpc_status(lsa_handle, opnum, arg.status);
826 ndr_rpc_release(lsa_handle);
827 return (NT_SC_VALUE(arg.status));
828 }
829
830 if (arg.mapped_count == 0) {
831 ndr_rpc_release(lsa_handle);
832 return (NT_STATUS_NONE_MAPPED);
833 }
834
835 name_entry = &arg.name_table.entries[0];
836 if (name_entry->domain_ix != 0) {
837 ndr_rpc_release(lsa_handle);
838 return (NT_STATUS_NONE_MAPPED);
839 }
840
841 name = (char *)name_entry->name.str;
842 account->a_name = (name) ? strdup(name) : strdup("");
843 account->a_type = name_entry->sid_name_use;
844 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
845 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
846
847 domain_entry = &arg.domain_table->entries[0];
848 if ((name = (char *)domain_entry->domain_name.str) != NULL)
849 account->a_domain = strdup(name);
850 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
851
852 ndr_rpc_release(lsa_handle);
853 return (status);
854 }
855
856 /*
857 * lsar_lookup_sids3
858 *
859 * This function is only valid if the remote RPC server is a domain
860 * controller and requires the security extensions defined in MS-RPCE.
861 *
862 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
863 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
864 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
865 */
866 static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_sids3(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)867 lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
868 smb_account_t *account)
869 {
870 struct lsar_lookup_sids3 arg;
871 lsar_translated_name_ex_t *name_entry;
872 struct mslsa_lup_sid_entry sid_entry;
873 struct mslsa_domain_entry *domain_entry;
874 uint32_t status = NT_STATUS_SUCCESS;
875 char *name;
876 int opnum = LSARPC_OPNUM_LookupSids3;
877
878 bzero(&arg, sizeof (struct lsar_lookup_sids3));
879
880 sid_entry.psid = sid;
881 arg.lup_sid_table.n_entry = 1;
882 arg.lup_sid_table.entries = &sid_entry;
883 arg.lookup_level = LSA_LOOKUP_WKSTA;
884 arg.client_revision = LSA_CLIENT_REVISION_AD;
885
886 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
887 ndr_rpc_release(lsa_handle);
888 return (NT_STATUS_INVALID_PARAMETER);
889 }
890
891 if (arg.status != NT_STATUS_SUCCESS) {
892 ndr_rpc_status(lsa_handle, opnum, arg.status);
893 ndr_rpc_release(lsa_handle);
894 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
895 arg.status == NT_STATUS_INVALID_SERVER_STATE)
896 return (NT_STATUS_INVALID_PARAMETER);
897 return (NT_SC_VALUE(arg.status));
898 }
899
900 if (arg.mapped_count == 0) {
901 ndr_rpc_release(lsa_handle);
902 return (NT_STATUS_NONE_MAPPED);
903 }
904
905 name_entry = &arg.name_table.entries[0];
906 if (name_entry->domain_ix != 0) {
907 ndr_rpc_release(lsa_handle);
908 return (NT_STATUS_NONE_MAPPED);
909 }
910
911 name = (char *)name_entry->name.str;
912 account->a_name = (name) ? strdup(name) : strdup("");
913 account->a_type = name_entry->sid_name_use;
914 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
915 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
916
917 domain_entry = &arg.domain_table->entries[0];
918 if ((name = (char *)domain_entry->domain_name.str) != NULL)
919 account->a_domain = strdup(name);
920 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
921
922 ndr_rpc_release(lsa_handle);
923 return (status);
924 }
925
926 /*
927 * lsar_enum_accounts
928 *
929 * Enumerate the list of accounts (i.e. SIDs). Use the handle returned
930 * from lsa_open_policy2. The enum_context is used to support multiple
931 * calls to this enumeration function. It should be set to 0 on the
932 * first call. It will be updated by the domain controller and should
933 * simply be passed unchanged to subsequent calls until there are no
934 * more accounts. A warning status of 0x1A indicates that no more data
935 * is available. The list of accounts will be returned in accounts.
936 * This list is dynamically allocated using malloc, it should be freed
937 * by the caller when it is no longer required.
938 */
939 DWORD
lsar_enum_accounts(mlsvc_handle_t * lsa_handle,DWORD * enum_context,struct mslsa_EnumAccountBuf * accounts)940 lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
941 struct mslsa_EnumAccountBuf *accounts)
942 {
943 struct mslsa_EnumerateAccounts arg;
944 struct mslsa_AccountInfo *info;
945 int opnum;
946 int rc;
947 DWORD status;
948 DWORD n_entries;
949 DWORD i;
950 int nbytes;
951
952 if (lsa_handle == NULL || enum_context == NULL || accounts == NULL)
953 return (NT_STATUS_INTERNAL_ERROR);
954
955 accounts->entries_read = 0;
956 accounts->info = 0;
957
958 opnum = LSARPC_OPNUM_EnumerateAccounts;
959
960 bzero(&arg, sizeof (struct mslsa_EnumerateAccounts));
961 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
962 arg.enum_context = *enum_context;
963 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
964
965 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
966 if (rc == 0) {
967 status = arg.status;
968 if (arg.status != 0) {
969 if (arg.status == NT_STATUS_NO_MORE_ENTRIES) {
970 *enum_context = arg.enum_context;
971 } else {
972 ndr_rpc_status(lsa_handle, opnum, arg.status);
973 }
974 } else if (arg.enum_buf->entries_read != 0) {
975 n_entries = arg.enum_buf->entries_read;
976 nbytes = n_entries * sizeof (struct mslsa_AccountInfo);
977
978 if ((info = malloc(nbytes)) == NULL) {
979 ndr_rpc_release(lsa_handle);
980 return (NT_STATUS_NO_MEMORY);
981 }
982
983 for (i = 0; i < n_entries; ++i)
984 info[i].sid = (lsa_sid_t *)smb_sid_dup(
985 (smb_sid_t *)arg.enum_buf->info[i].sid);
986
987 accounts->entries_read = n_entries;
988 accounts->info = info;
989 *enum_context = arg.enum_context;
990 }
991 } else {
992 status = NT_STATUS_INVALID_PARAMETER;
993 }
994
995 ndr_rpc_release(lsa_handle);
996 return (status);
997 }
998
999 /*
1000 * lsar_enum_trusted_domains
1001 *
1002 * Enumerate the list of trusted domains. Use the handle returned from
1003 * lsa_open_policy2. The enum_context is used to support multiple calls
1004 * to this enumeration function. It should be set to 0 on the first
1005 * call. It will be updated by the domain controller and should simply
1006 * be passed unchanged to subsequent calls until there are no more
1007 * domains.
1008 *
1009 * The trusted domains aren't actually returned here. They are added
1010 * to the NT domain database. After all of the trusted domains have
1011 * been discovered, the database can be interrogated to find all of
1012 * the trusted domains.
1013 */
1014 DWORD
lsar_enum_trusted_domains(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1015 lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1016 smb_trusted_domains_t *list)
1017 {
1018 struct mslsa_EnumTrustedDomain arg;
1019 int opnum;
1020 DWORD status;
1021
1022 if (list == NULL)
1023 return (NT_STATUS_INVALID_PARAMETER);
1024
1025 opnum = LSARPC_OPNUM_EnumTrustedDomain;
1026
1027 bzero(list, sizeof (smb_trusted_domains_t));
1028 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain));
1029 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1030 arg.enum_context = *enum_context;
1031 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1032
1033 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1034 status = NT_STATUS_INVALID_PARAMETER;
1035 } else if (arg.status != 0) {
1036 *enum_context = arg.enum_context;
1037 status = NT_SC_VALUE(arg.status);
1038
1039 /*
1040 * STATUS_NO_MORE_ENTRIES provides call
1041 * status but does not indicate an error.
1042 */
1043 if (status != NT_STATUS_NO_MORE_ENTRIES)
1044 ndr_rpc_status(lsa_handle, opnum, arg.status);
1045 } else if (arg.enum_buf->entries_read == 0) {
1046 *enum_context = arg.enum_context;
1047 status = 0;
1048 } else {
1049 lsar_set_trusted_domains(arg.enum_buf, list);
1050 *enum_context = arg.enum_context;
1051 status = 0;
1052 }
1053
1054 ndr_rpc_release(lsa_handle);
1055 return (status);
1056 }
1057
1058 DWORD
lsar_enum_trusted_domains_ex(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1059 lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1060 smb_trusted_domains_t *list)
1061 {
1062 struct mslsa_EnumTrustedDomainEx arg;
1063 int opnum;
1064 DWORD status;
1065
1066 if (list == NULL)
1067 return (NT_STATUS_INVALID_PARAMETER);
1068
1069 opnum = LSARPC_OPNUM_EnumTrustedDomainsEx;
1070
1071 bzero(list, sizeof (smb_trusted_domains_t));
1072 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx));
1073 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1074 arg.enum_context = *enum_context;
1075 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1076
1077 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1078 status = NT_STATUS_INVALID_PARAMETER;
1079 } else if (arg.status != 0) {
1080 *enum_context = arg.enum_context;
1081 status = NT_SC_VALUE(arg.status);
1082
1083 /*
1084 * STATUS_NO_MORE_ENTRIES provides call
1085 * status but does not indicate an error.
1086 */
1087 if (status != NT_STATUS_NO_MORE_ENTRIES)
1088 ndr_rpc_status(lsa_handle, opnum, arg.status);
1089 } else if (arg.enum_buf->entries_read == 0) {
1090 *enum_context = arg.enum_context;
1091 status = 0;
1092 } else {
1093 lsar_set_trusted_domains_ex(arg.enum_buf, list);
1094 *enum_context = arg.enum_context;
1095 status = 0;
1096 }
1097
1098 ndr_rpc_release(lsa_handle);
1099 return (status);
1100 }
1101
1102 /*
1103 * lsar_enum_privs_account
1104 *
1105 * Privileges enum? Need an account handle.
1106 */
1107 /*ARGSUSED*/
1108 int
lsar_enum_privs_account(mlsvc_handle_t * account_handle,smb_account_t * account)1109 lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
1110 {
1111 struct mslsa_EnumPrivsAccount arg;
1112 int opnum;
1113 int rc;
1114
1115 opnum = LSARPC_OPNUM_EnumPrivsAccount;
1116
1117 bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount));
1118 (void) memcpy(&arg.account_handle, &account_handle->handle,
1119 sizeof (mslsa_handle_t));
1120
1121 rc = ndr_rpc_call(account_handle, opnum, &arg);
1122 if ((rc == 0) && (arg.status != 0)) {
1123 ndr_rpc_status(account_handle, opnum, arg.status);
1124 rc = -1;
1125 }
1126 ndr_rpc_release(account_handle);
1127 return (rc);
1128 }
1129
1130 /*
1131 * lsar_lookup_priv_value
1132 *
1133 * Map a privilege name to a local unique id (LUID). Privilege names
1134 * are consistent across the network. LUIDs are machine specific.
1135 * This function provides the means to map a privilege name to the
1136 * LUID used by a remote server to represent it. The handle here is
1137 * a policy handle.
1138 */
1139 int
lsar_lookup_priv_value(mlsvc_handle_t * lsa_handle,char * name,struct ms_luid * luid)1140 lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
1141 struct ms_luid *luid)
1142 {
1143 struct mslsa_LookupPrivValue arg;
1144 int opnum;
1145 int rc;
1146 size_t length;
1147
1148 if (lsa_handle == NULL || name == NULL || luid == NULL)
1149 return (-1);
1150
1151 opnum = LSARPC_OPNUM_LookupPrivValue;
1152
1153 bzero(&arg, sizeof (struct mslsa_LookupPrivValue));
1154 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1155
1156 length = smb_wcequiv_strlen(name);
1157 length += sizeof (smb_wchar_t);
1158
1159 arg.name.length = length;
1160 arg.name.allosize = length;
1161 arg.name.str = (unsigned char *)name;
1162
1163 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1164 if (rc == 0) {
1165 if (arg.status != 0)
1166 rc = -1;
1167 else
1168 (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid));
1169 }
1170
1171 ndr_rpc_release(lsa_handle);
1172 return (rc);
1173 }
1174
1175 /*
1176 * lsar_lookup_priv_name
1177 *
1178 * Map a local unique id (LUID) to a privilege name. Privilege names
1179 * are consistent across the network. LUIDs are machine specific.
1180 * This function the means to map the LUID used by a remote server to
1181 * the appropriate privilege name. The handle here is a policy handle.
1182 */
1183 int
lsar_lookup_priv_name(mlsvc_handle_t * lsa_handle,struct ms_luid * luid,char * name,int namelen)1184 lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid,
1185 char *name, int namelen)
1186 {
1187 struct mslsa_LookupPrivName arg;
1188 int opnum;
1189 int rc;
1190
1191 if (lsa_handle == NULL || luid == NULL || name == NULL)
1192 return (-1);
1193
1194 opnum = LSARPC_OPNUM_LookupPrivName;
1195
1196 bzero(&arg, sizeof (struct mslsa_LookupPrivName));
1197 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1198 (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid));
1199
1200 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1201 if (rc == 0) {
1202 if (arg.status != 0)
1203 rc = -1;
1204 else
1205 (void) strlcpy(name, (char const *)arg.name->str,
1206 namelen);
1207 }
1208
1209 ndr_rpc_release(lsa_handle);
1210 return (rc);
1211 }
1212
1213 /*
1214 * lsar_lookup_priv_display_name
1215 *
1216 * Map a privilege name to a privilege display name. The input handle
1217 * should be an LSA policy handle and the name would normally be one
1218 * of the privileges defined in smb_privilege.h
1219 *
1220 * There's something peculiar about the return status from NT servers,
1221 * it's not always present. So for now, I'm ignoring the status in the
1222 * RPC response.
1223 *
1224 * Returns NT status codes.
1225 */
1226 DWORD
lsar_lookup_priv_display_name(mlsvc_handle_t * lsa_handle,char * name,char * display_name,int display_len)1227 lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
1228 char *display_name, int display_len)
1229 {
1230 struct mslsa_LookupPrivDisplayName arg;
1231 int opnum;
1232 size_t length;
1233 DWORD status;
1234
1235 if (lsa_handle == NULL || name == NULL || display_name == NULL)
1236 return (NT_STATUS_INVALID_PARAMETER);
1237
1238 opnum = LSARPC_OPNUM_LookupPrivDisplayName;
1239
1240 bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName));
1241 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1242
1243 length = smb_wcequiv_strlen(name);
1244 arg.name.length = length;
1245 arg.name.allosize = length;
1246 arg.name.str = (unsigned char *)name;
1247
1248 arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
1249 arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
1250
1251 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0)
1252 status = NT_STATUS_INVALID_PARAMETER;
1253 #if 0
1254 else if (arg.status != 0)
1255 status = NT_SC_VALUE(arg.status);
1256 #endif
1257 else {
1258 (void) strlcpy(display_name,
1259 (char const *)arg.display_name->str, display_len);
1260 status = NT_STATUS_SUCCESS;
1261 }
1262
1263 ndr_rpc_release(lsa_handle);
1264 return (status);
1265 }
1266
1267 static void
lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx * enum_buf,smb_trusted_domains_t * list)1268 lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf,
1269 smb_trusted_domains_t *list)
1270 {
1271 char sidstr[SMB_SID_STRSZ];
1272 int i;
1273
1274 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1275 return;
1276
1277 list->td_num = 0;
1278 list->td_domains = calloc(enum_buf->entries_read,
1279 sizeof (smb_domain_t));
1280
1281 if (list->td_domains == NULL)
1282 return;
1283
1284 list->td_num = enum_buf->entries_read;
1285 for (i = 0; i < list->td_num; i++) {
1286 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1287 smb_domain_set_trust_info(
1288 sidstr,
1289 (char *)enum_buf->info[i].nb_name.str,
1290 (char *)enum_buf->info[i].dns_name.str,
1291 enum_buf->info[i].trust_direction,
1292 enum_buf->info[i].trust_type,
1293 enum_buf->info[i].trust_attrs,
1294 &list->td_domains[i]);
1295 }
1296 }
1297
1298 static void
lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf * enum_buf,smb_trusted_domains_t * list)1299 lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
1300 smb_trusted_domains_t *list)
1301 {
1302 char sidstr[SMB_SID_STRSZ];
1303 int i;
1304
1305 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1306 return;
1307
1308 list->td_num = 0;
1309 list->td_domains = calloc(enum_buf->entries_read,
1310 sizeof (smb_domain_t));
1311
1312 if (list->td_domains == NULL)
1313 return;
1314
1315 list->td_num = enum_buf->entries_read;
1316 for (i = 0; i < list->td_num; i++) {
1317 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1318 smb_domain_set_trust_info(
1319 sidstr, (char *)enum_buf->info[i].name.str,
1320 "", 0, 0, 0, &list->td_domains[i]);
1321 }
1322 }
1323
1324 static void
smb_account_trace(const smb_account_t * info)1325 smb_account_trace(const smb_account_t *info)
1326 {
1327 char sidbuf[SMB_SID_STRSZ];
1328
1329 bzero(sidbuf, SMB_SID_STRSZ);
1330 smb_sid_tostr(info->a_sid, sidbuf);
1331
1332 smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name,
1333 sidbuf, info->a_rid, smb_sid_type2str(info->a_type));
1334 }
1335