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