1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21148c5f43SAlan Wright
22da6c28aaSamw /*
23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*dafb549fSGordon Ross * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
25da6c28aaSamw */
26da6c28aaSamw
27da6c28aaSamw /*
28da6c28aaSamw * This module provides the high level interface to the LSA RPC functions.
29da6c28aaSamw */
30da6c28aaSamw
31da6c28aaSamw #include <strings.h>
32da6c28aaSamw #include <unistd.h>
33da6c28aaSamw
34da6c28aaSamw #include <smbsrv/libsmb.h>
35da6c28aaSamw #include <smbsrv/libmlsvc.h>
36da6c28aaSamw #include <smbsrv/smbinfo.h>
37da6c28aaSamw #include <smbsrv/smb_token.h>
38da6c28aaSamw
3989dc44ceSjose borrego #include <lsalib.h>
40dc20a302Sas
41*dafb549fSGordon Ross static uint32_t lsa_lookup_name_int(char *, uint16_t, smb_account_t *,
42*dafb549fSGordon Ross boolean_t);
43*dafb549fSGordon Ross static uint32_t lsa_lookup_sid_int(smb_sid_t *, smb_account_t *, boolean_t);
44*dafb549fSGordon Ross
457f667e74Sjose borrego static uint32_t lsa_lookup_name_builtin(char *, char *, smb_account_t *);
467f667e74Sjose borrego static uint32_t lsa_lookup_name_domain(char *, smb_account_t *);
47dc20a302Sas
487f667e74Sjose borrego static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_account_t *);
497f667e74Sjose borrego static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_account_t *);
50dc20a302Sas
51b3700b07SGordon Ross static uint32_t lsa_list_accounts(mlsvc_handle_t *);
52b3700b07SGordon Ross static uint32_t lsa_map_status(uint32_t);
53da6c28aaSamw
54dc20a302Sas /*
55dc20a302Sas * Lookup the given account and returns the account information
567f667e74Sjose borrego * in the passed smb_account_t structure.
5789dc44ceSjose borrego *
5889dc44ceSjose borrego * The lookup is performed in the following order:
5989dc44ceSjose borrego * well known accounts
6089dc44ceSjose borrego * local accounts
6189dc44ceSjose borrego * domain accounts
6289dc44ceSjose borrego *
6389dc44ceSjose borrego * If it's established the given account is well know or local
6489dc44ceSjose borrego * but the lookup fails for some reason, the next step(s) won't be
6589dc44ceSjose borrego * performed.
66dc20a302Sas *
67dc20a302Sas * If the name is a domain account, it may refer to a user, group or
68dc20a302Sas * alias. If it is a local account, its type should be specified
69dc20a302Sas * in the sid_type parameter. In case the account type is unknown
70dc20a302Sas * sid_type should be set to SidTypeUnknown.
71dc20a302Sas *
7289dc44ceSjose borrego * account argument could be either [domain\]name or [domain/]name.
7389dc44ceSjose borrego *
7489dc44ceSjose borrego * Return status:
7589dc44ceSjose borrego *
7689dc44ceSjose borrego * NT_STATUS_SUCCESS Account is successfully translated
7789dc44ceSjose borrego * NT_STATUS_NONE_MAPPED Couldn't translate the account
78dc20a302Sas */
79dc20a302Sas uint32_t
lsa_lookup_name(char * account,uint16_t type,smb_account_t * info)807f667e74Sjose borrego lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
81*dafb549fSGordon Ross {
82*dafb549fSGordon Ross return (lsa_lookup_name_int(account, type, info, B_TRUE));
83*dafb549fSGordon Ross }
84*dafb549fSGordon Ross
85*dafb549fSGordon Ross /* Variant that avoids the call out to AD. */
86*dafb549fSGordon Ross uint32_t
lsa_lookup_lname(char * account,uint16_t type,smb_account_t * info)87*dafb549fSGordon Ross lsa_lookup_lname(char *account, uint16_t type, smb_account_t *info)
88*dafb549fSGordon Ross {
89*dafb549fSGordon Ross return (lsa_lookup_name_int(account, type, info, B_FALSE));
90*dafb549fSGordon Ross }
91*dafb549fSGordon Ross
92*dafb549fSGordon Ross uint32_t
lsa_lookup_name_int(char * account,uint16_t type,smb_account_t * info,boolean_t try_ad)93*dafb549fSGordon Ross lsa_lookup_name_int(char *account, uint16_t type, smb_account_t *info,
94*dafb549fSGordon Ross boolean_t try_ad)
95dc20a302Sas {
9689dc44ceSjose borrego char nambuf[SMB_USERNAME_MAXLEN];
9789dc44ceSjose borrego char dombuf[SMB_PI_MAX_DOMAIN];
9889dc44ceSjose borrego char *name, *domain;
9989dc44ceSjose borrego uint32_t status;
10089dc44ceSjose borrego char *slash;
10189dc44ceSjose borrego
1025831d79bSGordon Ross if (account == NULL)
1035831d79bSGordon Ross return (NT_STATUS_NONE_MAPPED);
1045831d79bSGordon Ross
10589dc44ceSjose borrego (void) strsubst(account, '/', '\\');
10689dc44ceSjose borrego (void) strcanon(account, "\\");
10789dc44ceSjose borrego /* \john -> john */
10889dc44ceSjose borrego account += strspn(account, "\\");
10989dc44ceSjose borrego
11089dc44ceSjose borrego if ((slash = strchr(account, '\\')) != NULL) {
11189dc44ceSjose borrego *slash = '\0';
11289dc44ceSjose borrego (void) strlcpy(dombuf, account, sizeof (dombuf));
11389dc44ceSjose borrego (void) strlcpy(nambuf, slash + 1, sizeof (nambuf));
11489dc44ceSjose borrego *slash = '\\';
11589dc44ceSjose borrego name = nambuf;
11689dc44ceSjose borrego domain = dombuf;
117dc20a302Sas } else {
118dc20a302Sas name = account;
119dc20a302Sas domain = NULL;
120dc20a302Sas }
121dc20a302Sas
12289dc44ceSjose borrego status = lsa_lookup_name_builtin(domain, name, info);
12389dc44ceSjose borrego if (status == NT_STATUS_NOT_FOUND) {
1247f667e74Sjose borrego status = smb_sam_lookup_name(domain, name, type, info);
12589dc44ceSjose borrego if (status == NT_STATUS_SUCCESS)
126dc20a302Sas return (status);
127dc20a302Sas
128*dafb549fSGordon Ross if (try_ad && ((domain == NULL) ||
129*dafb549fSGordon Ross (status == NT_STATUS_NOT_FOUND))) {
13089dc44ceSjose borrego status = lsa_lookup_name_domain(account, info);
131*dafb549fSGordon Ross }
132dc20a302Sas }
133dc20a302Sas
13489dc44ceSjose borrego return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
135dc20a302Sas }
136dc20a302Sas
137dc20a302Sas uint32_t
lsa_lookup_sid(smb_sid_t * sid,smb_account_t * info)1387f667e74Sjose borrego lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info)
139*dafb549fSGordon Ross {
140*dafb549fSGordon Ross return (lsa_lookup_sid_int(sid, info, B_TRUE));
141*dafb549fSGordon Ross }
142*dafb549fSGordon Ross
143*dafb549fSGordon Ross /* Variant that avoids the call out to AD. */
144*dafb549fSGordon Ross uint32_t
lsa_lookup_lsid(smb_sid_t * sid,smb_account_t * info)145*dafb549fSGordon Ross lsa_lookup_lsid(smb_sid_t *sid, smb_account_t *info)
146*dafb549fSGordon Ross {
147*dafb549fSGordon Ross return (lsa_lookup_sid_int(sid, info, B_FALSE));
148*dafb549fSGordon Ross }
149*dafb549fSGordon Ross
150*dafb549fSGordon Ross static uint32_t
lsa_lookup_sid_int(smb_sid_t * sid,smb_account_t * info,boolean_t try_ad)151*dafb549fSGordon Ross lsa_lookup_sid_int(smb_sid_t *sid, smb_account_t *info, boolean_t try_ad)
152dc20a302Sas {
1537f667e74Sjose borrego uint32_t status;
1547f667e74Sjose borrego
1556537f381Sas if (!smb_sid_isvalid(sid))
156dc20a302Sas return (NT_STATUS_INVALID_SID);
157dc20a302Sas
1587f667e74Sjose borrego status = lsa_lookup_sid_builtin(sid, info);
1597f667e74Sjose borrego if (status == NT_STATUS_NOT_FOUND) {
1607f667e74Sjose borrego status = smb_sam_lookup_sid(sid, info);
161*dafb549fSGordon Ross if (try_ad && status == NT_STATUS_NOT_FOUND) {
1627f667e74Sjose borrego status = lsa_lookup_sid_domain(sid, info);
163*dafb549fSGordon Ross }
1647f667e74Sjose borrego }
165dc20a302Sas
1667f667e74Sjose borrego return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
167dc20a302Sas }
168dc20a302Sas
169da6c28aaSamw /*
170da6c28aaSamw * Obtains the primary domain SID and name from the specified server
17129bd2886SAlan Wright * (domain controller).
172da6c28aaSamw *
1738d7e4166Sjose borrego * The requested information will be returned via 'info' argument.
1748d7e4166Sjose borrego *
175b3700b07SGordon Ross * Returns NT status codes. (Raw, not LSA-ized)
176da6c28aaSamw */
177da6c28aaSamw DWORD
lsa_query_primary_domain_info(char * server,char * domain,smb_domain_t * info)17829bd2886SAlan Wright lsa_query_primary_domain_info(char *server, char *domain,
179a0aa776eSAlan Wright smb_domain_t *info)
180da6c28aaSamw {
181da6c28aaSamw mlsvc_handle_t domain_handle;
182a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
183b3700b07SGordon Ross DWORD status;
184a0aa776eSAlan Wright
185a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
186da6c28aaSamw
187b3700b07SGordon Ross status = lsar_open(server, domain, user, &domain_handle);
188b3700b07SGordon Ross if (status != 0)
189b3700b07SGordon Ross return (status);
190da6c28aaSamw
191da6c28aaSamw status = lsar_query_info_policy(&domain_handle,
1928d7e4166Sjose borrego MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info);
193da6c28aaSamw
194da6c28aaSamw (void) lsar_close(&domain_handle);
195da6c28aaSamw return (status);
196da6c28aaSamw }
197da6c28aaSamw
198da6c28aaSamw /*
199da6c28aaSamw * Obtains the account domain SID and name from the current server
20029bd2886SAlan Wright * (domain controller).
201da6c28aaSamw *
2028d7e4166Sjose borrego * The requested information will be returned via 'info' argument.
2038d7e4166Sjose borrego *
204b3700b07SGordon Ross * Returns NT status codes. (Raw, not LSA-ized)
205da6c28aaSamw */
206da6c28aaSamw DWORD
lsa_query_account_domain_info(char * server,char * domain,smb_domain_t * info)20729bd2886SAlan Wright lsa_query_account_domain_info(char *server, char *domain,
208a0aa776eSAlan Wright smb_domain_t *info)
209da6c28aaSamw {
210da6c28aaSamw mlsvc_handle_t domain_handle;
211a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
212b3700b07SGordon Ross DWORD status;
213a0aa776eSAlan Wright
214a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
215da6c28aaSamw
216b3700b07SGordon Ross status = lsar_open(server, domain, user, &domain_handle);
217b3700b07SGordon Ross if (status != 0)
218b3700b07SGordon Ross return (status);
219da6c28aaSamw
220da6c28aaSamw status = lsar_query_info_policy(&domain_handle,
2218d7e4166Sjose borrego MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info);
2228d7e4166Sjose borrego
2238d7e4166Sjose borrego (void) lsar_close(&domain_handle);
2248d7e4166Sjose borrego return (status);
2258d7e4166Sjose borrego }
2268d7e4166Sjose borrego
2278d7e4166Sjose borrego /*
2288d7e4166Sjose borrego * lsa_query_dns_domain_info
2298d7e4166Sjose borrego *
2308d7e4166Sjose borrego * Obtains the DNS domain info from the specified server
2318d7e4166Sjose borrego * (domain controller).
2328d7e4166Sjose borrego *
2338d7e4166Sjose borrego * The requested information will be returned via 'info' argument.
2348d7e4166Sjose borrego *
235b3700b07SGordon Ross * Returns NT status codes. (Raw, not LSA-ized)
2368d7e4166Sjose borrego */
2378d7e4166Sjose borrego DWORD
lsa_query_dns_domain_info(char * server,char * domain,smb_domain_t * info)238a0aa776eSAlan Wright lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info)
2398d7e4166Sjose borrego {
2408d7e4166Sjose borrego mlsvc_handle_t domain_handle;
241a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
242b3700b07SGordon Ross DWORD status;
243a0aa776eSAlan Wright
244a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2458d7e4166Sjose borrego
246b3700b07SGordon Ross status = lsar_open(server, domain, user, &domain_handle);
247b3700b07SGordon Ross if (status != 0)
248b3700b07SGordon Ross return (status);
2498d7e4166Sjose borrego
250