sysdb_services.c revision a928f7a6bd7681db6e26cba3eb7da22d14288737
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher Stephen Gallagher <sgallagh@redhat.com>
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek Copyright (C) 2012 Red Hat
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek This program is free software; you can redistribute it and/or modify
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan it under the terms of the GNU General Public License as published by
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan the Free Software Foundation; either version 3 of the License, or
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek (at your option) any later version.
a86d6cd05e3f823214587475b83d907f394c035eJakub Hrozek This program is distributed in the hope that it will be useful,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek GNU General Public License for more details.
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher You should have received a copy of the GNU General Public License
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan along with this program. If not, see <http://www.gnu.org/licenses/>.
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek const char **aliases,
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek const char **protocols);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivansysdb_svc_remove_alias(struct sysdb_ctx *sysdb,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *alias);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = sss_filter_sanitize(tmp_ctx, proto, &sanitized_proto);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek subfilter = talloc_asprintf(tmp_ctx, SYSDB_SVC_BYNAME_FILTER,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_search_services(mem_ctx, domain, subfilter,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan res = talloc_zero(mem_ctx, struct ldb_result);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher static const char *attrs[] = SYSDB_SVC_ATTRS;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher ret = sss_filter_sanitize(tmp_ctx, proto, &sanitized_proto);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher subfilter = talloc_asprintf(tmp_ctx, SYSDB_SVC_BYPORT_FILTER,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (unsigned int) port);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_search_services(mem_ctx, domain, subfilter,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher res = talloc_zero(mem_ctx, struct ldb_result);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivansysdb_store_service(struct sss_domain_info *domain,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek const char *name;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek unsigned int i;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* Check that the port is unique
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * If the port appears for any service other than
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * the one matching the primary_name, we need to
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * remove them so that getservbyport() can work
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * properly. Last entry saved to the cache should
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * always "win".
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan ret = sysdb_getservbyport(tmp_ctx, domain, port, NULL, &res);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Somehow the cache has multiple entries with
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher * the same port. This is corrupted. We'll delete
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan * them all to sort it out.
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher "Corrupt cache entry [%s] detected. Deleting\n",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher "Could not delete corrupt cache entry [%s]\n",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Check whether this is the same name as we're currently
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan * saving to the cache.
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan name = ldb_msg_find_attr_as_string(res->msgs[0],
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher if (!name || strcmp(name, primary_name) != 0) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "A service with no name?\n");
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Corrupted */
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek /* Either this is a corrupt entry or it's another service
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek * claiming ownership of this port. In order to account
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek * for port reassignments, we need to delete the old entry.
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Corrupt or replaced cache entry [%s] detected. "
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek "Deleting\n",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Could not delete cache entry [%s]\n",
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek /* Ok, ports should now be unique. Now look
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek * the service up by name to determine if we
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek * need to update existing entries or modify
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_getservbyname(tmp_ctx, domain, primary_name, NULL, &res);
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek } else if (ret != ENOENT) { /* Found entries */
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Check whether this is the same name as we're currently
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek * saving to the cache.
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek name = ldb_msg_find_attr_as_string(res->msgs[i],
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek /* Corrupted */
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek "A service with no name?\n");
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Corrupt cache entry [%s] detected. Deleting\n",
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Could not delete corrupt cache entry [%s]\n",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* This is the same service name, so we need
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek * to update this entry with the values
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Two existing services with the same name: [%s]? "
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek "Deleting both.\n",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Delete the entry from the previous pass */
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek ret = sysdb_delete_entry(sysdb, update_dn, true);
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek "Could not delete cache entry [%s]\n",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Delete the new entry as well */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek "Could not delete cache entry [%s]\n",
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek update_dn = talloc_steal(tmp_ctx, res->msgs[i]->dn);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Another service is claiming this name as an alias.
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek * In order to account for aliases being promoted to
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek * primary names, we need to make sure to remove the
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek * old alias entry.
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* Update the existing entry */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_svc_update(sysdb, update_dn, port, aliases, protocols);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* Add a new entry */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_svc_add(tmp_ctx, domain, primary_name, port,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Set the cache timeout */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_set_entry_attr(sysdb, update_dn, attrs, SYSDB_MOD_REP);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_remove_attrs(domain, primary_name,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "Could not remove missing attributes: [%s]\n",
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivansysdb_svc_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = sysdb_dn_sanitize(NULL, name, &clean_name);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan dn = ldb_dn_new_fmt(mem_ctx, sysdb->ldb, SYSDB_TMPL_SVC,
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek const char **aliases,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek unsigned long i;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan msg->dn = sysdb_svc_dn(domain->sysdb, msg, domain->name, primary_name);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Objectclass */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_SVC_CLASS);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Set the primary name */
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek ret = sysdb_add_string(msg, SYSDB_NAME, primary_name);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek /* Set the port number */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* If this service has any aliases, include them */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Set the name aliases */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS,
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek for (i=0; aliases[i]; i++) {
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* Set the protocols */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek for (i=0; protocols[i]; i++) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* creation time */
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek const char **aliases,
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek unsigned int i;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Update the port */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* Update the aliases */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, SYSDB_MOD_REP, NULL);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan for (i = 0; aliases[i]; i++) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* Update the protocols */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lret = ldb_msg_add_empty(msg, SYSDB_SVC_PROTO, SYSDB_MOD_REP, NULL);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (i = 0; protocols[i]; i++) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan lret = ldb_msg_add_string(msg, SYSDB_SVC_PROTO, protocols[i]);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "ldb_modify failed: [%s](%d)[%s]\n",
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb));
b355dcb54194f498921743ca33304eac35d89718Stephen Gallaghersysdb_svc_remove_alias(struct sysdb_ctx *sysdb,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek ret = sysdb_delete_string(msg, SYSDB_NAME_ALIAS, alias);
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek "ldb_modify failed: [%s](%d)[%s]\n",
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb));
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozeksysdb_svc_delete(struct sss_domain_info *domain,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek const char *name,
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek unsigned int i;
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek ret = sysdb_getservbyname(tmp_ctx, domain, name, proto, &res);
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek /* Doesn't exist in the DB. Nothing to do */
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_getservbyport(tmp_ctx, domain, port, proto, &res);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* Doesn't exist in the DB. Nothing to do */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* There should only be one matching entry,
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek * but if there are multiple, we should delete
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek * them all to de-corrupt the DB.
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, false);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek "Could not cancel transaction\n");
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_search_services(mem_ctx, domain, "",
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozeksysdb_set_service_attr(struct sss_domain_info *domain,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek const char *name,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek dn = sysdb_svc_dn(domain->sysdb, tmp_ctx, domain->name, name);
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_set_entry_attr(domain->sysdb, dn, attrs, mod_op);
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozekerrno_t sysdb_search_services(TALLOC_CTX *mem_ctx,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek const char **attrs,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to build base dn\n");
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_SC, sub_filter);
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n");
f45a20d6ba9e8d695ec3ab707f0cc082999aa4a3Jakub Hrozek ret = sysdb_search_entry(mem_ctx, domain->sysdb, basedn,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan DEBUG(SSSDBG_TRACE_INTERNAL, "No such entry\n");
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan DEBUG(SSSDBG_MINOR_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));