summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2009-03-05 15:39:26 -0500
committerSimo Sorce <ssorce@redhat.com>2009-03-05 17:25:50 -0500
commit132ccd66fb7f7bf583a6ddbed031a2bf5eef473c (patch)
treed8356cdc4c71a6c5f038bf391aa4f22623580ac1 /server
parent16802de42f27a9060eb395751e82c9ad85cb8fe3 (diff)
downloadsssd-132ccd66fb7f7bf583a6ddbed031a2bf5eef473c.tar.gz
sssd-132ccd66fb7f7bf583a6ddbed031a2bf5eef473c.tar.xz
sssd-132ccd66fb7f7bf583a6ddbed031a2bf5eef473c.zip
Implement GetCachedUsers in the InfoPipe
This function allows a caller to retrieve a list of users who have logged in on the system, specifying an optional minimum last login time to trim the list. I modified sysdb_enumpwent to accept an optional search argument. GetCachedUsers takes advantage of this argument to limit the search by the last login time. I also found and fixed a few additional low-memory conditions around D-BUS message replies.
Diffstat (limited to 'server')
-rw-r--r--server/db/sysdb.h3
-rw-r--r--server/db/sysdb_search.c7
-rw-r--r--server/infopipe/infopipe_users.c201
-rw-r--r--server/responder/nss/nsssrv_cmd.c4
4 files changed, 205 insertions, 10 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 544a81f5a..1302cddbd 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -84,6 +84,8 @@
#define SYSDB_INITGR_LEGACY_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_LEGACY_MEMBER"=%s))"
+#define SYSDB_GETCACHED_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_USER_ATTR_LAST_LOGIN">=%llu))"
+
#define SYSDB_PW_ATTRS {SYSDB_PW_NAME, SYSDB_PW_UIDNUM, \
SYSDB_PW_GIDNUM, SYSDB_PW_FULLNAME, \
SYSDB_PW_HOMEDIR, SYSDB_PW_SHELL, \
@@ -199,6 +201,7 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
const char *domain,
bool legacy,
+ const char *expression,
sysdb_callback_t fn, void *ptr);
int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c
index ff18419e9..8b14221da 100644
--- a/server/db/sysdb_search.c
+++ b/server/db/sysdb_search.c
@@ -264,6 +264,7 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *ctx,
const char *domain,
bool legacy,
+ const char *expression,
sysdb_callback_t fn, void *ptr)
{
static const char *attrs[] = SYSDB_PW_ATTRS;
@@ -278,7 +279,11 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- sctx->expression = SYSDB_PWENT_FILTER;
+ if (expression)
+ sctx->expression = expression;
+ else
+ sctx->expression = SYSDB_PWENT_FILTER;
+
sctx->attrs = attrs;
return sysdb_operation(mem_ctx, ctx, user_search, sctx);
diff --git a/server/infopipe/infopipe_users.c b/server/infopipe/infopipe_users.c
index 2928722a1..52082092b 100644
--- a/server/infopipe/infopipe_users.c
+++ b/server/infopipe/infopipe_users.c
@@ -32,17 +32,173 @@
static int attr_comparator(const void *key1, const void *key2);
static int username_comparator(const void *key1, const void *key2);
+struct infp_getcached_ctx {
+ struct infp_req_ctx *infp_req;
+ struct sysdb_req *sysdb_req;
+ char **usernames;
+ uint64_t min_last_login;
+};
+static void infp_users_get_cached_callback(void *ptr,
+ int status,
+ struct ldb_result *res)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ dbus_bool_t dbret;
+ int i;
+ char *username;
+ struct infp_getcached_ctx *infp_getcached_req =
+ talloc_get_type(ptr, struct infp_getcached_ctx);
+
+ if (status != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to enumerate users in the cache db.\n"));
+ talloc_free(infp_getcached_req);
+ return;
+ }
+
+ /* Construct a reply */
+ reply = dbus_message_new_method_return(infp_getcached_req->infp_req->req_message);
+ if(reply == NULL) {
+ talloc_free(infp_getcached_req);
+ return;
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ "s", &array_iter);
+ if (!dbret) goto error;
+
+ for (i = 0; i < res->count; i++) {
+ username = talloc_strdup(infp_getcached_req,
+ ldb_msg_find_attr_as_string(res->msgs[i],
+ SYSDB_PW_NAME,
+ NULL));
+ if (username != NULL) {
+ dbret = dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_STRING, &username);
+ if (!dbret) goto error;
+ }
+ }
+ dbret = dbus_message_iter_close_container(&iter, &array_iter);
+ if(!dbret) goto error;
+
+ sbus_conn_send_reply(infp_getcached_req->infp_req->sconn, reply);
+ dbus_message_unref(reply);
+
+ talloc_free(infp_getcached_req);
+ return;
+
+error:
+ DEBUG(0,
+ ("Critical error constructing reply message for %s\n",
+ INFP_USERS_GET_CACHED));
+ dbus_message_unref(reply);
+ talloc_free(infp_getcached_req);
+ return;
+}
+
int infp_users_get_cached(DBusMessage *message, struct sbus_conn_ctx *sconn)
{
DBusMessage *reply;
+ DBusError error;
+ dbus_bool_t dbret;
+ char *einval_msg;
+ char *search_expression;
+ struct infp_getcached_ctx *infp_getcached_req;
+ int ret;
- reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ /* Arguments */
+ const char *arg_domain;
+ const uint64_t arg_minlastlogin;
- /* send reply */
- sbus_conn_send_reply(sconn, reply);
+ infp_getcached_req = talloc_zero(NULL, struct infp_getcached_ctx);
+ if (infp_getcached_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ /* Create an infp_req_ctx */
+ infp_getcached_req->infp_req =
+ talloc_zero(infp_getcached_req, struct infp_req_ctx);
+ if (infp_getcached_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ infp_getcached_req->infp_req->infp =
+ talloc_get_type(sbus_conn_get_private_data(sconn), struct infp_ctx);
+ infp_getcached_req->infp_req->sconn = sconn;
+ infp_getcached_req->infp_req->req_message = message;
+ infp_getcached_req->infp_req->caller =
+ sysbus_get_caller(infp_getcached_req->infp_req,
+ infp_getcached_req->infp_req->req_message,
+ infp_getcached_req->infp_req->sconn);
+ if (infp_getcached_req->infp_req->caller == NULL) {
+ ret = EIO;
+ goto error;
+ }
+
+ dbus_error_init(&error);
+ dbret = dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &arg_domain,
+ DBUS_TYPE_UINT64, &arg_minlastlogin,
+ DBUS_TYPE_INVALID);
+ if(!dbret) {
+ DEBUG(0, ("Parsing arguments to %s failed: %s:%s\n",
+ INFP_USERS_GET_CACHED, error.name, error.message));
+ einval_msg = talloc_strdup(infp_getcached_req, error.message);
+ dbus_error_free(&error);
+ goto einval;
+ }
+
+ infp_getcached_req->min_last_login = arg_minlastlogin;
+
+ infp_getcached_req->infp_req->domain =
+ btreemap_get_value(infp_getcached_req->infp_req->infp->domain_map,
+ (const void *)arg_domain);
+ /* Check for a valid domain */
+ if(infp_getcached_req->infp_req->domain == NULL) {
+ einval_msg = talloc_strdup(infp_getcached_req, "Invalid domain.");
+ goto einval;
+ }
+
+ /* NOTE: not checking permissions since the
+ * information here is all visible in NSS as well
+ */
+
+ /* Call sysdb_enumpwent with special search parameters */
+ search_expression = talloc_asprintf(infp_getcached_req,
+ SYSDB_GETCACHED_FILTER,
+ infp_getcached_req->min_last_login);
+ ret = sysdb_enumpwent(infp_getcached_req,
+ infp_getcached_req->infp_req->infp->sysdb,
+ infp_getcached_req->infp_req->domain->name,
+ infp_getcached_req->infp_req->domain->legacy,
+ search_expression,
+ infp_users_get_cached_callback, infp_getcached_req);
+ if(ret != EOK) {
+ DEBUG(0, ("Could not read from the cache database.\n"));
+ goto error;
+ }
+
+ return EOK;
+
+einval:
+ reply = dbus_message_new_error(message,
+ DBUS_ERROR_INVALID_ARGS,
+ einval_msg);
+ if(reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ sbus_conn_send_reply(sconn, reply);
dbus_message_unref(reply);
+ talloc_free(infp_getcached_req);
return EOK;
+
+error:
+ talloc_free(infp_getcached_req);
+ return ret;
}
int infp_users_create(DBusMessage *message, struct sbus_conn_ctx *sconn)
@@ -643,6 +799,9 @@ int infp_users_get_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
dbus_free_string_array(attributes);
reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, error.message);
+ if (reply == NULL) {
+ return ENOMEM;
+ }
sbus_conn_send_reply(sconn, reply);
dbus_message_unref(reply);
@@ -654,12 +813,17 @@ int infp_users_get_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
if (username_count < 1) {
/* No usernames received. Return an error */
reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "No usernames specified.");
+ if (reply == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
sbus_conn_send_reply(sconn, reply);
dbus_free_string_array(usernames);
dbus_free_string_array(attributes);
dbus_message_unref(reply);
ret = EOK;
+ goto end;
}
/* Create a infp_getattr_ctx */
@@ -804,7 +968,12 @@ static void infp_do_user_set_attr_callback(void *ptr, int ldb_status, struct ldb
/* Send reply ack */
reply = dbus_message_new_method_return(infp_setattr_req->infp_req->req_message);
+ if(reply == NULL) {
+ talloc_free(infp_setattr_req);
+ return;
+ }
sbus_conn_send_reply(infp_setattr_req->infp_req->sconn, reply);
+ dbus_message_unref(reply);
talloc_free(infp_setattr_req);
}
@@ -1133,17 +1302,22 @@ int infp_users_set_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
return EOK;
-error:
- talloc_free(infp_setattr_req);
- return ret;
-
einval:
reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, einval_msg);
+ if(reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+
sbus_conn_send_reply(sconn, reply);
dbus_message_unref(reply);
talloc_free(infp_setattr_req);
return EOK;
+
+error:
+ talloc_free(infp_setattr_req);
+ return ret;
}
struct infp_setuid_ctx {
@@ -1170,7 +1344,12 @@ static void infp_do_user_set_uid_callback(void *ptr, int ldb_status, struct ldb_
/* Send reply ack */
reply = dbus_message_new_method_return(infp_setuid_req->infp_req->req_message);
+ if(reply == NULL) {
+ talloc_free(infp_setuid_req);
+ return;
+ }
sbus_conn_send_reply(infp_setuid_req->infp_req->sconn, reply);
+ dbus_message_unref(reply);
talloc_free(infp_setuid_req);
}
@@ -1270,6 +1449,10 @@ int infp_users_set_uid(DBusMessage *message, struct sbus_conn_ctx *sconn)
INFP_ATTR_TYPE_USERID))
{
reply = dbus_message_new_error(message, DBUS_ERROR_ACCESS_DENIED, NULL);
+ if(reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
/* send reply */
sbus_conn_send_reply(sconn, reply);
dbus_message_unref(reply);
@@ -1296,6 +1479,10 @@ int infp_users_set_uid(DBusMessage *message, struct sbus_conn_ctx *sconn)
einval:
reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, einval_msg);
+ if(reply == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
/* send reply */
sbus_conn_send_reply(sconn, reply);
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 130b8c666..94f92319b 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -788,7 +788,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_enumpwent(cmdctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy,
+ dctx->domain, dctx->legacy, NULL,
nss_cmd_setpwent_callback, cmdctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -885,7 +885,7 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
NULL, 0);
} else {
ret = sysdb_enumpwent(dctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy,
+ dctx->domain, dctx->legacy, NULL,
nss_cmd_setpwent_callback, cmdctx);
}
if (ret != EOK) {