>From ba95fbde773cbc2f486354f893263677b49f5f47 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Sun, 25 May 2014 17:17:57 +0200 Subject: [PATCH] TOOLS: Allow adding and modifying custom attributes with sss_usermod https://fedorahosted.org/sssd/ticket/2182 Adds three new options to the sss_usermod tool: --addattr --setattr --delattr The syntax is attrname=val1,val2, For example: sss_usermod --addattr=phone-123-456 tuser The operations are performed in the order of add, mod, del. --- src/man/sss_usermod.8.xml | 36 +++++++++++++++ src/tools/sss_sync_ops.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/tools/sss_sync_ops.h | 4 ++ src/tools/sss_usermod.c | 35 +++++++++++++++ 4 files changed, 187 insertions(+) diff --git a/src/man/sss_usermod.8.xml b/src/man/sss_usermod.8.xml index 55f8cd00d7626d3d26df39ac1ce19eed5f1d049e..b9fef823736f88db77b48630c5fc2cfc6ff6635c 100644 --- a/src/man/sss_usermod.8.xml +++ b/src/man/sss_usermod.8.xml @@ -130,6 +130,42 @@ + + + + ATTR_NAME_VAL + + + + Add an attribute/value pair. The format is + attrname=value. + + + + + + + ATTR_NAME_VAL + + + + Set an attribute to a name/value pair. The format + is attrname=value. For multi-valued attributes, + the command replaces the values already present + + + + + + + ATTR_NAME_VAL + + + + Delete an attribute/value pair. The format is attrname=value. + + + diff --git a/src/tools/sss_sync_ops.c b/src/tools/sss_sync_ops.c index 4c8f7102e6da4a7de819979096482853246e974f..232a711dd42e091842dc75386892c420191ebf95 100644 --- a/src/tools/sss_sync_ops.c +++ b/src/tools/sss_sync_ops.c @@ -35,6 +35,8 @@ #define DFL_SKEL_DIR "/etc/skel" #define DFL_MAIL_DIR "/var/spool/mail" +#define ATTR_NAME_SEP '=' +#define ATTR_VAL_SEP ',' #define VAR_CHECK(var, val, attr, msg) do { \ if (var != (val)) { \ @@ -43,6 +45,94 @@ } \ } while(0) +static int attr_name_val_split(TALLOC_CTX *mem_ctx, const char *nameval, + char **_name, char ***_values, int *_nvals) +{ + char *name; + char **values; + const char *vals; + int nvals; + TALLOC_CTX *tmp_ctx; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) return ENOMEM; + + vals = strchr(nameval, ATTR_NAME_SEP); + if (vals == NULL) { + ret = EINVAL; + goto done; + } + + name = talloc_strndup(tmp_ctx, nameval, vals-nameval); + if (name == NULL) { + ret = ENOMEM; + goto done; + } + vals++; + + ret = split_on_separator(tmp_ctx, vals, ATTR_VAL_SEP, true, true, + &values, &nvals); + if (ret != EOK) { + goto done; + } + + *_name = talloc_steal(mem_ctx, name); + *_values = talloc_steal(mem_ctx, values); + *_nvals = nvals; + ret = EOK; +done: + talloc_free(tmp_ctx); + return EOK; +} + +static int attr_op(struct ops_ctx *octx, const char *nameval, int op) +{ + TALLOC_CTX *tmp_ctx; + errno_t ret; + struct sysdb_attrs *attrs; + char *name; + char **vals; + int nvals; + int i; + + switch(op) { + case SYSDB_MOD_ADD: + case SYSDB_MOD_DEL: + case SYSDB_MOD_REP: + break; + default: + return EINVAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) return ENOMEM; + + attrs = sysdb_new_attrs(tmp_ctx); + if (attrs == NULL) { + ret = ENOMEM; + goto done; + } + + ret = attr_name_val_split(tmp_ctx, nameval, &name, &vals, &nvals); + if (ret != EOK) { + goto done; + } + + for (i=0; i < nvals; i++) { + ret = sysdb_attrs_add_string(attrs, name, vals[i]); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not add %s to %s\n", vals[i], name); + continue; + } + } + + ret = sysdb_set_user_attr(octx->domain, octx->name, attrs, op); +done: + talloc_free(tmp_ctx); + return EOK; +} /* * Generic modify groups member */ @@ -231,6 +321,28 @@ int usermod(TALLOC_CTX *mem_ctx, } } + if (data->addattr) { + ret = attr_op(data, data->addattr, SYSDB_MOD_ADD); + if (ret) { + return ret; + } + } + + if (data->setattr) { + ret = attr_op(data, data->setattr, SYSDB_MOD_REP); + if (ret) { + return ret; + } + + } + + if (data->delattr) { + ret = attr_op(data, data->delattr, SYSDB_MOD_DEL); + if (ret) { + return ret; + } + } + flush_nscd_cache(NSCD_DB_PASSWD); flush_nscd_cache(NSCD_DB_GROUP); diff --git a/src/tools/sss_sync_ops.h b/src/tools/sss_sync_ops.h index 6b50c5af54f0d824e597d627aa4de02d14e5600c..3aaf7a9f349c432b29e405e44bb4e05d7309e690 100644 --- a/src/tools/sss_sync_ops.h +++ b/src/tools/sss_sync_ops.h @@ -53,6 +53,10 @@ struct ops_ctx { char **addgroups; char **rmgroups; + + char *addattr; + char *setattr; + char *delattr; }; /* default values for add operations */ diff --git a/src/tools/sss_usermod.c b/src/tools/sss_usermod.c index 11369b7e63ee22f5288d2458934283f76768ded2..079c078e7b4cca7177f2d00ed3ec440a3013bba2 100644 --- a/src/tools/sss_usermod.c +++ b/src/tools/sss_usermod.c @@ -54,11 +54,15 @@ int main(int argc, const char **argv) { "remove-group", 'r', POPT_ARG_STRING, NULL, 'r', _("Groups to remove this user from"), NULL }, { "lock", 'L', POPT_ARG_NONE, NULL, 'L', _("Lock the account"), NULL }, { "unlock", 'U', POPT_ARG_NONE, NULL, 'U', _("Unlock the account"), NULL }, + { "addattr", '\0', POPT_ARG_STRING, NULL, 't' , _("Add an attribute/value pair. The format is attrname=value."), NULL }, + { "delattr", '\0', POPT_ARG_STRING, NULL, 'd' , _("Delete an attribute/value pair. The format is attrname=value."), NULL }, + { "setattr", '\0', POPT_ARG_STRING, NULL, 's' , _("Set an attribute to a name/value pair. The format is attrname=value. For multi-valued attributes, the command replaces the values already present"), NULL }, { "selinux-user", 'Z', POPT_ARG_STRING, &pc_selinux_user, 0, _("The SELinux user for user's login"), NULL }, POPT_TABLEEND }; poptContext pc = NULL; char *addgroups = NULL, *rmgroups = NULL; + char *addattr = NULL, *delattr = NULL, *setattr = NULL; int ret; errno_t sret; const char *pc_username = NULL; @@ -105,6 +109,34 @@ int main(int argc, const char **argv) case 'U': pc_lock = DO_UNLOCK; break; + + case 't': + addattr = poptGetOptArg(pc); + if (addattr == NULL) { + BAD_POPT_PARAMS(pc, + _("Specify the attribute name/value pair(s)\n"), + ret, fini); + } + break; + + case 'd': + delattr = poptGetOptArg(pc); + if (delattr == NULL) { + BAD_POPT_PARAMS(pc, + _("Specify the attribute name/value pair(s)\n"), + ret, fini); + } + break; + + case 's': + setattr = poptGetOptArg(pc); + if (setattr == NULL) { + BAD_POPT_PARAMS(pc, + _("Specify the attribute name/value pair(s)\n"), + ret, fini); + } + break; + } } @@ -221,6 +253,9 @@ int main(int argc, const char **argv) tctx->octx->uid = pc_uid; tctx->octx->gid = pc_gid; tctx->octx->lock = pc_lock; + tctx->octx->addattr = addattr; + tctx->octx->delattr = delattr; + tctx->octx->setattr = setattr; tctx->error = sysdb_transaction_start(tctx->sysdb); if (tctx->error != EOK) { -- 1.9.0