xref: /illumos-gate/usr/src/cmd/idmap/idmapd/idmap_lsa.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
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
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
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
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