diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2009-03-06 08:46:03 -0500 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2009-03-06 12:36:53 -0500 |
commit | 88f6f6db02c76f4f9d17cbd665b951cdccaaa39e (patch) | |
tree | 2b2b7e654bb40a4bdce989c6dd76a54ec6a548a9 | |
parent | baa296befe5908dde17d6e907c0071c2f65a4a88 (diff) | |
download | sssd-88f6f6db02c76f4f9d17cbd665b951cdccaaa39e.tar.gz sssd-88f6f6db02c76f4f9d17cbd665b951cdccaaa39e.tar.xz sssd-88f6f6db02c76f4f9d17cbd665b951cdccaaa39e.zip |
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.h | 2 | ||||
-rw-r--r-- | server/db/sysdb_req.c | 2 | ||||
-rw-r--r-- | server/infopipe/infopipe_users.c | 218 | ||||
-rw-r--r-- | server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml | 8 | ||||
-rw-r--r-- | server/monitor/monitor.c | 2 |
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; } |