/* * Public interface for deleting groups */ int groupdel(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct ops_ctx *data) { struct ldb_dn *group_dn; int ret; data->sysdb_fqname = sss_create_internal_fqname(data, data->name, data->domain->name); if (data->sysdb_fqname == NULL) { return ENOMEM; } group_dn = sysdb_group_dn(mem_ctx, data->domain, data->sysdb_fqname); if (group_dn == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct a group DN\n"); return ENOMEM; } ret = sysdb_delete_entry(sysdb, group_dn, false); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Removing group failed: %s (%d)\n", strerror(ret), ret); } flush_nscd_cache(NSCD_DB_GROUP); return ret; }
errno_t sysdb_del_autofsentry(struct sysdb_ctx *sysdb_ctx, const char *entry_dn) { struct ldb_dn *dn; errno_t ret; dn = ldb_dn_new(NULL, sysdb_ctx_get_ldb(sysdb_ctx), entry_dn); if (!dn) { return ENOMEM; } ret = sysdb_delete_entry(sysdb_ctx, dn, true); talloc_free(dn); return ret; }
/* * Public interface for deleting groups */ int groupdel(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct ops_ctx *data) { struct ldb_dn *group_dn; int ret; group_dn = sysdb_group_dn(sysdb, mem_ctx, data->domain, data->name); if (group_dn == NULL) { DEBUG(1, ("Could not construct a group DN\n")); return ENOMEM; } ret = sysdb_delete_entry(sysdb, group_dn, false); if (ret) { DEBUG(2, ("Removing group failed: %s (%d)\n", strerror(ret), ret)); } flush_nscd_cache(NSCD_DB_GROUP); return ret; }
/* * Public interface for deleting users */ int userdel(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct ops_ctx *data) { struct ldb_dn *user_dn; int ret; user_dn = sysdb_user_dn(sysdb, mem_ctx, data->domain, data->name); if (!user_dn) { DEBUG(1, ("Could not construct a user DN\n")); return ENOMEM; } ret = sysdb_delete_entry(sysdb, user_dn, false); if (ret) { DEBUG(2, ("Removing user failed: %s (%d)\n", strerror(ret), ret)); } flush_nscd_cache(NSCD_DB_PASSWD); flush_nscd_cache(NSCD_DB_GROUP); return ret; }
errno_t sysdb_svc_delete(struct sss_domain_info *domain, const char *name, int port, const char *proto) { errno_t ret, sret; TALLOC_CTX *tmp_ctx; struct ldb_result *res; unsigned int i; bool in_transaction = false; struct sysdb_ctx *sysdb = domain->sysdb; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } ret = sysdb_transaction_start(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); goto done; } in_transaction = true; if (name) { ret = sysdb_getservbyname(tmp_ctx, domain, name, proto, &res); if (ret != EOK && ret != ENOENT) goto done; if (ret == ENOENT) { /* Doesn't exist in the DB. Nothing to do */ ret = EOK; goto done; } } else { ret = sysdb_getservbyport(tmp_ctx, domain, port, proto, &res); if (ret != EOK && ret != ENOENT) goto done; if (ret == ENOENT) { /* Doesn't exist in the DB. Nothing to do */ ret = EOK; goto done; } } /* There should only be one matching entry, * but if there are multiple, we should delete * them all to de-corrupt the DB. */ for (i = 0; i < res->count; i++) { ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, false); if (ret != EOK) goto done; } ret = sysdb_transaction_commit(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); goto done; } in_transaction = false; done: if (in_transaction) { sret = sysdb_transaction_cancel(sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); } } if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_TRACE_INTERNAL, "Error: %d (%s)\n", ret, strerror(ret)); } talloc_zfree(tmp_ctx); return ret; }
errno_t sysdb_store_service(struct sss_domain_info *domain, const char *primary_name, int port, const char **aliases, const char **protocols, struct sysdb_attrs *extra_attrs, char **remove_attrs, uint64_t cache_timeout, time_t now) { errno_t ret; errno_t sret; TALLOC_CTX *tmp_ctx; bool in_transaction = false; struct ldb_result *res = NULL; const char *name; unsigned int i; struct ldb_dn *update_dn = NULL; struct sysdb_attrs *attrs; struct sysdb_ctx *sysdb; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; sysdb = domain->sysdb; ret = sysdb_transaction_start(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); goto done; } in_transaction = true; /* Check that the port is unique * If the port appears for any service other than * the one matching the primary_name, we need to * remove them so that getservbyport() can work * properly. Last entry saved to the cache should * always "win". */ ret = sysdb_getservbyport(tmp_ctx, domain, port, NULL, &res); if (ret != EOK && ret != ENOENT) { goto done; } else if (ret != ENOENT) { if (res->count != 1) { /* Somehow the cache has multiple entries with * the same port. This is corrupted. We'll delete * them all to sort it out. */ for (i = 0; i < res->count; i++) { DEBUG(SSSDBG_TRACE_FUNC, "Corrupt cache entry [%s] detected. Deleting\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[i]->dn)); ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete corrupt cache entry [%s]\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[i]->dn)); goto done; } } } else { /* Check whether this is the same name as we're currently * saving to the cache. */ name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); if (!name || strcmp(name, primary_name) != 0) { if (!name) { DEBUG(SSSDBG_CRIT_FAILURE, "A service with no name?\n"); /* Corrupted */ } /* Either this is a corrupt entry or it's another service * claiming ownership of this port. In order to account * for port reassignments, we need to delete the old entry. */ DEBUG(SSSDBG_TRACE_FUNC, "Corrupt or replaced cache entry [%s] detected. " "Deleting\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[0]->dn)); ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete cache entry [%s]\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[0]->dn)); } } } } talloc_zfree(res); /* Ok, ports should now be unique. Now look * the service up by name to determine if we * need to update existing entries or modify * aliases. */ ret = sysdb_getservbyname(tmp_ctx, domain, primary_name, NULL, &res); if (ret != EOK && ret != ENOENT) { goto done; } else if (ret != ENOENT) { /* Found entries */ for (i = 0; i < res->count; i++) { /* Check whether this is the same name as we're currently * saving to the cache. */ name = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_NAME, NULL); if (!name) { /* Corrupted */ DEBUG(SSSDBG_CRIT_FAILURE, "A service with no name?\n"); DEBUG(SSSDBG_TRACE_FUNC, "Corrupt cache entry [%s] detected. Deleting\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[i]->dn)); ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete corrupt cache entry [%s]\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[i]->dn)); goto done; } } else if (strcmp(name, primary_name) == 0) { /* This is the same service name, so we need * to update this entry with the values * provided. */ if(update_dn) { DEBUG(SSSDBG_CRIT_FAILURE, "Two existing services with the same name: [%s]? " "Deleting both.\n", primary_name); /* Delete the entry from the previous pass */ ret = sysdb_delete_entry(sysdb, update_dn, true); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete cache entry [%s]\n", ldb_dn_canonical_string(tmp_ctx, update_dn)); goto done; } /* Delete the new entry as well */ ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete cache entry [%s]\n", ldb_dn_canonical_string(tmp_ctx, res->msgs[i]->dn)); goto done; } update_dn = NULL; } else { update_dn = talloc_steal(tmp_ctx, res->msgs[i]->dn); } } else { /* Another service is claiming this name as an alias. * In order to account for aliases being promoted to * primary names, we need to make sure to remove the * old alias entry. */ ret = sysdb_svc_remove_alias(sysdb, res->msgs[i]->dn, primary_name); if (ret != EOK) goto done; } } talloc_zfree(res); } if (update_dn) { /* Update the existing entry */ ret = sysdb_svc_update(sysdb, update_dn, port, aliases, protocols); } else { /* Add a new entry */ ret = sysdb_svc_add(tmp_ctx, domain, primary_name, port, aliases, protocols, &update_dn); } if (ret != EOK) goto done; /* Set the cache timeout */ if (!extra_attrs) { attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { ret = ENOMEM; goto done; } } else { attrs = extra_attrs; } ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); if (ret) goto done; ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, ((cache_timeout) ? (now + cache_timeout) : 0)); if (ret) goto done; ret = sysdb_set_entry_attr(sysdb, update_dn, attrs, SYSDB_MOD_REP); if (ret != EOK) goto done; if (remove_attrs) { ret = sysdb_remove_attrs(domain, primary_name, SYSDB_MEMBER_SERVICE, remove_attrs); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not remove missing attributes: [%s]\n", strerror(ret)); goto done; } } ret = sysdb_transaction_commit(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); goto done; } in_transaction = false; done: if (in_transaction) { sret = sysdb_transaction_cancel(sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); } } talloc_free(tmp_ctx); return ret; }