Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2012 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 :
24 : #include "db/sysdb.h"
25 : #include "db/sysdb_private.h"
26 :
27 : static struct ldb_dn *
28 0 : sysdb_idmap_dn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain,
29 : const char *object_sid)
30 : {
31 : errno_t ret;
32 : char *clean_sid;
33 : struct ldb_dn *dn;
34 :
35 0 : ret = sysdb_dn_sanitize(NULL, object_sid, &clean_sid);
36 0 : if (ret != EOK) {
37 0 : return NULL;
38 : }
39 :
40 0 : DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_IDMAP"\n", clean_sid, domain->name);
41 :
42 0 : dn = ldb_dn_new_fmt(mem_ctx, domain->sysdb->ldb, SYSDB_TMPL_IDMAP,
43 : clean_sid, domain->name);
44 0 : talloc_free(clean_sid);
45 :
46 0 : return dn;
47 : }
48 :
49 : errno_t
50 0 : sysdb_idmap_store_mapping(struct sss_domain_info *domain,
51 : const char *dom_name,
52 : const char *dom_sid,
53 : id_t slice_num)
54 : {
55 : errno_t ret, sret;
56 : int lret;
57 0 : bool in_transaction = false;
58 : TALLOC_CTX *tmp_ctx;
59 : struct ldb_dn *dn;
60 : static const char *attrs[] = SYSDB_IDMAP_ATTRS;
61 : size_t count;
62 : struct ldb_message *update_msg;
63 : struct ldb_message **msgs;
64 : const char *old_name;
65 : id_t old_slice;
66 :
67 0 : tmp_ctx = talloc_new(NULL);
68 0 : if (!tmp_ctx) return ENOMEM;
69 :
70 0 : dn = sysdb_idmap_dn(tmp_ctx, domain, dom_sid);
71 0 : if (!dn) {
72 0 : ret = ENOMEM;
73 0 : goto done;
74 : }
75 :
76 0 : update_msg = ldb_msg_new(tmp_ctx);
77 0 : if (!update_msg) {
78 0 : ret = ENOMEM;
79 0 : goto done;
80 : }
81 0 : update_msg->dn = dn;
82 :
83 0 : ret = sysdb_transaction_start(domain->sysdb);
84 0 : if (ret != EOK) {
85 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
86 0 : goto done;
87 : }
88 :
89 0 : in_transaction = true;
90 :
91 :
92 : /* Check for an existing mapping */
93 0 : ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE,
94 : NULL, attrs, &count, &msgs);
95 0 : if (ret != EOK && ret != ENOENT) goto done;
96 :
97 0 : if (ret == EOK && count != 1) {
98 : /* More than one reply for a base search? */
99 0 : ret = EIO;
100 0 : goto done;
101 0 : } else if (ret == ENOENT) {
102 : /* Create a new mapping */
103 0 : DEBUG(SSSDBG_CONF_SETTINGS,
104 : "Adding new ID mapping [%s][%s][%lu]\n",
105 : dom_name, dom_sid, (unsigned long)slice_num);
106 :
107 : /* Add the objectClass */
108 0 : lret = ldb_msg_add_empty(update_msg, SYSDB_OBJECTCLASS,
109 : LDB_FLAG_MOD_ADD,
110 : NULL);
111 0 : if (lret != LDB_SUCCESS) {
112 0 : ret = sysdb_error_to_errno(lret);
113 0 : goto done;
114 : }
115 :
116 0 : lret = ldb_msg_add_string(update_msg, SYSDB_OBJECTCLASS,
117 : SYSDB_IDMAP_MAPPING_OC);
118 0 : if (lret != LDB_SUCCESS) {
119 0 : ret = sysdb_error_to_errno(lret);
120 0 : goto done;
121 : }
122 :
123 : /* Add the domain objectSID */
124 0 : lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SID_ATTR,
125 : LDB_FLAG_MOD_ADD,
126 : NULL);
127 0 : if (lret != LDB_SUCCESS) {
128 0 : ret = sysdb_error_to_errno(lret);
129 0 : goto done;
130 : }
131 :
132 0 : lret = ldb_msg_add_string(update_msg, SYSDB_IDMAP_SID_ATTR, dom_sid);
133 0 : if (lret != LDB_SUCCESS) {
134 0 : ret = sysdb_error_to_errno(lret);
135 0 : goto done;
136 : }
137 :
138 : /* Add the domain name */
139 0 : lret = ldb_msg_add_empty(update_msg, SYSDB_NAME,
140 : LDB_FLAG_MOD_ADD,
141 : NULL);
142 0 : if (lret != LDB_SUCCESS) {
143 0 : ret = sysdb_error_to_errno(lret);
144 0 : goto done;
145 : }
146 :
147 0 : lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name);
148 0 : if (lret != LDB_SUCCESS) {
149 0 : ret = sysdb_error_to_errno(lret);
150 0 : goto done;
151 : }
152 :
153 : /* Add the slice number */
154 0 : lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SLICE_ATTR,
155 : LDB_FLAG_MOD_ADD,
156 : NULL);
157 0 : if (lret != LDB_SUCCESS) {
158 0 : ret = sysdb_error_to_errno(lret);
159 0 : goto done;
160 : }
161 :
162 0 : lret = ldb_msg_add_fmt(update_msg, SYSDB_IDMAP_SLICE_ATTR,
163 : "%lu", (unsigned long)slice_num);
164 0 : if (lret != LDB_SUCCESS) {
165 0 : ret = sysdb_error_to_errno(lret);
166 0 : goto done;
167 : }
168 :
169 0 : lret = ldb_add(domain->sysdb->ldb, update_msg);
170 0 : if (lret != LDB_SUCCESS) {
171 0 : DEBUG(SSSDBG_MINOR_FAILURE,
172 : "Failed to add mapping: [%s]\n",
173 : ldb_strerror(lret));
174 0 : ret = sysdb_error_to_errno(lret);
175 0 : goto done;
176 : }
177 : } else {
178 : /* Update the existing mapping */
179 :
180 : /* Check whether the slice has changed
181 : * This should never happen, and it's a recipe for
182 : * disaster. We'll throw an error if it does.
183 : */
184 0 : old_slice = ldb_msg_find_attr_as_int(msgs[0],
185 : SYSDB_IDMAP_SLICE_ATTR,
186 : -1);
187 0 : if (old_slice == -1) {
188 0 : DEBUG(SSSDBG_CRIT_FAILURE,
189 : "Could not identify original slice for SID [%s]\n",
190 : dom_sid);
191 0 : ret = ENOENT;
192 0 : goto done;
193 : }
194 :
195 0 : if (slice_num != old_slice) {
196 0 : DEBUG(SSSDBG_FATAL_FAILURE,
197 : "Detected attempt to change slice value for sid [%s] "
198 : "This will break existing users. Refusing to perform.\n",
199 : dom_sid);
200 0 : ret = EINVAL;
201 0 : goto done;
202 : }
203 :
204 : /* Check whether the name has changed. This may happen
205 : * if we're told the real name of a domain and want to
206 : * replace the SID as placeholder.
207 : */
208 0 : old_name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
209 0 : if (!old_name) {
210 0 : DEBUG(SSSDBG_CRIT_FAILURE,
211 : "Could not identify original domain name of SID [%s]\n",
212 : dom_sid);
213 0 : ret = ENOENT;
214 0 : goto done;
215 : }
216 :
217 0 : if (strcmp(old_name, dom_name) == 0) {
218 : /* There's nothing to be done. We don't need to
219 : * make any changes here. Just return success.
220 : */
221 0 : DEBUG(SSSDBG_TRACE_LIBS,
222 : "No changes needed, canceling transaction\n");
223 0 : ret = EOK;
224 0 : goto done;
225 : } else {
226 : /* The name has changed. Replace it */
227 0 : DEBUG(SSSDBG_CONF_SETTINGS,
228 : "Changing domain name of SID [%s] from [%s] to [%s]\n",
229 : dom_sid, old_name, dom_name);
230 :
231 : /* Set the new name */
232 0 : lret = ldb_msg_add_empty(update_msg, SYSDB_NAME,
233 : LDB_FLAG_MOD_REPLACE,
234 : NULL);
235 0 : if (lret != LDB_SUCCESS) {
236 0 : ret = sysdb_error_to_errno(lret);
237 0 : goto done;
238 : }
239 :
240 0 : lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name);
241 0 : if (lret != LDB_SUCCESS) {
242 0 : ret = sysdb_error_to_errno(lret);
243 0 : goto done;
244 : }
245 : }
246 :
247 0 : lret = ldb_modify(domain->sysdb->ldb, update_msg);
248 0 : if (lret != LDB_SUCCESS) {
249 0 : DEBUG(SSSDBG_MINOR_FAILURE,
250 : "Failed to update mapping: [%s](%d)[%s]\n",
251 : ldb_strerror(lret), lret, ldb_errstring(domain->sysdb->ldb));
252 0 : ret = sysdb_error_to_errno(lret);
253 0 : goto done;
254 : }
255 : }
256 :
257 0 : ret = sysdb_transaction_commit(domain->sysdb);
258 0 : if (ret != EOK) {
259 0 : DEBUG(SSSDBG_CRIT_FAILURE,
260 : "Could not commit transaction: [%s]\n", strerror(ret));
261 0 : goto done;
262 : }
263 0 : in_transaction = false;
264 :
265 : done:
266 0 : if (in_transaction) {
267 0 : sret = sysdb_transaction_cancel(domain->sysdb);
268 0 : if (sret != EOK) {
269 0 : DEBUG(SSSDBG_CRIT_FAILURE,
270 : "Could not cancel transaction\n");
271 : }
272 : }
273 0 : talloc_free(tmp_ctx);
274 0 : return ret;
275 : }
276 :
277 : errno_t
278 8 : sysdb_idmap_get_mappings(TALLOC_CTX *mem_ctx,
279 : struct sss_domain_info *domain,
280 : struct ldb_result **_result)
281 : {
282 : errno_t ret;
283 : struct ldb_dn *base_dn;
284 : TALLOC_CTX *tmp_ctx;
285 : struct ldb_result *res;
286 : static const char *attrs[] = SYSDB_IDMAP_ATTRS;
287 :
288 8 : tmp_ctx = talloc_new(NULL);
289 8 : if (!tmp_ctx) return ENOMEM;
290 :
291 8 : DEBUG(SSSDBG_TRACE_ALL, SYSDB_TMPL_IDMAP_BASE"\n", domain->name);
292 :
293 8 : base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
294 : SYSDB_TMPL_IDMAP_BASE, domain->name);
295 8 : if (!base_dn) {
296 0 : ret = ENOMEM;
297 0 : goto done;
298 : }
299 :
300 8 : SSS_LDB_SEARCH(ret, domain->sysdb->ldb, tmp_ctx, &res, base_dn,
301 : LDB_SCOPE_SUBTREE, attrs, SYSDB_IDMAP_FILTER);
302 8 : if (ret != EOK) {
303 8 : DEBUG(SSSDBG_MINOR_FAILURE,
304 : "Could not locate ID mappings: [%s]\n",
305 : sss_strerror(ret));
306 8 : goto done;
307 : }
308 :
309 0 : *_result = talloc_steal(mem_ctx, res);
310 :
311 0 : ret = EOK;
312 :
313 : done:
314 8 : talloc_free(tmp_ctx);
315 8 : return ret;
316 : }
|