Branch data 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 "util/util.h"
25 : : #include "db/sysdb.h"
26 : : #include "db/sysdb_private.h"
27 : : #include "db/sysdb_services.h"
28 : :
29 : : errno_t
30 : : sysdb_svc_add(TALLOC_CTX *mem_ctx,
31 : : struct sysdb_ctx *sysdb,
32 : : const char *primary_name,
33 : : int port,
34 : : const char **aliases,
35 : : const char **protocols,
36 : : struct ldb_dn **dn);
37 : :
38 : : static errno_t
39 : : sysdb_svc_update(struct sysdb_ctx *sysdb,
40 : : struct ldb_dn *dn,
41 : : int port,
42 : : const char **aliases,
43 : : const char **protocols);
44 : :
45 : : errno_t
46 : : sysdb_svc_remove_alias(struct sysdb_ctx *sysdb,
47 : : struct ldb_dn *dn,
48 : : const char *alias);
49 : :
50 : : errno_t
51 : 11 : sysdb_getservbyname(TALLOC_CTX *mem_ctx,
52 : : struct sysdb_ctx *sysdb,
53 : : const char *name,
54 : : const char *proto,
55 : : struct ldb_result **_res)
56 : : {
57 : : errno_t ret;
58 : : int lret;
59 : : TALLOC_CTX *tmp_ctx;
60 : : static const char *attrs[] = SYSDB_SVC_ATTRS;
61 : : struct ldb_dn *base_dn;
62 : : struct ldb_result *res;
63 : : char *sanitized_name;
64 : : char *sanitized_proto;
65 : :
66 : 11 : *_res = NULL;
67 : :
68 : 11 : tmp_ctx = talloc_new(NULL);
69 [ + - ]: 11 : if (!tmp_ctx) {
70 : : return ENOMEM;
71 : : }
72 : :
73 : 11 : base_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
74 : : SYSDB_TMPL_SVC_BASE,
75 : 11 : sysdb->domain->name);
76 [ + - ]: 11 : if (!base_dn) {
77 : : ret = ENOMEM;
78 : : goto done;
79 : : }
80 : :
81 : 11 : ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name);
82 [ + - ]: 11 : if (ret != EOK) {
83 : : goto done;
84 : : }
85 : :
86 [ - + ]: 11 : if (proto) {
87 : 0 : ret = sss_filter_sanitize(tmp_ctx, proto, &sanitized_proto);
88 [ # # ]: 0 : if (ret != EOK) {
89 : : goto done;
90 : : }
91 : : }
92 : :
93 [ - + ]: 11 : lret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
94 : : LDB_SCOPE_SUBTREE, attrs,
95 : : SYSDB_SVC_BYNAME_FILTER,
96 : : proto?sanitized_proto:"*",
97 : : sanitized_name, sanitized_name);
98 [ - + ]: 11 : if (lret != LDB_SUCCESS) {
99 : 0 : ret = sysdb_error_to_errno(lret);
100 : : goto done;
101 : : }
102 : :
103 [ + + ]: 11 : if (res->count == 0) {
104 : : ret = ENOENT;
105 : : goto done;
106 : : }
107 : :
108 : 8 : *_res = talloc_steal(mem_ctx, res);
109 : :
110 : 8 : ret = EOK;
111 : :
112 : : done:
113 : 11 : talloc_free(tmp_ctx);
114 : : return ret;
115 : : }
116 : :
117 : : errno_t
118 : 11 : sysdb_getservbyport(TALLOC_CTX *mem_ctx,
119 : : struct sysdb_ctx *sysdb,
120 : : int port,
121 : : const char *proto,
122 : : struct ldb_result **_res)
123 : : {
124 : : errno_t ret;
125 : : int lret;
126 : : TALLOC_CTX *tmp_ctx;
127 : : static const char *attrs[] = SYSDB_SVC_ATTRS;
128 : : struct ldb_dn *base_dn;
129 : : struct ldb_result *res;
130 : 11 : char *sanitized_proto = NULL;
131 : :
132 [ + - ]: 11 : if (port <= 0) {
133 : : return EINVAL;
134 : : }
135 : :
136 : 11 : tmp_ctx = talloc_new(NULL);
137 [ + - ]: 11 : if (!tmp_ctx) {
138 : : return ENOMEM;
139 : : }
140 : :
141 : 11 : base_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
142 : : SYSDB_TMPL_SVC_BASE,
143 : 11 : sysdb->domain->name);
144 [ + - ]: 11 : if (!base_dn) {
145 : : ret = ENOMEM;
146 : : goto done;
147 : : }
148 : :
149 [ - + ]: 11 : if (proto) {
150 : 0 : ret = sss_filter_sanitize(tmp_ctx, proto, &sanitized_proto);
151 [ # # ]: 0 : if (ret != EOK) {
152 : : goto done;
153 : : }
154 : : }
155 : :
156 [ - + ]: 11 : lret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
157 : : LDB_SCOPE_SUBTREE, attrs,
158 : : SYSDB_SVC_BYPORT_FILTER,
159 : 11 : sanitized_proto?sanitized_proto:"*",
160 : : (unsigned int) port);
161 [ - + ]: 11 : if (lret) {
162 : 0 : ret = sysdb_error_to_errno(lret);
163 : : goto done;
164 : : }
165 : :
166 [ + + ]: 11 : if (res->count == 0) {
167 : : ret = ENOENT;
168 : : goto done;
169 : : }
170 : :
171 : 9 : *_res = talloc_steal(mem_ctx, res);
172 : :
173 : 9 : ret = EOK;
174 : :
175 : : done:
176 : 11 : talloc_free(tmp_ctx);
177 : : return ret;
178 : : }
179 : :
180 : : errno_t
181 : 4 : sysdb_store_service(struct sysdb_ctx *sysdb,
182 : : const char *primary_name,
183 : : int port,
184 : : const char **aliases,
185 : : const char **protocols,
186 : : struct sysdb_attrs *extra_attrs,
187 : : char **remove_attrs,
188 : : uint64_t cache_timeout,
189 : : time_t now)
190 : : {
191 : : errno_t ret;
192 : : errno_t sret;
193 : : TALLOC_CTX *tmp_ctx;
194 : 4 : bool in_transaction = false;
195 : 4 : struct ldb_result *res = NULL;
196 : : const char *name;
197 : : unsigned int i;
198 : 4 : struct ldb_dn *update_dn = NULL;
199 : : struct sysdb_attrs *attrs;
200 : :
201 : 4 : tmp_ctx = talloc_new(NULL);
202 [ + - ]: 4 : if (!tmp_ctx) return ENOMEM;
203 : :
204 : 4 : ret = sysdb_transaction_start(sysdb);
205 [ - + ]: 4 : if (ret != EOK) {
206 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
[ # # ][ # # ]
[ # # ]
207 : : goto done;
208 : : }
209 : :
210 : 4 : in_transaction = true;
211 : :
212 : : /* Check that the port is unique
213 : : * If the port appears for any service other than
214 : : * the one matching the primary_name, we need to
215 : : * remove them so that getservbyport() can work
216 : : * properly. Last entry saved to the cache should
217 : : * always "win".
218 : : */
219 : 4 : ret = sysdb_getservbyport(tmp_ctx, sysdb, port, NULL, &res);
220 [ + - ]: 4 : if (ret != EOK && ret != ENOENT) {
221 : : goto done;
222 [ + + ]: 4 : } else if (ret != ENOENT) {
223 [ - + ]: 2 : if (res->count != 1) {
224 : : /* Somehow the cache has multiple entries with
225 : : * the same port. This is corrupted. We'll delete
226 : : * them all to sort it out.
227 : : */
228 [ # # ]: 0 : for (i = 0; i < res->count; i++) {
229 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC,
[ # # ][ # # ]
[ # # ]
230 : : ("Corrupt cache entry [%s] detected. Deleting\n",
231 : : ldb_dn_canonical_string(tmp_ctx,
232 : : res->msgs[i]->dn)));
233 : :
234 : 0 : ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
235 [ # # ]: 0 : if (ret != EOK) {
236 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
237 : : ("Could not delete corrupt cache entry [%s]\n",
238 : : ldb_dn_canonical_string(tmp_ctx,
239 : : res->msgs[i]->dn)));
240 : : goto done;
241 : : }
242 : : }
243 : : } else {
244 : : /* Check whether this is the same name as we're currently
245 : : * saving to the cache.
246 : : */
247 : 2 : name = ldb_msg_find_attr_as_string(res->msgs[0],
248 : : SYSDB_NAME,
249 : : NULL);
250 [ + - ][ + - ]: 2 : if (!name || strcmp(name, primary_name) != 0) {
251 : :
252 [ - + ]: 2 : if (!name) {
253 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
254 : : ("A service with no name?\n"));
255 : : /* Corrupted */
256 : : }
257 : :
258 : : /* Either this is a corrupt entry or it's another service
259 : : * claiming ownership of this port. In order to account
260 : : * for port reassignments, we need to delete the old entry.
261 : : */
262 [ + - ][ + - ]: 2 : DEBUG(SSSDBG_TRACE_FUNC,
[ - + ][ # # ]
[ # # ]
263 : : ("Corrupt or replaced cache entry [%s] detected. "
264 : : "Deleting\n",
265 : : ldb_dn_canonical_string(tmp_ctx,
266 : : res->msgs[0]->dn)));
267 : :
268 : 2 : ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true);
269 [ - + ]: 2 : if (ret != EOK) {
270 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
271 : : ("Could not delete cache entry [%s]\n",
272 : : ldb_dn_canonical_string(tmp_ctx,
273 : : res->msgs[0]->dn)));
274 : : }
275 : : }
276 : : }
277 : : }
278 : 4 : talloc_zfree(res);
279 : :
280 : : /* Ok, ports should now be unique. Now look
281 : : * the service up by name to determine if we
282 : : * need to update existing entries or modify
283 : : * aliases.
284 : : */
285 : 4 : ret = sysdb_getservbyname(tmp_ctx, sysdb, primary_name, NULL, &res);
286 [ + - ]: 4 : if (ret != EOK && ret != ENOENT) {
287 : : goto done;
288 [ + + ]: 4 : } else if (ret != ENOENT) { /* Found entries */
289 [ + + ]: 2 : for (i = 0; i < res->count; i++) {
290 : : /* Check whether this is the same name as we're currently
291 : : * saving to the cache.
292 : : */
293 : 1 : name = ldb_msg_find_attr_as_string(res->msgs[i],
294 : : SYSDB_NAME,
295 : : NULL);
296 [ - + ]: 1 : if (!name) {
297 : :
298 : : /* Corrupted */
299 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
300 : : ("A service with no name?\n"));
301 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC,
[ # # ][ # # ]
[ # # ]
302 : : ("Corrupt cache entry [%s] detected. Deleting\n",
303 : : ldb_dn_canonical_string(tmp_ctx,
304 : : res->msgs[i]->dn)));
305 : :
306 : 0 : ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
307 [ # # ]: 0 : if (ret != EOK) {
308 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
309 : : ("Could not delete corrupt cache entry [%s]\n",
310 : : ldb_dn_canonical_string(tmp_ctx,
311 : : res->msgs[i]->dn)));
312 : : goto done;
313 : : }
314 [ + - ]: 1 : } else if (strcmp(name, primary_name) == 0) {
315 : : /* This is the same service name, so we need
316 : : * to update this entry with the values
317 : : * provided.
318 : : */
319 [ - + ]: 1 : if(update_dn) {
320 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
321 : : ("Two existing services with the same name: [%s]? "
322 : : "Deleting both.\n",
323 : : primary_name));
324 : :
325 : : /* Delete the entry from the previous pass */
326 : 0 : ret = sysdb_delete_entry(sysdb, update_dn, true);
327 [ # # ]: 0 : if (ret != EOK) {
328 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
329 : : ("Could not delete cache entry [%s]\n",
330 : : ldb_dn_canonical_string(tmp_ctx,
331 : : update_dn)));
332 : : goto done;
333 : : }
334 : :
335 : : /* Delete the new entry as well */
336 : 0 : ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
337 [ # # ]: 0 : if (ret != EOK) {
338 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
339 : : ("Could not delete cache entry [%s]\n",
340 : : ldb_dn_canonical_string(tmp_ctx,
341 : : res->msgs[i]->dn)));
342 : : goto done;
343 : : }
344 : :
345 : 0 : update_dn = NULL;
346 : : } else {
347 : 1 : update_dn = talloc_steal(tmp_ctx, res->msgs[i]->dn);
348 : : }
349 : : } else {
350 : : /* Another service is claiming this name as an alias.
351 : : * In order to account for aliases being promoted to
352 : : * primary names, we need to make sure to remove the
353 : : * old alias entry.
354 : : */
355 : 0 : ret = sysdb_svc_remove_alias(sysdb,
356 : 0 : res->msgs[i]->dn,
357 : : primary_name);
358 [ # # ]: 0 : if (ret != EOK) goto done;
359 : : }
360 : : }
361 : 1 : talloc_zfree(res);
362 : : }
363 : :
364 [ + + ]: 4 : if (update_dn) {
365 : : /* Update the existing entry */
366 : 1 : ret = sysdb_svc_update(sysdb, update_dn, port, aliases, protocols);
367 : : } else {
368 : : /* Add a new entry */
369 : 3 : ret = sysdb_svc_add(tmp_ctx, sysdb, primary_name, port,
370 : : aliases, protocols, &update_dn);
371 : : }
372 [ + - ]: 4 : if (ret != EOK) goto done;
373 : :
374 : : /* Set the cache timeout */
375 [ + - ]: 4 : if (!extra_attrs) {
376 : 4 : attrs = sysdb_new_attrs(tmp_ctx);
377 [ + - ]: 4 : if (!attrs) {
378 : : ret = ENOMEM;
379 : : goto done;
380 : : }
381 : : } else {
382 : : attrs = extra_attrs;
383 : : }
384 : :
385 : 4 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
386 [ + - ]: 4 : if (ret) goto done;
387 : :
388 [ + - ]: 4 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
389 : : ((cache_timeout) ?
390 : 4 : (now + cache_timeout) : 0));
391 [ + - ]: 4 : if (ret) goto done;
392 : :
393 : 4 : ret = sysdb_set_entry_attr(sysdb, update_dn, attrs, SYSDB_MOD_REP);
394 [ + - ]: 4 : if (ret != EOK) goto done;
395 : :
396 [ - + ]: 4 : if (remove_attrs) {
397 : 0 : ret = sysdb_remove_attrs(sysdb, primary_name,
398 : : SYSDB_MEMBER_SERVICE,
399 : : remove_attrs);
400 [ # # ]: 0 : if (ret != EOK) {
401 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
402 : : ("Could not remove missing attributes: [%s]\n",
403 : : strerror(ret)));
404 : : goto done;
405 : : }
406 : : }
407 : :
408 : 4 : ret = sysdb_transaction_commit(sysdb);
409 [ - + ]: 4 : if (ret != EOK) {
410 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
411 : : goto done;
412 : : }
413 : : in_transaction = false;
414 : :
415 : : done:
416 [ - + ]: 4 : if (in_transaction) {
417 : 0 : sret = sysdb_transaction_cancel(sysdb);
418 [ # # ]: 0 : if (sret != EOK) {
419 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
[ # # ][ # # ]
[ # # ]
420 : : }
421 : : }
422 : 4 : talloc_free(tmp_ctx);
423 : : return ret;
424 : : }
425 : :
426 : : struct ldb_dn *
427 : 6 : sysdb_svc_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
428 : : const char *domain, const char *name)
429 : : {
430 : : errno_t ret;
431 : : char *clean_name;
432 : : struct ldb_dn *dn;
433 : :
434 : 6 : ret = sysdb_dn_sanitize(NULL, name, &clean_name);
435 [ + - ]: 6 : if (ret != EOK) {
436 : : return NULL;
437 : : }
438 : :
439 : 6 : dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_SVC,
440 : : clean_name, domain);
441 : 6 : talloc_free(clean_name);
442 : :
443 : : return dn;
444 : : }
445 : :
446 : : errno_t
447 : 5 : sysdb_svc_add(TALLOC_CTX *mem_ctx,
448 : : struct sysdb_ctx *sysdb,
449 : : const char *primary_name,
450 : : int port,
451 : : const char **aliases,
452 : : const char **protocols,
453 : : struct ldb_dn **dn)
454 : : {
455 : : errno_t ret;
456 : : int lret;
457 : : TALLOC_CTX *tmp_ctx;
458 : : struct ldb_message *msg;
459 : : unsigned long i;
460 : :
461 : 5 : tmp_ctx = talloc_new(NULL);
462 [ + - ]: 5 : if (!tmp_ctx) return ENOMEM;
463 : :
464 : 5 : msg = ldb_msg_new(tmp_ctx);
465 [ + - ]: 5 : if (!msg) {
466 : : ret = ENOMEM;
467 : : goto done;
468 : : }
469 : :
470 : : /* svc dn */
471 : 5 : msg->dn = sysdb_svc_dn(sysdb, msg, sysdb->domain->name, primary_name);
472 [ + - ]: 5 : if (!msg->dn) {
473 : : ret = ENOMEM;
474 : : goto done;
475 : : }
476 : :
477 : : /* Objectclass */
478 : 5 : ret = add_string(msg, LDB_FLAG_MOD_ADD,
479 : : SYSDB_OBJECTCLASS, SYSDB_SVC_CLASS);
480 [ + - ]: 5 : if (ret != EOK) goto done;
481 : :
482 : : /* Set the primary name */
483 : 5 : ret = add_string(msg, LDB_FLAG_MOD_ADD,
484 : : SYSDB_NAME, primary_name);
485 [ + - ]: 5 : if (ret != EOK) goto done;
486 : :
487 : : /* Set the port number */
488 : 5 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD,
489 : : SYSDB_SVC_PORT, port);
490 [ + - ]: 5 : if (ret != EOK) goto done;
491 : :
492 : : /* If this service has any aliases, include them */
493 [ + - ][ + - ]: 5 : if (aliases && aliases[0]) {
494 : : /* Set the name aliases */
495 : 5 : lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS,
496 : : LDB_FLAG_MOD_ADD, NULL);
497 [ + - ]: 5 : if (lret != LDB_SUCCESS) {
498 : 0 : ret = sysdb_error_to_errno(lret);
499 : 0 : goto done;
500 : : }
501 [ + + ]: 15 : for (i=0; aliases[i]; i++) {
502 : 10 : lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]);
503 [ - + ]: 10 : if (lret != LDB_SUCCESS) {
504 : 0 : ret = sysdb_error_to_errno(lret);
505 : 0 : goto done;
506 : : }
507 : : }
508 : : }
509 : :
510 : : /* Set the protocols */
511 : 5 : lret = ldb_msg_add_empty(msg, SYSDB_SVC_PROTO,
512 : : LDB_FLAG_MOD_ADD, NULL);
513 [ + - ]: 5 : if (lret != LDB_SUCCESS) {
514 : 0 : ret = sysdb_error_to_errno(lret);
515 : 0 : goto done;
516 : : }
517 [ + + ]: 15 : for (i=0; protocols[i]; i++) {
518 : 10 : lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]);
519 [ - + ]: 10 : if (lret != LDB_SUCCESS) {
520 : 0 : ret = sysdb_error_to_errno(lret);
521 : 0 : goto done;
522 : : }
523 : : }
524 : :
525 : : /* creation time */
526 : 5 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
527 : 5 : (unsigned long)time(NULL));
528 [ + - ]: 5 : if (ret) goto done;
529 : :
530 : 5 : lret = ldb_add(sysdb->ldb, msg);
531 : 5 : ret = sysdb_error_to_errno(lret);
532 : :
533 [ + + ]: 5 : if (ret == EOK && dn) {
534 : 3 : *dn = talloc_steal(mem_ctx, msg->dn);
535 : : }
536 : :
537 : : done:
538 [ - + ]: 5 : if (ret) {
539 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
540 : : ("Error: %d (%s)\n", ret, strerror(ret)));
541 : : }
542 : 5 : talloc_free(tmp_ctx);
543 : 5 : return ret;
544 : : }
545 : :
546 : : static errno_t
547 : 1 : sysdb_svc_update(struct sysdb_ctx *sysdb,
548 : : struct ldb_dn *dn,
549 : : int port,
550 : : const char **aliases,
551 : : const char **protocols)
552 : : {
553 : : errno_t ret;
554 : : struct ldb_message *msg;
555 : : int lret;
556 : : unsigned int i;
557 : :
558 [ + - ][ + - ]: 1 : if (!dn || !protocols || !protocols[0]) {
559 : : return EINVAL;
560 : : }
561 : :
562 : 1 : msg = ldb_msg_new(NULL);
563 [ + - ]: 1 : if (!msg) {
564 : : ret = ENOMEM;
565 : : goto done;
566 : : }
567 : :
568 : 1 : msg->dn = dn;
569 : :
570 : : /* Update the port */
571 : 1 : ret = add_ulong(msg, SYSDB_MOD_REP,
572 : : SYSDB_SVC_PORT, port);
573 [ + - ]: 1 : if (ret != EOK) goto done;
574 : :
575 [ + - ][ + - ]: 1 : if (aliases && aliases[0]) {
576 : : /* Update the aliases */
577 : 1 : lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, SYSDB_MOD_REP, NULL);
578 [ + - ]: 1 : if (lret != LDB_SUCCESS) {
579 : : ret = ENOMEM;
580 : : goto done;
581 : : }
582 : :
583 [ + + ]: 3 : for (i = 0; aliases[i]; i++) {
584 : 2 : lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]);
585 [ + - ]: 2 : if (lret != LDB_SUCCESS) {
586 : : ret = EINVAL;
587 : : goto done;
588 : : }
589 : : }
590 : : }
591 : :
592 : : /* Update the protocols */
593 : 1 : lret = ldb_msg_add_empty(msg, SYSDB_SVC_PROTO, SYSDB_MOD_REP, NULL);
594 [ + - ]: 1 : if (lret != LDB_SUCCESS) {
595 : : ret = ENOMEM;
596 : : goto done;
597 : : }
598 : :
599 [ + + ]: 3 : for (i = 0; protocols[i]; i++) {
600 : 2 : lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]);
601 [ + - ]: 2 : if (lret != LDB_SUCCESS) {
602 : : ret = EINVAL;
603 : : goto done;
604 : : }
605 : : }
606 : :
607 : 1 : lret = ldb_modify(sysdb->ldb, msg);
608 : 1 : ret = sysdb_error_to_errno(lret);
609 : :
610 : : done:
611 [ - + ]: 1 : if (ret) {
612 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
613 : : ("Error: %d (%s)\n", ret, strerror(ret)));
614 : : }
615 : 1 : talloc_free(msg);
616 : : return ret;
617 : : }
618 : :
619 : : errno_t
620 : 1 : sysdb_svc_remove_alias(struct sysdb_ctx *sysdb,
621 : : struct ldb_dn *dn,
622 : : const char *alias)
623 : : {
624 : : errno_t ret;
625 : : struct ldb_message *msg;
626 : : int lret;
627 : :
628 : 1 : msg = ldb_msg_new(NULL);
629 [ + - ]: 1 : if (!msg) {
630 : : ret = ENOMEM;
631 : : goto done;
632 : : }
633 : :
634 : 1 : msg->dn = dn;
635 : :
636 : 1 : ret = add_string(msg, SYSDB_MOD_DEL,
637 : : SYSDB_NAME_ALIAS, alias);
638 [ + - ]: 1 : if (ret != EOK) goto done;
639 : :
640 : 1 : lret = ldb_modify(sysdb->ldb, msg);
641 : 1 : ret = sysdb_error_to_errno(lret);
642 : :
643 : : done:
644 [ - + ]: 1 : if (ret) {
645 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
646 : : ("Error: %d (%s)\n", ret, strerror(ret)));
647 : : }
648 : 1 : talloc_zfree(msg);
649 : 1 : return ret;
650 : : }
651 : :
652 : : errno_t
653 : 2 : sysdb_svc_delete(struct sysdb_ctx *sysdb,
654 : : const char *name,
655 : : int port,
656 : : const char *proto)
657 : : {
658 : : errno_t ret, sret;
659 : : TALLOC_CTX *tmp_ctx;
660 : : struct ldb_result *res;
661 : : unsigned int i;
662 : 2 : bool in_transaction = false;
663 : :
664 : 2 : tmp_ctx = talloc_new(NULL);
665 [ + - ]: 2 : if (!tmp_ctx) {
666 : : return ENOMEM;
667 : : }
668 : :
669 : 2 : ret = sysdb_transaction_start(sysdb);
670 [ - + ]: 2 : if (ret != EOK) {
671 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
[ # # ][ # # ]
[ # # ]
672 : : goto done;
673 : : }
674 : :
675 : 2 : in_transaction = true;
676 : :
677 [ + + ]: 2 : if (name) {
678 : 1 : ret = sysdb_getservbyname(tmp_ctx, sysdb, name, proto, &res);
679 [ + - ]: 1 : if (ret != EOK && ret != ENOENT) goto done;
680 [ + - ]: 1 : if (ret == ENOENT) {
681 : : /* Doesn't exist in the DB. Nothing to do */
682 : : ret = EOK;
683 : : goto done;
684 : : }
685 : : } else {
686 : 1 : ret = sysdb_getservbyport(tmp_ctx, sysdb, port, proto, &res);
687 [ + - ]: 1 : if (ret != EOK && ret != ENOENT) goto done;
688 [ + - ]: 2 : if (ret == ENOENT) {
689 : : /* Doesn't exist in the DB. Nothing to do */
690 : : ret = EOK;
691 : : goto done;
692 : : }
693 : : }
694 : :
695 : : /* There should only be one matching entry,
696 : : * but if there are multiple, we should delete
697 : : * them all to de-corrupt the DB.
698 : : */
699 [ + + ]: 4 : for (i = 0; i < res->count; i++) {
700 : 2 : ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, false);
701 [ + - ]: 2 : if (ret != EOK) goto done;
702 : : }
703 : :
704 : 2 : ret = sysdb_transaction_commit(sysdb);
705 [ - + ]: 2 : if (ret != EOK) {
706 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
707 : : goto done;
708 : : }
709 : : in_transaction = false;
710 : :
711 : : done:
712 [ - + ]: 2 : if (in_transaction) {
713 : 0 : sret = sysdb_transaction_cancel(sysdb);
714 [ # # ]: 0 : if (sret != EOK) {
715 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
716 : : ("Could not cancel transaction\n"));
717 : : }
718 : : }
719 : :
720 [ - + ]: 2 : if (ret != EOK && ret != ENOENT) {
721 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
722 : : ("Error: %d (%s)\n", ret, strerror(ret)));
723 : : }
724 : 2 : talloc_zfree(tmp_ctx);
725 : : return ret;
726 : : }
727 : :
728 : :
729 : : errno_t
730 : 0 : sysdb_enumservent(TALLOC_CTX *mem_ctx,
731 : : struct sysdb_ctx *sysdb,
732 : : struct ldb_result **_res)
733 : : {
734 : : errno_t ret;
735 : : int lret;
736 : : TALLOC_CTX *tmp_ctx;
737 : : static const char *attrs[] = SYSDB_SVC_ATTRS;
738 : : struct ldb_dn *base_dn;
739 : : struct ldb_result *res;
740 : :
741 : 0 : *_res = NULL;
742 : :
743 : 0 : tmp_ctx = talloc_new(NULL);
744 [ # # ]: 0 : if (!tmp_ctx) {
745 : : return ENOMEM;
746 : : }
747 : :
748 : 0 : base_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
749 : : SYSDB_TMPL_SVC_BASE,
750 : 0 : sysdb->domain->name);
751 [ # # ]: 0 : if (!base_dn) {
752 : : ret = ENOMEM;
753 : : goto done;
754 : : }
755 : :
756 : 0 : lret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
757 : : LDB_SCOPE_SUBTREE, attrs,
758 : : SYSDB_SC);
759 [ # # ]: 0 : if (lret != LDB_SUCCESS) {
760 : 0 : ret = sysdb_error_to_errno(lret);
761 : : goto done;
762 : : }
763 : :
764 [ # # ]: 0 : if (res->count == 0) {
765 : : ret = ENOENT;
766 : : goto done;
767 : : }
768 : :
769 : 0 : *_res = talloc_steal(mem_ctx, res);
770 : :
771 : 0 : ret = EOK;
772 : :
773 : : done:
774 : 0 : talloc_free(tmp_ctx);
775 : : return ret;
776 : : }
777 : :
778 : : errno_t
779 : 0 : sysdb_set_service_attr(struct sysdb_ctx *sysdb,
780 : : const char *name,
781 : : struct sysdb_attrs *attrs,
782 : : int mod_op)
783 : : {
784 : : errno_t ret;
785 : : struct ldb_dn *dn;
786 : : TALLOC_CTX *tmp_ctx;
787 : :
788 : 0 : tmp_ctx = talloc_new(NULL);
789 [ # # ]: 0 : if (!tmp_ctx) {
790 : : return ENOMEM;
791 : : }
792 : :
793 : 0 : dn = sysdb_svc_dn(sysdb, tmp_ctx, sysdb->domain->name, name);
794 [ # # ]: 0 : if (!dn) {
795 : : ret = ENOMEM;
796 : : goto done;
797 : : }
798 : :
799 : 0 : ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
800 : :
801 : : done:
802 : 0 : talloc_free(tmp_ctx);
803 : 0 : return ret;
804 : 1 : }
|