diff options
author | Simo Sorce <idra@samba.org> | 2009-01-11 17:21:11 -0500 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2009-01-11 17:21:11 -0500 |
commit | 9aaaff891a0125dc1102668a99338530fb07abfa (patch) | |
tree | 42b728f445da593aafdba32ee2fb456324b27c44 /server/providers | |
parent | 28fc5582c207d493a33406222da517a241a157ec (diff) | |
download | sssd-9aaaff891a0125dc1102668a99338530fb07abfa.tar.gz sssd-9aaaff891a0125dc1102668a99338530fb07abfa.tar.bz2 sssd-9aaaff891a0125dc1102668a99338530fb07abfa.zip |
Add support for getpwuid in proxy backend
Diffstat (limited to 'server/providers')
-rw-r--r-- | server/providers/dp_backend.h | 1 | ||||
-rw-r--r-- | server/providers/dp_backend_store.c | 123 | ||||
-rw-r--r-- | server/providers/proxy.c | 61 |
3 files changed, 160 insertions, 25 deletions
diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h index c7cb61c4..1ad31d5e 100644 --- a/server/providers/dp_backend.h +++ b/server/providers/dp_backend.h @@ -52,6 +52,7 @@ int dp_be_store_account_posix(struct be_ctx *ctx, uint64_t uid, uint64_t gid, char *gecos, char *homedir, char *shell); int dp_be_remove_account_posix(struct be_ctx *ctx, char *name); +int dp_be_remove_account_posix_by_uid(struct be_ctx *ctx, uid_t uid); int dp_be_cachedb_init(struct be_ctx *ctx); diff --git a/server/providers/dp_backend_store.c b/server/providers/dp_backend_store.c index 9bccb218..f9c55e0b 100644 --- a/server/providers/dp_backend_store.c +++ b/server/providers/dp_backend_store.c @@ -27,6 +27,11 @@ #include "providers/dp_backend.h" #include <time.h> +/* NOTE: these functions ues ldb sync calls, but the cache db is a + * local TDB, so there should never be an issue. + * In case this changes (ex. plugins that contact the network etc.. + * make sure to split functions in multiple async calls */ + int dp_be_store_account_posix(struct be_ctx *ctx, char *name, char *pwd, uint64_t uid, uint64_t gid, @@ -47,7 +52,7 @@ int dp_be_store_account_posix(struct be_ctx *ctx, } account_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb, - "uid=%s,cn=users,cn=%s,cn=remote", + "uid=%s,cn=users,cn=%s,cn=accounts", name, ctx->domain); if (!account_dn) { talloc_free(tmp_ctx); @@ -61,26 +66,8 @@ int dp_be_store_account_posix(struct be_ctx *ctx, goto done; } - res = talloc_zero(tmp_ctx, struct ldb_result); - if (!res) { - ret = ENOMEM; - goto done; - } - - lret = ldb_build_search_req(&req, ctx->ldb, tmp_ctx, - account_dn, LDB_SCOPE_BASE, - "(objectClass=User)", attrs, NULL, - res, ldb_search_default_callback, NULL); - if (lret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build search request (%d) !?\n", lret)); - ret = EIO; - goto done; - } - - lret = ldb_request(ctx->ldb, req); - if (lret == LDB_SUCCESS) { - lret = ldb_wait(req->handle, LDB_WAIT_ALL); - } + lret = ldb_search(ctx->ldb, tmp_ctx, &res, account_dn, + LDB_SCOPE_BASE, attrs, "(objectClass=User)"); if (lret != LDB_SUCCESS) { DEBUG(1, ("Failed to make search request: %s(%d)[%s]\n", ldb_strerror(lret), lret, ldb_errstring(ctx->ldb))); @@ -88,7 +75,6 @@ int dp_be_store_account_posix(struct be_ctx *ctx, goto done; } - talloc_free(req); req = NULL; msg = ldb_msg_new(tmp_ctx); @@ -159,7 +145,7 @@ int dp_be_store_account_posix(struct be_ctx *ctx, lret = ldb_msg_add_empty(msg, "uidNumber", flags, NULL); if (lret == LDB_SUCCESS) { lret = ldb_msg_add_fmt(msg, "uidNumber", - "%lu", (long unsigned)uid); + "%lu", (unsigned long)uid); } if (lret != LDB_SUCCESS) { ret = errno; @@ -176,7 +162,7 @@ int dp_be_store_account_posix(struct be_ctx *ctx, lret = ldb_msg_add_empty(msg, "gidNumber", flags, NULL); if (lret == LDB_SUCCESS) { lret = ldb_msg_add_fmt(msg, "gidNumber", - "%lu", (long unsigned)gid); + "%lu", (unsigned long)gid); } if (lret != LDB_SUCCESS) { ret = errno; @@ -316,6 +302,95 @@ int dp_be_remove_account_posix(struct be_ctx *ctx, char *name) return ret; } +int dp_be_remove_account_posix_by_uid(struct be_ctx *ctx, uid_t uid) +{ + TALLOC_CTX *tmp_ctx; + const char *attrs[] = { "name", "uid", NULL }; + struct ldb_dn *base_dn; + struct ldb_dn *account_dn; + struct ldb_result *res; + int lret, ret; + + tmp_ctx = talloc_new(ctx); + if (!tmp_ctx) { + return ENOMEM; + } + + base_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb, + "cn=users,cn=%s,cn=accounts", ctx->domain); + if (!base_dn) { + talloc_free(tmp_ctx); + return ENOMEM; + } + + lret = ldb_transaction_start(ctx->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret)); + ret = EIO; + goto done; + } + + lret = ldb_search(ctx->ldb, tmp_ctx, &res, base_dn, + LDB_SCOPE_BASE, attrs, + "(&(uid=%lu)(objectClass=User))", + (unsigned long)uid); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to make search request: %s(%d)[%s]\n", + ldb_strerror(lret), lret, ldb_errstring(ctx->ldb))); + ret = EIO; + goto done; + } + + if (res->count == 0) { + ret = EOK; + goto done; + } + if (res->count > 1) { + DEBUG(0, ("Cache DB corrupted, base search returned %d results\n", + res->count)); + ret = EOK; + goto done; + } + + account_dn = ldb_dn_copy(tmp_ctx, res->msgs[0]->dn); + if (!account_dn) { + ret = ENOMEM; + goto done; + } + + talloc_free(res); + res = NULL; + + ret = ldb_delete(ctx->ldb, account_dn); + + if (ret != LDB_SUCCESS) { + DEBUG(2, ("LDB Error: %s(%d)\nError Message: [%s]\n", + ldb_strerror(ret), ret, ldb_errstring(ctx->ldb))); + ret = EIO; + goto done; + } + + lret = ldb_transaction_commit(ctx->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed ldb transaction commit !! (%d)\n", lret)); + ret = EIO; + goto done; + } + + ret = EOK; + +done: + if (ret != EOK) { + lret = ldb_transaction_cancel(ctx->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret)); + } + } + + talloc_free(tmp_ctx); + return ret; +} + /* TODO: Unify with nss_ldb and provide a single cachedb interface */ int dp_be_cachedb_init(struct be_ctx *ctx) diff --git a/server/providers/proxy.c b/server/providers/proxy.c index b5674490..f93a5ede 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -72,7 +72,8 @@ static int get_pw_name(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, char ret = dp_be_remove_account_posix(be_ctx, name); break; case NSS_STATUS_SUCCESS: - ret = dp_be_store_account_posix(be_ctx, name, result.pw_passwd, + ret = dp_be_store_account_posix(be_ctx, + result.pw_name, result.pw_passwd, result.pw_uid, result.pw_gid, result.pw_gecos, result.pw_dir, result.pw_shell); @@ -93,6 +94,46 @@ static int get_pw_name(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, char return ret; } +static int get_pw_uid(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, uid_t uid) +{ + struct proxy_nss_ops *ops = &proxy_ctx->ops; + enum nss_status status; + struct passwd result; + char *buffer; + int ret; + + buffer = talloc_size(NULL, 4096); + if (!buffer) return ENOMEM; + + status = ops->getpwuid_r(uid, &result, buffer, 4096, &ret); + + switch (status) { + case NSS_STATUS_NOTFOUND: + ret = dp_be_remove_account_posix_by_uid(be_ctx, uid); + break; + case NSS_STATUS_SUCCESS: + ret = dp_be_store_account_posix(be_ctx, + result.pw_name, result.pw_passwd, + result.pw_uid, result.pw_gid, + result.pw_gecos, result.pw_dir, + result.pw_shell); + break; + default: + DEBUG(2, ("proxy -> getpwuid_r failed for '%lu' (%d)[%s]\n", + (unsigned long)uid, ret, strerror(ret))); + talloc_free(buffer); + return ret; + } + + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n", + (unsigned long)uid, ret)); + } + + talloc_free(buffer); + return ret; +} + static int proxy_check_online(struct be_ctx *be_ctx, int *reply) { *reply = MOD_ONLINE; @@ -104,6 +145,7 @@ static int proxy_get_account_info(struct be_ctx *be_ctx, int filter_type, char *filter_value) { struct proxy_ctx *ctx; + uid_t uid; ctx = talloc_get_type(be_ctx->pvt_data, struct proxy_ctx); @@ -124,6 +166,23 @@ static int proxy_get_account_info(struct be_ctx *be_ctx, } break; case BE_FILTER_IDNUM: + switch (attr_type) { + case BE_ATTR_CORE: + if (strchr(filter_value, '*')) { + return EINVAL; + } else { + char *endptr; + errno = 0; + uid = (uid_t)strtol(filter_value, &endptr, 0); + if (errno || *endptr || (filter_value == endptr)) { + return EINVAL; + } + return get_pw_uid(be_ctx, ctx, uid); + } + break; + default: + return EINVAL; + } break; default: return EINVAL; |