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