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
37idmap_retcode
38idmap_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 */
66idmap_retcode
67lookup_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
127out:
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 */
138idmap_retcode
139lookup_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
222out:
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