lsar_clnt.c revision 1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9f
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 */
54typedef struct lsa_names {
55	uint32_t	n_entry;
56	mslsa_string_t	name[8];
57} lsa_names_t;
58
59typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *,
60    smb_account_t *);
61
62static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *,
63    smb_account_t *);
64static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *,
65    smb_account_t *);
66static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *,
67    smb_account_t *);
68static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *,
69    smb_account_t *);
70static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *,
71    smb_account_t *account);
72
73static char *lsar_get_username(const char *);
74static void smb_account_trace(const smb_account_t *);
75
76static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
77    smb_trusted_domains_t *);
78static 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 */
92int
93lsar_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 */
116int
117lsar_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 */
176int
177lsar_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 */
230int
231lsar_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 */
258int
259lsar_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 */
291DWORD
292lsar_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 */
374uint32_t
375lsar_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 */
456static char *
457lsar_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 */
482static uint32_t
483lsar_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 */
536static uint32_t
537lsar_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 */
591static uint32_t
592lsar_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 */
653static uint32_t /*LINTED E_STATIC_UNUSED*/
654lsar_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 */
711uint32_t
712lsar_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 */
748static uint32_t
749lsar_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 */
808static uint32_t
809lsar_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 */
876static uint32_t /*LINTED E_STATIC_UNUSED*/
877lsar_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 */
949int
950lsar_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 */
1021DWORD
1022lsar_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
1065DWORD
1066lsar_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*/
1115int
1116lsar_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 */
1146int
1147lsar_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 */
1191int
1192lsar_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 */
1234DWORD
1235lsar_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
1275static void
1276lsar_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
1306static void
1307lsar_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
1332static void
1333smb_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