Example #1
0
/*
 * 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;
}
Example #2
0
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;
}
Example #3
0
/*
 * 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;
}
Example #4
0
/*
 * 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;
}
Example #5
0
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;
}
Example #6
0
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;
}