summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2009-02-12 15:57:52 -0500
committerSimo Sorce <idra@samba.org>2009-02-13 19:32:27 -0500
commit9b8e4c72933306216507ea869081632fa83a902d (patch)
tree4239393a9495affad5e7655fdad7240bc9418bda
parent314f09402c10ab5a049f25b44f59d75ce5880910 (diff)
downloadsssd-9b8e4c72933306216507ea869081632fa83a902d.tar.gz
sssd-9b8e4c72933306216507ea869081632fa83a902d.tar.bz2
sssd-9b8e4c72933306216507ea869081632fa83a902d.zip
Make backend requests async
-rw-r--r--server/providers/data_provider.c6
-rw-r--r--server/providers/data_provider_be.c237
-rw-r--r--server/providers/dp_backend.h31
-rw-r--r--server/providers/proxy.c397
4 files changed, 599 insertions, 72 deletions
diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c
index e361dfc8..aa66c8e5 100644
--- a/server/providers/data_provider.c
+++ b/server/providers/data_provider.c
@@ -194,7 +194,6 @@ static int dp_monitor_init(struct dp_ctx *dpctx)
}
static void be_identity_check(DBusPendingCall *pending, void *data);
-static void be_online_check(DBusPendingCall *pending, void *data);
static void be_got_account_info(DBusPendingCall *pending, void *data);
static int dbus_dp_init(struct sbus_conn_ctx *conn_ctx, void *data)
@@ -385,11 +384,6 @@ done:
dbus_message_unref(reply);
}
-static void be_online_check(DBusPendingCall *pending, void *data)
-{
- return;
-}
-
static void be_got_account_info(DBusPendingCall *pending, void *data)
{
struct dp_be_request *bereq;
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index ad551c23..7b491ce7 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -147,15 +147,110 @@ static int be_identity(DBusMessage *message, void *data, DBusMessage **r)
return EOK;
}
+struct be_async_req {
+ be_req_fn_t fn;
+ struct be_req *req;
+};
+
+static void be_async_req_handler(struct event_context *ev,
+ struct timed_event *te,
+ struct timeval tv, void *pvt)
+{
+ struct be_async_req *async_req;
+
+ async_req = talloc_get_type(pvt, struct be_async_req);
+
+ async_req->fn(async_req->req);
+}
+
+static int be_file_request(struct be_ctx *ctx,
+ be_req_fn_t fn,
+ struct be_req *req)
+{
+ struct be_async_req *areq;
+ struct timed_event *te;
+ struct timeval tv;
+
+ areq = talloc(req, struct be_async_req);
+ if (!areq) {
+ return ENOMEM;
+ }
+ areq->fn = fn;
+ areq->req = req;
+
+ /* fire immediately */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ te = event_add_timed(ctx->ev, req, tv, be_async_req_handler, areq);
+ if (te == NULL) {
+ return EIO;
+ }
+
+ return EOK;
+}
+
+static void online_chk_callback(struct be_req *req, int status,
+ const char *errstr)
+{
+ struct be_online_req *oreq;
+ DBusMessage *reply;
+ DBusConnection *conn;
+ dbus_bool_t dbret;
+ dbus_uint16_t online;
+ dbus_uint16_t err_maj = 0;
+ dbus_uint32_t err_min = 0;
+ const char *err_msg = "Success";
+
+ oreq = talloc_get_type(req->req_data, struct be_online_req);
+
+ if (status != EOK) {
+ online = MOD_OFFLINE;
+ err_maj = DP_ERR_FATAL;
+ err_min = status;
+ err_msg = errstr;
+ }
+
+ online = oreq->online;
+ reply = (DBusMessage *)req->pvt;
+
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &online,
+ DBUS_TYPE_UINT16, &err_maj,
+ DBUS_TYPE_UINT32, &err_min,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(1, ("Failed to generate dbus reply\n"));
+ return;
+ }
+
+ conn = sbus_get_connection(req->be_ctx->dp_ctx->scon_ctx);
+ dbus_connection_send(conn, reply, NULL);
+ dbus_message_unref(reply);
+
+ DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
+ err_maj, err_min, err_msg));
+
+ /* finally free the request */
+ talloc_free(req);
+}
+
+
static int be_check_online(DBusMessage *message, void *data, DBusMessage **r)
{
struct sbus_message_handler_ctx *smh_ctx;
+ struct be_online_req *req;
+ struct be_req *be_req;
struct be_ctx *ctx;
DBusMessage *reply;
dbus_bool_t dbret;
void *user_data;
- int online = 0;
int ret;
+ dbus_uint16_t online;
+ dbus_uint16_t err_maj;
+ dbus_uint32_t err_min;
+ const char *err_msg;
if (!data) return EINVAL;
smh_ctx = talloc_get_type(data, struct sbus_message_handler_ctx);
@@ -165,12 +260,54 @@ static int be_check_online(DBusMessage *message, void *data, DBusMessage **r)
ctx = talloc_get_type(user_data, struct be_ctx);
if (!ctx) return EINVAL;
- ret = ctx->ops->check_online(ctx, &online);
- if (ret != EOK) return ret;
-
reply = dbus_message_new_method_return(message);
+
+ /* process request */
+ be_req = talloc(ctx, struct be_req);
+ if (!be_req) {
+ online = MOD_OFFLINE;
+ err_maj = DP_ERR_FATAL;
+ err_min = ENOMEM;
+ err_msg = "Out of memory";
+ goto done;
+ }
+ be_req->be_ctx = ctx;
+ be_req->fn = online_chk_callback;
+ be_req->pvt = reply;
+
+ req = talloc(be_req, struct be_online_req);
+ if (!req) {
+ online = MOD_OFFLINE;
+ err_maj = DP_ERR_FATAL;
+ err_min = ENOMEM;
+ err_msg = "Out of memory";
+ goto done;
+ }
+ req->online = 0;
+
+ be_req->req_data = req;
+
+ ret = be_file_request(ctx, ctx->ops->check_online, be_req);
+ if (ret != EOK) {
+ online = MOD_OFFLINE;
+ err_maj = DP_ERR_FATAL;
+ err_min = ret;
+ err_msg = "Failed to file request";
+ goto done;
+ }
+
+ return EOK;
+
+done:
+ if (be_req) {
+ talloc_free(be_req);
+ }
+
dbret = dbus_message_append_args(reply,
DBUS_TYPE_UINT16, &online,
+ DBUS_TYPE_UINT16, &err_maj,
+ DBUS_TYPE_UINT32, &err_min,
+ DBUS_TYPE_STRING, &err_msg,
DBUS_TYPE_INVALID);
if (!dbret) return EIO;
@@ -178,9 +315,51 @@ static int be_check_online(DBusMessage *message, void *data, DBusMessage **r)
return EOK;
}
+
+static void acctinfo_callback(struct be_req *req, int status,
+ const char *errstr)
+{
+ DBusMessage *reply;
+ DBusConnection *conn;
+ dbus_bool_t dbret;
+ dbus_uint16_t err_maj = 0;
+ dbus_uint32_t err_min = 0;
+ const char *err_msg = "Success";
+
+ if (status != EOK) {
+ err_maj = DP_ERR_FATAL;
+ err_min = status;
+ err_msg = errstr;
+ }
+
+ reply = (DBusMessage *)req->pvt;
+
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &err_maj,
+ DBUS_TYPE_UINT32, &err_min,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(1, ("Failed to generate dbus reply\n"));
+ return;
+ }
+
+ conn = sbus_get_connection(req->be_ctx->dp_ctx->scon_ctx);
+ dbus_connection_send(conn, reply, NULL);
+ dbus_message_unref(reply);
+
+ DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
+ err_maj, err_min, err_msg));
+
+ /* finally free the request */
+ talloc_free(req);
+}
+
static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r)
{
struct sbus_message_handler_ctx *smh_ctx;
+ struct be_acct_req *req;
+ struct be_req *be_req;
struct be_ctx *ctx;
DBusMessage *reply;
DBusError dbus_error;
@@ -191,10 +370,11 @@ static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r
int attr_type, filter_type;
char *filter_val;
int ret;
- dbus_uint16_t err_maj = 0;
- dbus_uint32_t err_min = 0;
- const char *err_msg = "Success";
+ dbus_uint16_t err_maj;
+ dbus_uint32_t err_min;
+ const char *err_msg;
+ be_req = NULL;
*r = NULL;
if (!data) return EINVAL;
@@ -259,16 +439,46 @@ static int be_get_account_info(DBusMessage *message, void *data, DBusMessage **r
}
/* process request */
- ret = ctx->ops->get_account_info(ctx, type, attr_type,
- filter_type, filter_val);
+ be_req = talloc(ctx, struct be_req);
+ if (!be_req) {
+ err_maj = DP_ERR_FATAL;
+ err_min = ENOMEM;
+ err_msg = "Out of memory";
+ goto done;
+ }
+ be_req->be_ctx = ctx;
+ be_req->fn = acctinfo_callback;
+ be_req->pvt = reply;
+
+ req = talloc(be_req, struct be_acct_req);
+ if (!req) {
+ err_maj = DP_ERR_FATAL;
+ err_min = ENOMEM;
+ err_msg = "Out of memory";
+ goto done;
+ }
+ req->entry_type = type;
+ req->attr_type = attr_type;
+ req->filter_type = filter_type;
+ req->filter_value = talloc_strdup(req, filter_val);
+
+ be_req->req_data = req;
+
+ ret = be_file_request(ctx, ctx->ops->get_account_info, be_req);
if (ret != EOK) {
err_maj = DP_ERR_FATAL;
err_min = ret;
- err_msg = "Backend error";
+ err_msg = "Failed to file request";
goto done;
}
+ return EOK;
+
done:
+ if (be_req) {
+ talloc_free(be_req);
+ }
+
dbret = dbus_message_append_args(reply,
DBUS_TYPE_UINT16, &err_maj,
DBUS_TYPE_UINT32, &err_min,
@@ -283,13 +493,14 @@ done:
return EOK;
}
+
+
/* mon_cli_init
* sbus channel to the monitor daemon */
static int mon_cli_init(struct be_ctx *ctx)
{
int ret;
char *sbus_address;
- struct service_sbus_ctx *ss_ctx;
struct sbus_method_ctx *sm_ctx;
/* Set up SBUS connection to the monitor */
@@ -309,14 +520,12 @@ static int mon_cli_init(struct be_ctx *ctx)
sbus_address, sm_ctx,
ctx /* Private Data */,
NULL /* Destructor */,
- &ss_ctx);
+ &ctx->ss_ctx);
if (ret != EOK) {
DEBUG(0, ("Failed to connect to monitor services.\n"));
return ret;
}
- ctx->ss_ctx = ss_ctx;
-
return EOK;
}
diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h
index 219df957..765c16ee 100644
--- a/server/providers/dp_backend.h
+++ b/server/providers/dp_backend.h
@@ -41,11 +41,34 @@ struct be_ctx {
void *pvt_data;
};
+struct be_req;
+
+typedef void (*be_async_callback_t)(struct be_req *, int, const char *);
+
+struct be_req {
+ struct be_ctx *be_ctx;
+ void *req_data;
+
+ be_async_callback_t fn;
+ void *pvt;
+};
+
+struct be_acct_req {
+ int entry_type;
+ int attr_type;
+ int filter_type;
+ char *filter_value;
+};
+
+struct be_online_req {
+ int online;
+};
+
+typedef void (*be_req_fn_t)(struct be_req *);
+
struct be_mod_ops {
- int (*check_online)(struct be_ctx *, int *reply);
- int (*get_account_info)(struct be_ctx *,
- int entry_type, int attr_type,
- int filter_type, char *filter_value);
+ be_req_fn_t check_online;
+ be_req_fn_t get_account_info;
};
#endif /* __DP_BACKEND_H___ */
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index a9469219..62638c1f 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -55,67 +55,82 @@ struct proxy_ctx {
struct proxy_nss_ops ops;
};
-static int get_pw_name(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, char *name)
+static void proxy_reply(struct be_req *req, int error, const char *errstr)
{
- struct proxy_nss_ops *ops = &proxy_ctx->ops;
+ return req->fn(req, error, errstr);
+}
+
+static void get_pw_name(struct be_req *req, char *name)
+{
+ struct proxy_ctx *ctx;
enum nss_status status;
struct passwd result;
char *buffer;
int ret;
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
buffer = talloc_size(NULL, 4096);
- if (!buffer) return ENOMEM;
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
- status = ops->getpwnam_r(name, &result, buffer, 4096, &ret);
+ status = ctx->ops.getpwnam_r(name, &result, buffer, 4096, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
- ret = sysdb_posix_remove_user(be_ctx, be_ctx->sysdb,
- be_ctx->domain, name);
+ ret = sysdb_posix_remove_user(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, name);
break;
case NSS_STATUS_SUCCESS:
- ret = sysdb_posix_store_user(be_ctx, be_ctx->sysdb, be_ctx->domain,
+ ret = sysdb_posix_store_user(req, req->be_ctx->sysdb,
+ req->be_ctx->domain,
result.pw_name, result.pw_passwd,
result.pw_uid, result.pw_gid,
- result.pw_gecos, result.pw_dir,
- result.pw_shell);
+ result.pw_gecos, result.pw_dir,
+ result.pw_shell);
break;
default:
DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n",
name, ret, strerror(ret)));
talloc_free(buffer);
- return ret;
+ return proxy_reply(req, ret, "Operation failed");
}
if (ret != EOK) {
DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n",
name, ret));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
}
talloc_free(buffer);
- return ret;
+ return proxy_reply(req, EOK, NULL);
}
-static int get_pw_uid(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, uid_t uid)
+static void get_pw_uid(struct be_req *req, uid_t uid)
{
- struct proxy_nss_ops *ops = &proxy_ctx->ops;
+ struct proxy_ctx *ctx;
enum nss_status status;
struct passwd result;
char *buffer;
int ret;
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
buffer = talloc_size(NULL, 4096);
- if (!buffer) return ENOMEM;
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
- status = ops->getpwuid_r(uid, &result, buffer, 4096, &ret);
+ status = ctx->ops.getpwuid_r(uid, &result, buffer, 4096, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
- ret = sysdb_posix_remove_user_by_uid(be_ctx, be_ctx->sysdb,
- be_ctx->domain,uid);
+ ret = sysdb_posix_remove_user_by_uid(req, req->be_ctx->sysdb,
+ req->be_ctx->domain,uid);
break;
case NSS_STATUS_SUCCESS:
- ret = sysdb_posix_store_user(be_ctx, be_ctx->sysdb, be_ctx->domain,
+ ret = sysdb_posix_store_user(req, req->be_ctx->sysdb,
+ req->be_ctx->domain,
result.pw_name, result.pw_passwd,
result.pw_uid, result.pw_gid,
result.pw_gecos, result.pw_dir,
@@ -125,82 +140,368 @@ static int get_pw_uid(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, uid_t
DEBUG(2, ("proxy -> getpwuid_r failed for '%lu' (%d)[%s]\n",
(unsigned long)uid, ret, strerror(ret)));
talloc_free(buffer);
- return ret;
+ return proxy_reply(req, ret, "Operation failed");
}
if (ret != EOK) {
DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n",
(unsigned long)uid, ret));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
}
talloc_free(buffer);
- return ret;
+ return proxy_reply(req, EOK, NULL);
}
-static int proxy_check_online(struct be_ctx *be_ctx, int *reply)
+#define MAX_BUF_SIZE 1024*1024 /* max 1MiB */
+
+static void enum_users(struct be_req *req)
{
- *reply = MOD_ONLINE;
- return EOK;
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct passwd result;
+ char *buffer, *newb;
+ size_t buflen;
+ const char *errstr;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ buflen = 4096;
+ buffer = talloc_size(NULL, buflen);
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.setpwent();
+ if (status != NSS_STATUS_SUCCESS)
+ return proxy_reply(req, EIO, "Operation failed");
+
+ while (status == NSS_STATUS_SUCCESS) {
+
+ status = ctx->ops.getpwent_r(&result, buffer, buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (buflen < MAX_BUF_SIZE) {
+ buflen *= 2;
+ }
+ if (buflen > MAX_BUF_SIZE) {
+ buflen = MAX_BUF_SIZE;
+ }
+ newb = talloc_realloc_size(NULL, buffer, buflen);
+ if (!newb) {
+ errstr = "Out of memory";
+ ret = ENOMEM;
+ goto done;
+ }
+ buffer = newb;
+ status = NSS_STATUS_SUCCESS;
+ break;
+
+ case NSS_STATUS_NOTFOUND:
+ /* we got last one */
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_posix_store_user(req, req->be_ctx->sysdb,
+ req->be_ctx->domain,
+ result.pw_name, result.pw_passwd,
+ result.pw_uid, result.pw_gid,
+ result.pw_gecos, result.pw_dir,
+ result.pw_shell);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ (unsigned long)result.pw_name, ret, strerror(ret)));
+ }
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ errstr = "Operation failed";
+ goto done;
+ }
+ }
+
+ errstr = NULL;
+ ret = EOK;
+
+done:
+ talloc_free(buffer);
+ ctx->ops.endpwent();
+ return proxy_reply(req, ret, errstr);
+}
+
+static void get_gr_name(struct be_req *req, char *name)
+{
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct group result;
+ char *buffer;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ buffer = talloc_size(NULL, 4096);
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getgrnam_r(name, &result, buffer, 4096, &ret);
+
+ switch (status) {
+ case NSS_STATUS_NOTFOUND:
+ ret = sysdb_posix_remove_group(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, name);
+ break;
+ case NSS_STATUS_SUCCESS:
+ /* FIXME: check members are all available or fetch them */
+ ret = sysdb_posix_store_group(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, result.gr_name,
+ result.gr_gid, result.gr_mem);
+ break;
+ default:
+ DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n",
+ name, ret, strerror(ret)));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n",
+ name, ret));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ talloc_free(buffer);
+ return proxy_reply(req, EOK, NULL);
+}
+
+static void get_gr_gid(struct be_req *req, gid_t gid)
+{
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct group result;
+ char *buffer;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ buffer = talloc_size(NULL, 4096);
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getgrgid_r(gid, &result, buffer, 4096, &ret);
+
+ switch (status) {
+ case NSS_STATUS_NOTFOUND:
+ ret = sysdb_posix_remove_group_by_gid(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, gid);
+ break;
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_posix_store_group(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, result.gr_name,
+ result.gr_gid, result.gr_mem);
+ break;
+ default:
+ DEBUG(2, ("proxy -> getgrgid_r failed for '%lu' (%d)[%s]\n",
+ (unsigned long)gid, ret, strerror(ret)));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n",
+ (unsigned long)gid, ret));
+ talloc_free(buffer);
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ talloc_free(buffer);
+ return proxy_reply(req, EOK, NULL);
}
-static int proxy_get_account_info(struct be_ctx *be_ctx,
- int entry_type, int attr_type,
- int filter_type, char *filter_value)
+static void enum_groups(struct be_req *req)
{
struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct group result;
+ char *buffer, *newb;
+ size_t buflen;
+ const char * errstr;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ buflen = 4096;
+ buffer = talloc_size(NULL, buflen);
+ if (!buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.setgrent();
+ if (status != NSS_STATUS_SUCCESS)
+ return proxy_reply(req, EIO, "Operation failed");
+
+ while (status == NSS_STATUS_SUCCESS) {
+
+ status = ctx->ops.getgrent_r(&result, buffer, buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (buflen < MAX_BUF_SIZE) {
+ buflen *= 2;
+ }
+ if (buflen > MAX_BUF_SIZE) {
+ buflen = MAX_BUF_SIZE;
+ }
+ newb = talloc_realloc_size(NULL, buffer, buflen);
+ if (!newb) {
+ errstr = "Out of memory";
+ ret = ENOMEM;
+ goto done;
+ }
+ buffer = newb;
+ status = NSS_STATUS_SUCCESS;
+ break;
+
+ case NSS_STATUS_NOTFOUND:
+ /* we got last one */
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_posix_store_group(req, req->be_ctx->sysdb,
+ req->be_ctx->domain, result.gr_name,
+ result.gr_gid, result.gr_mem);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ (unsigned long)result.gr_name, ret, strerror(ret)));
+ }
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ errstr = "Operation failed";
+ goto done;
+ }
+ }
+
+ errstr = NULL;
+ ret = EOK;
+
+done:
+ talloc_free(buffer);
+ ctx->ops.endgrent();
+ return proxy_reply(req, ret, errstr);
+}
+
+/* TODO: actually do check something */
+static void proxy_check_online(struct be_req *req)
+{
+ struct be_online_req *oreq;
+
+ oreq = talloc_get_type(req->req_data, struct be_online_req);
+
+ oreq->online = MOD_ONLINE;
+
+ req->fn(req, EOK, NULL);
+}
+
+/* TODO: See if we can use async_req code */
+static void proxy_get_account_info(struct be_req *req)
+{
+ struct be_acct_req *ar;
uid_t uid;
+ gid_t gid;
- ctx = talloc_get_type(be_ctx->pvt_data, struct proxy_ctx);
+ ar = talloc_get_type(req->req_data, struct be_acct_req);
- switch (entry_type) {
+ switch (ar->entry_type) {
case BE_REQ_USER: /* user */
- switch (filter_type) {
+ switch (ar->filter_type) {
case BE_FILTER_NAME:
- switch (attr_type) {
+ switch (ar->attr_type) {
case BE_ATTR_CORE:
- if (strchr(filter_value, '*')) {
- /* TODO */
+ if (strchr(ar->filter_value, '*')) {
+ return enum_users(req);
} else {
- return get_pw_name(be_ctx, ctx, filter_value);
+ return get_pw_name(req, ar->filter_value);
}
break;
default:
- return EINVAL;
+ return proxy_reply(req, EINVAL, "Invalid attr type");
}
break;
case BE_FILTER_IDNUM:
- switch (attr_type) {
+ switch (ar->attr_type) {
case BE_ATTR_CORE:
- if (strchr(filter_value, '*')) {
- return EINVAL;
+ if (strchr(ar->filter_value, '*')) {
+ return proxy_reply(req, EINVAL, "Invalid attr type");
} else {
char *endptr;
errno = 0;
- uid = (uid_t)strtol(filter_value, &endptr, 0);
- if (errno || *endptr || (filter_value == endptr)) {
- return EINVAL;
+ uid = (uid_t)strtol(ar->filter_value, &endptr, 0);
+ if (errno || *endptr || (ar->filter_value == endptr)) {
+ return proxy_reply(req, EINVAL, "Invalid attr type");
}
- return get_pw_uid(be_ctx, ctx, uid);
+ return get_pw_uid(req, uid);
}
break;
default:
- return EINVAL;
+ return proxy_reply(req, EINVAL, "Invalid attr type");
}
break;
default:
- return EINVAL;
+ return proxy_reply(req, EINVAL, "Invalid filter type");
}
break;
case BE_REQ_GROUP: /* group */
- /* TODO */
- return EOK;
+ switch (ar->filter_type) {
+ case BE_FILTER_NAME:
+ switch (ar->attr_type) {
+ case BE_ATTR_CORE:
+ if (strchr(ar->filter_value, '*')) {
+ return enum_groups(req);
+ } else {
+ return get_gr_name(req, ar->filter_value);
+ }
+ break;
+ default:
+ return proxy_reply(req, EINVAL, "Invalid attr type");
+ }
+ break;
+ case BE_FILTER_IDNUM:
+ switch (ar->attr_type) {
+ case BE_ATTR_CORE:
+ if (strchr(ar->filter_value, '*')) {
+ return proxy_reply(req, EINVAL, "Invalid attr type");
+ } else {
+ char *endptr;
+ errno = 0;
+ gid = (gid_t)strtol(ar->filter_value, &endptr, 0);
+ if (errno || *endptr || (ar->filter_value == endptr)) {
+ return proxy_reply(req, EINVAL, "Invalid attr type");
+ }
+ return get_gr_gid(req, gid);
+ }
+ break;
+ default:
+ return proxy_reply(req, EINVAL, "Invalid attr type");
+ }
+ break;
+ default:
+ return proxy_reply(req, EINVAL, "Invalid filter type");
+ }
+ break;
+
default: /*fail*/
- return EINVAL;
+ return proxy_reply(req, EINVAL, "Invalid request type");
}
-
- return EOK;
}
struct be_mod_ops proxy_mod_ops = {