diff options
author | José Bollo <jose.bollo@iot.bzh> | 2017-10-11 22:43:41 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2017-11-24 17:44:57 +0100 |
commit | dd87fc32c026b4fba9b13ab52f032e3b403b04bf (patch) | |
tree | ff547a6703eeda874b1ee13c0005dc04fbb65b46 | |
parent | f551ac4966543b360e3458a61615626d71f55a6e (diff) |
urun/udb: integration of user UID
Managing user applications at the system
levels requires to manage the user application
in a single process.
This process must manage the user identity
(UID).
Change-Id: I1ce8c9ca66ed0f916ecb2931ae014b08b113fa23
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | src/afm-binding.c | 73 | ||||
-rw-r--r-- | src/afm-udb.c | 31 | ||||
-rw-r--r-- | src/afm-udb.h | 8 | ||||
-rw-r--r-- | src/afm-urun.c | 108 | ||||
-rw-r--r-- | src/afm-urun.h | 14 |
5 files changed, 118 insertions, 116 deletions
diff --git a/src/afm-binding.c b/src/afm-binding.c index b111f09..19abc4e 100644 --- a/src/afm-binding.c +++ b/src/afm-binding.c @@ -143,7 +143,7 @@ static void runnables(struct afb_req req) { struct json_object *resp; INFO("method runnables called"); - resp = afm_udb_applications_public(afudb); + resp = afm_udb_applications_public(afudb, afb_req_get_uid(req)); afb_req_success(req, resp, NULL); } @@ -165,7 +165,7 @@ static void detail(struct afb_req req) /* wants details for appid */ INFO("method detail called for %s", appid); - resp = afm_udb_get_application_public(afudb, appid); + resp = afm_udb_get_application_public(afudb, appid, afb_req_get_uid(req)); if (resp) afb_req_success(req, resp, NULL); else @@ -191,14 +191,14 @@ static void start(struct afb_req req) /* get the application */ INFO("method start called for %s", appid); - appli = afm_udb_get_application_private(afudb, appid); + appli = afm_udb_get_application_private(afudb, appid, afb_req_get_uid(req)); if (appli == NULL) { not_found(req); return; } /* launch the application */ - runid = afm_urun_start(appli); + runid = afm_urun_start(appli, afb_req_get_uid(req)); if (runid <= 0) { cant_start(req); return; @@ -229,21 +229,21 @@ static void once(struct afb_req req) /* get the application */ INFO("method once called for %s", appid); - appli = afm_udb_get_application_private(afudb, appid); + appli = afm_udb_get_application_private(afudb, appid, afb_req_get_uid(req)); if (appli == NULL) { not_found(req); return; } /* launch the application */ - runid = afm_urun_once(appli); + runid = afm_urun_once(appli, afb_req_get_uid(req)); if (runid <= 0) { cant_start(req); return; } /* returns the state */ - resp = afm_urun_state(afudb, runid); + resp = afm_urun_state(afudb, runid, afb_req_get_uid(req)); afb_req_success(req, resp, NULL); } @@ -254,7 +254,7 @@ static void pause(struct afb_req req) { int runid, status; if (onrunid(req, "pause", &runid)) { - status = afm_urun_pause(runid); + status = afm_urun_pause(runid, afb_req_get_uid(req)); reply_status(req, status, _not_found_); } } @@ -266,7 +266,7 @@ static void resume(struct afb_req req) { int runid, status; if (onrunid(req, "resume", &runid)) { - status = afm_urun_resume(runid); + status = afm_urun_resume(runid, afb_req_get_uid(req)); reply_status(req, status, _not_found_); } } @@ -278,7 +278,7 @@ static void terminate(struct afb_req req) { int runid, status; if (onrunid(req, "terminate", &runid)) { - status = afm_urun_terminate(runid); + status = afm_urun_terminate(runid, afb_req_get_uid(req)); reply_status(req, status, _not_found_); } } @@ -290,7 +290,7 @@ static void runners(struct afb_req req) { struct json_object *resp; INFO("method runners called"); - resp = afm_urun_list(afudb); + resp = afm_urun_list(afudb, afb_req_get_uid(req)); afb_req_success(req, resp, NULL); } @@ -302,56 +302,11 @@ static void state(struct afb_req req) int runid; struct json_object *resp; if (onrunid(req, "state", &runid)) { - resp = afm_urun_state(afudb, runid); + resp = afm_urun_state(afudb, runid, afb_req_get_uid(req)); reply(req, resp, _not_found_); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void install(struct afb_req req) { const char *wgtfile; @@ -371,7 +326,7 @@ static void install(struct afb_req req) json = afb_req_json(req); if (wrap_json_unpack(json, "s", &wgtfile) || wrap_json_unpack(json, "{ss s?s s?b s?b}", - "widget", &wgtfile, + "wgt", &wgtfile, "root", &root, "force", &force, "reload", &reload)) { @@ -429,7 +384,7 @@ static void uninstall(struct afb_req req) static int init() { /* init database */ - afudb = afm_udb_create(1, 1, "afm-appli-"); + afudb = afm_udb_create(1, 0, "afm-appli-"); if (!afudb) { ERROR("afm_udb_create failed"); return -1; diff --git a/src/afm-udb.c b/src/afm-udb.c index 80cc715..24c188f 100644 --- a/src/afm-udb.c +++ b/src/afm-udb.c @@ -224,7 +224,6 @@ static int addunit( { struct json_object *priv, *pub, *id; const char *strid; - char *un = NULL; size_t len; /* create the application structure */ @@ -240,26 +239,13 @@ static int addunit( len = strlen(unitname); assert(len >= (sizeof service_extension - 1)); assert(!memcmp(&unitname[len - (sizeof service_extension - 1)], service_extension, sizeof service_extension)); - if (unitname[len - sizeof service_extension] == '@') { - char buffer[40]; - size_t l = (size_t)snprintf(buffer, sizeof buffer, "%d", (int)getuid()); - un = malloc(len + l + 1); - if (!un) - goto error; - memcpy(&un[0], unitname, len - (sizeof service_extension - 1)); - if (l) - memcpy(&un[len - (sizeof service_extension - 1)], buffer, l); - memcpy(&un[len - (sizeof service_extension - 1) + l], service_extension, sizeof service_extension); - } /* adds the values */ if (add_fields_of_content(priv, pub, content, length) || add_field(priv, pub, key_unit_path, unitpath) - || add_field(priv, pub, key_unit_name, un ? : unitname) + || add_field(priv, pub, key_unit_name, unitname) || add_field(priv, pub, key_unit_scope, isuser ? scope_user : scope_system)) goto error; - free(un); - un = NULL; /* get the id */ if (!json_object_object_get_ex(pub, key_id, &id)) { @@ -278,7 +264,6 @@ static int addunit( return 0; error: - free(un); json_object_put(pub); json_object_put(priv); return -1; @@ -486,7 +471,7 @@ error: * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_private(struct afm_udb *afudb) +struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int uid) { return json_object_get(afudb->applications.prvarr); } @@ -497,7 +482,7 @@ struct json_object *afm_udb_applications_private(struct afm_udb *afudb) * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_public(struct afm_udb *afudb) +struct json_object *afm_udb_applications_public(struct afm_udb *afudb, int uid) { return json_object_get(afudb->applications.pubarr); } @@ -507,7 +492,7 @@ struct json_object *afm_udb_applications_public(struct afm_udb *afudb) * It returns a JSON-object that must be released using 'json_object_put'. * Returns NULL in case of error. */ -static struct json_object *get_no_case(struct json_object *object, const char *id) +static struct json_object *get_no_case(struct json_object *object, const char *id, int uid) { struct json_object *result; struct json_object_iter i; @@ -529,9 +514,9 @@ static struct json_object *get_no_case(struct json_object *object, const char *i * It returns a JSON-object that must be released using 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id) +struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id, int uid) { - return get_no_case(afudb->applications.prvobj, id); + return get_no_case(afudb->applications.prvobj, id, uid); } /* @@ -540,9 +525,9 @@ struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const * Returns NULL in case of error. */ struct json_object *afm_udb_get_application_public(struct afm_udb *afudb, - const char *id) + const char *id, int uid) { - return get_no_case(afudb->applications.pubobj, id); + return get_no_case(afudb->applications.pubobj, id, uid); } diff --git a/src/afm-udb.h b/src/afm-udb.h index 672a311..dc30c9c 100644 --- a/src/afm-udb.h +++ b/src/afm-udb.h @@ -23,8 +23,8 @@ extern struct afm_udb *afm_udb_create(int sys, int usr, const char *prefix); extern void afm_udb_addref(struct afm_udb *afdb); extern void afm_udb_unref(struct afm_udb *afdb); extern int afm_udb_update(struct afm_udb *afdb); -extern struct json_object *afm_udb_applications_private(struct afm_udb *afdb); -extern struct json_object *afm_udb_applications_public(struct afm_udb *afdb); -extern struct json_object *afm_udb_get_application_private(struct afm_udb *afdb, const char *id); -extern struct json_object *afm_udb_get_application_public(struct afm_udb *afdb, const char *id); +extern struct json_object *afm_udb_applications_private(struct afm_udb *afdb, int uid); +extern struct json_object *afm_udb_applications_public(struct afm_udb *afdb, int uid); +extern struct json_object *afm_udb_get_application_private(struct afm_udb *afdb, const char *id, int uid); +extern struct json_object *afm_udb_get_application_public(struct afm_udb *afdb, const char *id, int uid); diff --git a/src/afm-urun.c b/src/afm-urun.c index 5649973..b6418ac 100644 --- a/src/afm-urun.c +++ b/src/afm-urun.c @@ -40,10 +40,13 @@ static const char key_unit_d_path[] = "-unit-dpath-"; /**************** get appli basis *********************/ -static int get_basis(struct json_object *appli, int *isuser, const char **dpath, int load) +static int get_basis(struct json_object *appli, int *isuser, const char **dpath, int load, int uid) { - char *dp; + char userid[40]; + char *dp, *arodot, *nun; const char *uname, *uscope; + struct json_object *odp; + int rc; /* get the scope */ if (!j_read_string_at(appli, "unit-scope", &uscope)) { @@ -52,21 +55,81 @@ static int get_basis(struct json_object *appli, int *isuser, const char **dpath, } *isuser = strcmp(uscope, "system") != 0; - /* get dpath */ - if (!j_read_string_at(appli, key_unit_d_path, dpath)) { - if (!load) { - errno = ENOENT; - goto error; + /* get dpaths of known users */ + odp = NULL; + if (json_object_object_get_ex(appli, key_unit_d_path, &odp)) { + /* try not parametric dpath */ + if (json_object_get_type(odp) == json_type_string) { + *dpath = json_object_get_string(odp); + return 0; } - if (!j_read_string_at(appli, "unit-name", &uname)) { - ERROR("'unit-name' missing in appli description %s", json_object_get_string(appli)); + assert(json_object_get_type(odp) == json_type_object); + /* get userid */ + if (uid < 0) { + ERROR("unexpected uid %d", uid); goto inval; } + rc = snprintf(userid, sizeof userid, "%d", uid); + assert(rc < (int)(sizeof userid)); + /* try dpath for the user */ + if (j_read_string_at(odp, userid, dpath)) + return 0; + } + + /* not here. load it? */ + if (!load) { + errno = ENOENT; + goto error; + } + + /* get uname */ + if (!j_read_string_at(appli, "unit-name", &uname)) { + ERROR("'unit-name' missing in appli description %s", json_object_get_string(appli)); + goto inval; + } + + /* is user parametric? */ + arodot = strchr(uname, '@'); + if (arodot && *++arodot == '.') { + if (!odp) { + /* get userid */ + if (uid < 0) { + ERROR("unexpected uid %d", uid); + goto inval; + } + rc = snprintf(userid, sizeof userid, "%d", uid); + assert(rc < (int)(sizeof userid)); + + /* create the dpaths of known users */ + odp = json_object_new_object(); + if (!odp) + goto nomem; + json_object_object_add(appli, key_unit_d_path, odp); + } + + /* get dpath of userid */ + nun = alloca((size_t)(arodot - uname) + strlen(userid) + strlen(arodot) + 1); + stpcpy(stpcpy(stpncpy(nun, uname, (size_t)(arodot - uname)), userid), arodot); + dp = systemd_unit_dpath_by_name(*isuser, uname, 1); + if (dp == NULL) { + ERROR("Can't load unit of name %s for %s: %m", uname, uscope); + goto error; + } + /* record the dpath */ + if (!j_add_string(odp, userid, dp)) { + free(dp); + goto nomem; + } + free(dp); + j_read_string_at(odp, userid, dpath); + } else { + /* get dpath */ dp = systemd_unit_dpath_by_name(*isuser, uname, 1); if (dp == NULL) { ERROR("Can't load unit of name %s for %s: %m", uname, uscope); goto error; } + /* record the dpath */ if (!j_add_string(appli, key_unit_d_path, dp)) { free(dp); goto nomem; @@ -74,7 +137,6 @@ static int get_basis(struct json_object *appli, int *isuser, const char **dpath, free(dp); j_read_string_at(appli, key_unit_d_path, dpath); } - return 0; nomem: @@ -162,9 +224,9 @@ error: * * Returns the runid in case of success or -1 in case of error */ -int afm_urun_start(struct json_object *appli) +int afm_urun_start(struct json_object *appli, int uid) { - return afm_urun_once(appli); + return afm_urun_once(appli, uid); } /* @@ -178,13 +240,13 @@ int afm_urun_start(struct json_object *appli) * * Returns the runid in case of success or -1 in case of error */ -int afm_urun_once(struct json_object *appli) +int afm_urun_once(struct json_object *appli, int uid) { const char *udpath, *state, *uscope, *uname; int rc, isuser; /* retrieve basis */ - rc = get_basis(appli, &isuser, &udpath, 1); + rc = get_basis(appli, &isuser, &udpath, 1, uid); if (rc < 0) goto error; @@ -237,7 +299,7 @@ static int not_yet_implemented(const char *what) * * Returns 0 in case of success or -1 in case of error */ -int afm_urun_terminate(int runid) +int afm_urun_terminate(int runid, int uid) { int rc = systemd_unit_stop_pid(1 /* TODO: isuser? */, (unsigned)runid); if (rc < 0) @@ -250,7 +312,7 @@ int afm_urun_terminate(int runid) * * Returns 0 in case of success or -1 in case of error */ -int afm_urun_pause(int runid) +int afm_urun_pause(int runid, int uid) { return not_yet_implemented("pause"); } @@ -260,7 +322,7 @@ int afm_urun_pause(int runid) * * Returns 0 in case of success or -1 in case of error */ -int afm_urun_resume(int runid) +int afm_urun_resume(int runid, int uid) { return not_yet_implemented("resume"); } @@ -270,7 +332,7 @@ int afm_urun_resume(int runid) * * Returns the list or NULL in case of error. */ -struct json_object *afm_urun_list(struct afm_udb *db) +struct json_object *afm_urun_list(struct afm_udb *db, int uid) { int i, n, isuser, pid; const char *udpath; @@ -286,11 +348,11 @@ struct json_object *afm_urun_list(struct afm_udb *db) if (result == NULL) goto error; - apps = afm_udb_applications_private(db); + apps = afm_udb_applications_private(db, uid); n = json_object_array_length(apps); for (i = 0 ; i < n ; i++) { appli = json_object_array_get_idx(apps, i); - if (appli && get_basis(appli, &isuser, &udpath, 0) >= 0) { + if (appli && get_basis(appli, &isuser, &udpath, 0, uid) >= 0) { pid = systemd_unit_pid_of_dpath(isuser, udpath); if (pid > 0 && j_read_string_at(appli, "id", &id)) { state = systemd_unit_state_of_dpath(isuser, udpath); @@ -315,7 +377,7 @@ error: * * Returns the state or NULL in case of success */ -struct json_object *afm_urun_state(struct afm_udb *db, int runid) +struct json_object *afm_urun_state(struct afm_udb *db, int runid, int uid) { int i, n, isuser, pid, wasuser; char *dpath; @@ -337,12 +399,12 @@ struct json_object *afm_urun_state(struct afm_udb *db, int runid) WARNING("searched runid %d not found", runid); } else { /* search in the base */ - apps = afm_udb_applications_private(db); + apps = afm_udb_applications_private(db, uid); n = json_object_array_length(apps); for (i = 0 ; i < n ; i++) { appli = json_object_array_get_idx(apps, i); if (appli - && get_basis(appli, &isuser, &udpath, 0) >= 0 + && get_basis(appli, &isuser, &udpath, 0, uid) >= 0 && !strcmp(dpath, udpath) && j_read_string_at(appli, "id", &id)) { pid = systemd_unit_pid_of_dpath(isuser, udpath); diff --git a/src/afm-urun.h b/src/afm-urun.h index 7f85e0f..178edf9 100644 --- a/src/afm-urun.h +++ b/src/afm-urun.h @@ -18,11 +18,11 @@ struct afm_udb; -extern int afm_urun_start(struct json_object *appli); -extern int afm_urun_once(struct json_object *appli); -extern int afm_urun_terminate(int runid); -extern int afm_urun_pause(int runid); -extern int afm_urun_resume(int runid); -extern struct json_object *afm_urun_list(struct afm_udb *db); -extern struct json_object *afm_urun_state(struct afm_udb *db, int runid); +extern int afm_urun_start(struct json_object *appli, int uid); +extern int afm_urun_once(struct json_object *appli, int uid); +extern int afm_urun_terminate(int runid, int uid); +extern int afm_urun_pause(int runid, int uid); +extern int afm_urun_resume(int runid, int uid); +extern struct json_object *afm_urun_list(struct afm_udb *db, int uid); +extern struct json_object *afm_urun_state(struct afm_udb *db, int runid, int uid); |