summaryrefslogtreecommitdiff
path: root/server/providers
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2009-01-11 17:21:11 -0500
committerSimo Sorce <idra@samba.org>2009-01-11 17:21:11 -0500
commit9aaaff891a0125dc1102668a99338530fb07abfa (patch)
tree42b728f445da593aafdba32ee2fb456324b27c44 /server/providers
parent28fc5582c207d493a33406222da517a241a157ec (diff)
downloadsssd-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.h1
-rw-r--r--server/providers/dp_backend_store.c123
-rw-r--r--server/providers/proxy.c61
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;