summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-10-11 22:43:41 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-11-24 17:44:57 +0100
commitdd87fc32c026b4fba9b13ab52f032e3b403b04bf (patch)
treeff547a6703eeda874b1ee13c0005dc04fbb65b46
parentf551ac4966543b360e3458a61615626d71f55a6e (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.c73
-rw-r--r--src/afm-udb.c31
-rw-r--r--src/afm-udb.h8
-rw-r--r--src/afm-urun.c108
-rw-r--r--src/afm-urun.h14
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);