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) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2022 RackTop Systems, Inc.
26 */
27
28 /*
29 * LSA lookups
30 */
31
32 #include <stdio.h>
33 #include <note.h>
34 #include <assert.h>
35
36 #include "idmapd.h"
37 #include "libsmb.h"
38
39 idmap_retcode
idmap_lsa_xlate_sid_type(const lsa_account_t * acct,idmap_id_type * ret_type)40 idmap_lsa_xlate_sid_type(const lsa_account_t *acct, idmap_id_type *ret_type)
41 {
42 switch (acct->a_sidtype) {
43 case SidTypeUser:
44 case SidTypeComputer:
45 case SidTypeDomain:
46 case SidTypeDeletedAccount:
47 case SidTypeUnknown:
48 case SidTypeLabel:
49 *ret_type = IDMAP_USID;
50 return (IDMAP_SUCCESS);
51 case SidTypeGroup:
52 case SidTypeAlias:
53 case SidTypeWellKnownGroup:
54 *ret_type = IDMAP_GSID;
55 return (IDMAP_SUCCESS);
56 case SidTypeNull:
57 case SidTypeInvalid:
58 default:
59 idmapdlog(LOG_WARNING,
60 "LSA lookup: bad type %d for %s@%s",
61 acct->a_sidtype, acct->a_name, acct->a_domain);
62 return (IDMAP_ERR_OTHER);
63 }
64 NOTE(NOTREACHED)
65 }
66
67 /* Given SID, look up name and type */
68 idmap_retcode
lookup_lsa_by_sid(const char * sidprefix,uint32_t rid,char ** ret_name,char ** ret_domain,idmap_id_type * ret_type)69 lookup_lsa_by_sid(
70 const char *sidprefix,
71 uint32_t rid,
72 char **ret_name,
73 char **ret_domain,
74 idmap_id_type *ret_type)
75 {
76 lsa_account_t acct;
77 char sid[SMB_SID_STRSZ + 1];
78 idmap_retcode ret;
79 int rc;
80
81 (void) memset(&acct, 0, sizeof (acct));
82 *ret_name = NULL;
83 *ret_domain = NULL;
84
85 (void) snprintf(sid, sizeof (sid), "%s-%u", sidprefix, rid);
86
87 rc = smb_lookup_lsid(sid, &acct);
88 if (rc != 0) {
89 idmapdlog(LOG_ERR, "Error: SMB lookup SID failed.");
90 idmapdlog(LOG_ERR,
91 "Check SMB service (svc:/network/smb/server).");
92 idmapdlog(LOG_ERR,
93 "Check connectivity to Active Directory.");
94
95 ret = IDMAP_ERR_OTHER;
96 goto out;
97 }
98 if (acct.a_status == NT_STATUS_NONE_MAPPED) {
99 ret = IDMAP_ERR_NOTFOUND;
100 goto out;
101 }
102 if (acct.a_status != NT_STATUS_SUCCESS) {
103 idmapdlog(LOG_WARNING,
104 "Warning: SMB lookup SID(%s) failed (0x%x)",
105 sid, acct.a_status);
106 /* Fail soft */
107 ret = IDMAP_ERR_NOTFOUND;
108 goto out;
109 }
110
111 ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
112 if (ret != IDMAP_SUCCESS)
113 goto out;
114
115 *ret_name = strdup(acct.a_name);
116 if (*ret_name == NULL) {
117 ret = IDMAP_ERR_MEMORY;
118 goto out;
119 }
120
121 *ret_domain = strdup(acct.a_domain);
122 if (*ret_domain == NULL) {
123 ret = IDMAP_ERR_MEMORY;
124 goto out;
125 }
126
127 ret = IDMAP_SUCCESS;
128
129 out:
130 if (ret != IDMAP_SUCCESS) {
131 free(*ret_name);
132 *ret_name = NULL;
133 free(*ret_domain);
134 *ret_domain = NULL;
135 }
136 return (ret);
137 }
138
139 /* Given name and optional domain, look up SID, type, and canonical name */
140 idmap_retcode
lookup_lsa_by_name(const char * name,const char * domain,char ** ret_sidprefix,uint32_t * ret_rid,char ** ret_name,char ** ret_domain,idmap_id_type * ret_type)141 lookup_lsa_by_name(
142 const char *name,
143 const char *domain,
144 char **ret_sidprefix,
145 uint32_t *ret_rid,
146 char **ret_name,
147 char **ret_domain,
148 idmap_id_type *ret_type)
149 {
150 lsa_account_t acct;
151 char *namedom = NULL;
152 idmap_retcode ret;
153 int rc;
154
155 (void) memset(&acct, 0, sizeof (acct));
156 *ret_sidprefix = NULL;
157 if (ret_name != NULL)
158 *ret_name = NULL;
159 if (ret_domain != NULL)
160 *ret_domain = NULL;
161
162 if (domain != NULL)
163 (void) asprintf(&namedom, "%s@%s", name, domain);
164 else
165 namedom = strdup(name);
166 if (namedom == NULL) {
167 ret = IDMAP_ERR_MEMORY;
168 goto out;
169 }
170
171 rc = smb_lookup_lname(namedom, SidTypeUnknown, &acct);
172 if (rc != 0) {
173 idmapdlog(LOG_ERR, "Error: SMB lookup name failed.");
174 idmapdlog(LOG_ERR,
175 "Check SMB service (svc:/network/smb/server).");
176 idmapdlog(LOG_ERR,
177 "Check connectivity to Active Directory.");
178 ret = IDMAP_ERR_OTHER;
179 goto out;
180 }
181 if (acct.a_status == NT_STATUS_NONE_MAPPED) {
182 ret = IDMAP_ERR_NOTFOUND;
183 goto out;
184 }
185 if (acct.a_status != NT_STATUS_SUCCESS) {
186 idmapdlog(LOG_WARNING,
187 "Warning: SMB lookup name(%s) failed (0x%x)",
188 namedom, acct.a_status);
189 /* Fail soft */
190 ret = IDMAP_ERR_NOTFOUND;
191 goto out;
192 }
193
194 rc = smb_sid_splitstr(acct.a_sid, ret_rid);
195 assert(rc == 0);
196 *ret_sidprefix = strdup(acct.a_sid);
197 if (*ret_sidprefix == NULL) {
198 ret = IDMAP_ERR_MEMORY;
199 goto out;
200 }
201
202 ret = idmap_lsa_xlate_sid_type(&acct, ret_type);
203 if (ret != IDMAP_SUCCESS)
204 goto out;
205
206 if (ret_name != NULL) {
207 *ret_name = strdup(acct.a_name);
208 if (*ret_name == NULL) {
209 ret = IDMAP_ERR_MEMORY;
210 goto out;
211 }
212 }
213
214 if (ret_domain != NULL) {
215 *ret_domain = strdup(acct.a_domain);
216 if (*ret_domain == NULL) {
217 ret = IDMAP_ERR_MEMORY;
218 goto out;
219 }
220 }
221
222 ret = IDMAP_SUCCESS;
223
224 out:
225 free(namedom);
226 if (ret != IDMAP_SUCCESS) {
227 if (ret_name != NULL) {
228 free(*ret_name);
229 *ret_name = NULL;
230 }
231 if (ret_domain != NULL) {
232 free(*ret_domain);
233 *ret_domain = NULL;
234 }
235 free(*ret_sidprefix);
236 *ret_sidprefix = NULL;
237 }
238 return (ret);
239 }
240
241 /*
242 * This exists just so we can avoid exposing all of idmapd to libsmb.h.
243 * Like the above functions, it's a door call over to smbd.
244 */
245 void
notify_dc_changed(void)246 notify_dc_changed(void)
247 {
248 int rc;
249 rc = smb_notify_dc_changed();
250 if (rc != 0) {
251 idmapdlog(LOG_WARNING,
252 "Warning: smb_notify_dc_changed, rc=%d", rc);
253 }
254 }
255