summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2009-03-06 08:46:03 -0500
committerSimo Sorce <ssorce@redhat.com>2009-03-06 12:36:53 -0500
commit88f6f6db02c76f4f9d17cbd665b951cdccaaa39e (patch)
tree2b2b7e654bb40a4bdce989c6dd76a54ec6a548a9
parentbaa296befe5908dde17d6e907c0071c2f65a4a88 (diff)
Implement CreateUser in InfoPipe
Changed the order of the arguments to CreateUser in the Introspection XML to match the other functions (domain belongs second on the list) A few other minor fixes as well: Fixed a typo in SYSDB_GETCACHED_FILTER and sysdb_transaction_end(). Added missing error handling in infp_do_user_set_uid().
-rw-r--r--server/db/sysdb.h2
-rw-r--r--server/db/sysdb_req.c2
-rw-r--r--server/infopipe/infopipe_users.c218
-rw-r--r--server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml8
-rw-r--r--server/monitor/monitor.c2
5 files changed, 223 insertions, 9 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index c87b0b4ee..f59b56c1d 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -81,7 +81,7 @@
#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_GETCACHED_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_USER_ATTR_LAST_LOGIN">=%lu))"
#define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
SYSDB_GIDNUM, SYSDB_FULLNAME, \
diff --git a/server/db/sysdb_req.c b/server/db/sysdb_req.c
index 161431cc9..15d8aa851 100644
--- a/server/db/sysdb_req.c
+++ b/server/db/sysdb_req.c
@@ -174,7 +174,7 @@ static void sysdb_transaction_end(struct sysdb_req *req)
DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
}
} else {
- DEBUG(4, ("Canceling transaction (%d[%s)\n",
+ DEBUG(4, ("Canceling transaction (%d[%s])\n",
req->status, strerror(req->status)));
ret = ldb_transaction_cancel(req->ctx->ldb);
if (ret != LDB_SUCCESS) {
diff --git a/server/infopipe/infopipe_users.c b/server/infopipe/infopipe_users.c
index a1b22e3b9..d6c00e5c7 100644
--- a/server/infopipe/infopipe_users.c
+++ b/server/infopipe/infopipe_users.c
@@ -201,17 +201,227 @@ error:
return ret;
}
+struct infp_createuser_ctx {
+ struct infp_req_ctx *infp_req;
+ struct sysdb_req *sysdb_req;
+
+ char *username;
+ char *fullname;
+ char *homedir;
+ char *shell;
+};
+
+static void infp_do_user_create_callback(void *pvt,
+ int status,
+ struct ldb_result *res)
+{
+ char *error_msg = NULL;
+ DBusMessage *reply = NULL;
+ struct infp_createuser_ctx *infp_createuser_req = talloc_get_type(pvt, struct infp_createuser_ctx);
+
+ /* Commit the transaction if it we got a successful response, or cancel it if we did not */
+ sysdb_transaction_done(infp_createuser_req->sysdb_req, status);
+
+ /* Verify that the addition completed successfully
+ * If LDB returned an error, run a search to determine
+ * if it was due the requested username already being
+ * in use
+ */
+ if (status == EOK) {
+ /* Return reply ack */
+ reply = dbus_message_new_method_return(infp_createuser_req->infp_req->req_message);
+ }
+ else if (status == EEXIST) {
+ /* Return error, user already exists */
+ error_msg = talloc_asprintf(infp_createuser_req,
+ "User [%s] already exists on domain [%s]",
+ infp_createuser_req->username,
+ infp_createuser_req->infp_req->domain->name);
+ reply = dbus_message_new_error(infp_createuser_req->infp_req->req_message,
+ DBUS_ERROR_FILE_EXISTS,
+ error_msg);
+ }
+ else {
+ /* Unknown error occurred. Print DEBUG message */
+ DEBUG(0, ("Failed to create user in the sysdb. Error code %d\n", status));
+ talloc_free(infp_createuser_req);
+ return;
+ }
+
+ if (reply) {
+ sbus_conn_send_reply(infp_createuser_req->infp_req->sconn, reply);
+ dbus_message_unref(reply);
+ }
+ talloc_free(infp_createuser_req);
+}
+
+static void infp_do_user_create(struct sysdb_req *req, void *pvt)
+{
+ int ret;
+ struct infp_createuser_ctx *infp_createuser_req = talloc_get_type(pvt, struct infp_createuser_ctx);
+ infp_createuser_req->sysdb_req = req;
+
+ ret = sysdb_add_user(infp_createuser_req->sysdb_req,
+ infp_createuser_req->infp_req->domain,
+ infp_createuser_req->username,
+ 0, 0,
+ infp_createuser_req->fullname,
+ infp_createuser_req->homedir,
+ infp_createuser_req->shell,
+ infp_do_user_create_callback,
+ infp_createuser_req);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not invoke sysdb_add_user"));
+ sysdb_transaction_done(infp_createuser_req->sysdb_req, ret);
+ talloc_free(infp_createuser_req);
+ return;
+ }
+}
+
int infp_users_create(DBusMessage *message, struct sbus_conn_ctx *sconn)
{
DBusMessage *reply;
+ DBusError error;
+ dbus_bool_t dbret;
+ char *einval_msg;
+ struct infp_createuser_ctx *infp_createuser_req;
+ int ret;
- reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ /* Arguments */
+ const char *arg_domain;
+ const char *arg_username;
+ const char *arg_fullname;
+ const char *arg_homedir;
+ const char *arg_shell;
+
+ infp_createuser_req = talloc_zero(NULL, struct infp_createuser_ctx);
+ if (infp_createuser_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ /* Create an infp_req_ctx */
+ infp_createuser_req->infp_req = talloc_zero(infp_createuser_req, struct infp_req_ctx);
+ if (infp_createuser_req == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ infp_createuser_req->infp_req->infp = talloc_get_type(sbus_conn_get_private_data(sconn), struct infp_ctx);
+ infp_createuser_req->infp_req->sconn = sconn;
+ infp_createuser_req->infp_req->req_message = message;
+ infp_createuser_req->infp_req->caller = sysbus_get_caller(infp_createuser_req->infp_req,
+ infp_createuser_req->infp_req->req_message,
+ infp_createuser_req->infp_req->sconn);
+ if (infp_createuser_req->infp_req->caller == NULL) {
+ ret = EIO;
+ goto error;
+ }
+
+ dbus_error_init(&error);
+ dbret = dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &arg_username,
+ DBUS_TYPE_STRING, &arg_domain,
+ DBUS_TYPE_STRING, &arg_fullname,
+ DBUS_TYPE_STRING, &arg_homedir,
+ DBUS_TYPE_STRING, &arg_shell,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(0, ("Parsing arguments to %s failed: %s:%s\n", INFP_USERS_CREATE, error.name, error.message));
+ einval_msg = talloc_strdup(infp_createuser_req, error.message);
+ dbus_error_free(&error);
+ goto einval;
+ }
+ /* FIXME: Allow creating users on domains other than LOCAL */
+ if (strcasecmp(arg_domain, "LOCAL") != 0) {
+ goto denied;
+ }
+
+ infp_createuser_req->infp_req->domain = btreemap_get_value(infp_createuser_req->infp_req->infp->domain_map,
+ (const void *)arg_domain);
+ /* Check for a valid domain */
+ if(infp_createuser_req->infp_req->domain == NULL) {
+ einval_msg = talloc_strdup(infp_createuser_req, "Invalid domain.");
+ goto einval;
+ }
+
+ if (strlen(arg_username)) {
+ infp_createuser_req->username = talloc_strdup(infp_createuser_req, arg_username);
+ if (infp_createuser_req->username == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ } else {
+ einval_msg = talloc_strdup(infp_createuser_req, "No username provided");
+ goto einval;
+ }
+
+ infp_createuser_req->fullname = NULL;
+ if (strlen(arg_fullname)) {
+ infp_createuser_req->fullname = talloc_strdup(infp_createuser_req, arg_username);
+ if(infp_createuser_req->fullname == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ }
+
+ infp_createuser_req->homedir = NULL;
+ if (strlen(arg_homedir)) {
+ infp_createuser_req->homedir = talloc_strdup(infp_createuser_req, arg_username);
+ if(infp_createuser_req->homedir == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ }
+
+ /* Check permissions */
+ if(!infp_get_permissions(infp_createuser_req->infp_req->caller,
+ infp_createuser_req->infp_req->domain,
+ INFP_OBJ_TYPE_USER,
+ NULL,
+ INFP_ACTION_TYPE_CREATE,
+ INFP_ACTION_TYPE_INVALID)) goto denied;
+
+ ret = sysdb_transaction(infp_createuser_req,
+ infp_createuser_req->infp_req->infp->sysdb,
+ infp_do_user_create,
+ infp_createuser_req);
+ if (ret != EOK) {
+ DEBUG(0,("Unable to start transaction to create user\n"));
+ goto error;
+ }
+
+ return EOK;
+
+denied:
+ 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);
+
+ talloc_free(infp_createuser_req);
+ 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_createuser_req);
return EOK;
+
+error:
+ talloc_free(infp_createuser_req);
+ return ret;
}
int infp_users_delete(DBusMessage *message, struct sbus_conn_ctx *sconn)
@@ -1368,6 +1578,12 @@ static void infp_do_user_set_uid(struct sysdb_req *req, void *pvt)
infp_setuid_req->username,
infp_setuid_req->uid_attr,
infp_do_user_set_uid_callback, infp_setuid_req);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not invoke sysdb_set_user_attr"));
+ sysdb_transaction_done(infp_setuid_req->sysdb_req, ret);
+ talloc_free(infp_setuid_req);
+ return;
+ }
}
int infp_users_set_uid(DBusMessage *message, struct sbus_conn_ctx *sconn)
diff --git a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
index 164c9d10a..0dcd2a0d5 100644
--- a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
+++ b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
@@ -46,7 +46,7 @@
CheckPermissions(domain=>'LOCAL', object=>'user', instance=>'testuser1', actions=>[('modify','userpic'),('modify','fullname')])
returns permissions=>[1,0]
Can I add members to group wheel?
- CheckPermissions(domain=>'LOCAL', object=>'user', instance=>'wheel', actions=>[('addmember','somearg')])
+ CheckPermissions(domain=>'LOCAL', object=>'group', instance=>'wheel', actions=>[('addmember','somearg')])
returns permissions=>[1]
The argument 'somearg' is ignored, since it does not apply to addmember."
/>
@@ -79,9 +79,8 @@
<annotation
name="org.freeipa.sssd.infopipe.DocString"
value="Create a new user in a particular domain. User will initially have a disabled password.
- @param domain The domain in which to add the user
@param username Username for the new user. Must be unique within a domain.
- @param defaultgroup Default group name for the user.
+ @param domain The domain in which to add the user
@param fullname Full (display) name for the user. Will set both 'fullname' and 'gecos' to this value initially.
@param homedir Home directory path for the user. Must be a parsable path, but does not need to exist or be mounted.
@param shell Login shell. Must exist in /etc/shells.
@@ -91,9 +90,8 @@
@note CreateUser will ignore users that already exist.
@note This function will automatically generate an appropriate UID for the user."
/>
- <arg name="domain" type="s" direction="in" />
<arg name="username" type="s" direction="in" />
- <arg name="defaultgroup" type="s" direction="in" />
+ <arg name="domain" type="s" direction="in" />
<arg name="fullname" type="s" direction="in" />
<arg name="homedir" type="s" direction="in" />
<arg name="shell" type="s" direction="in" />
diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c
index fb5b9b910..3c393c97d 100644
--- a/server/monitor/monitor.c
+++ b/server/monitor/monitor.c
@@ -650,7 +650,7 @@ static void identity_check(DBusPendingCall *pending, void *data)
svc = svc->next;
}
if (!svc) {
- DEBUG(0,("Unable to find peer in list of services, killing connection!\n"));
+ DEBUG(0,("Unable to find peer [%s] in list of services, killing connection!\n", svc_name));
sbus_disconnect(conn_ctx);
goto done;
}