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