Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add user/group manipulation functions
Baptiste Daroussin committed 14 years ago
commit 59f30365721ccc428e6b79e0086d8e88eb946055
parent edfbd67
10 files changed +349 -26
modified libpkg/Makefile
@@ -6,6 +6,7 @@ WARNS= 6
SHLIBDIR?=	/usr/lib
SHLIB_MAJOR=	0

+
#gr_utils.c has to be deleted as soon as it goes in base
SRCS=		pkg.c \
		pkg_add.c \
		pkg_attributes.c \
@@ -25,7 +26,9 @@ SRCS= pkg.c \
		fetch.c \
		packing.c \
		scripts.c \
-
		rcscripts.c
+
		rcscripts.c \
+
		usergroup.c \
+
		gr_util.c

CFLAGS+=	-std=c99
CFLAGS+=	-I${.CURDIR} \
modified libpkg/pkg.c
@@ -437,7 +437,7 @@ pkg_addlicense(struct pkg *pkg, const char *name)
}

int
-
pkg_adduser(struct pkg *pkg, const char *name)
+
pkg_adduid(struct pkg *pkg, const char *name, const char *uidstr)
{
	struct pkg_user *u = NULL;

@@ -455,11 +455,24 @@ pkg_adduser(struct pkg *pkg, const char *name)

	strlcpy(u->name, name, sizeof(u->name));

+
	if (uidstr != NULL)
+
		strlcpy(u->uidstr, uidstr, sizeof(u->uidstr));
+
	else
+
		u->uidstr[0] = '\0';
+

+
	STAILQ_INSERT_TAIL(&pkg->users, u, next);
+

	return (EPKG_OK);
}

int
-
pkg_addgroup(struct pkg *pkg, const char *name)
+
pkg_adduser(struct pkg *pkg, const char *name)
+
{
+
	return (pkg_adduid(pkg, name, NULL));
+
}
+

+
int
+
pkg_addgid(struct pkg *pkg, const char *name, const char *gidstr)
{
	struct pkg_group *g = NULL;

@@ -476,11 +489,23 @@ pkg_addgroup(struct pkg *pkg, const char *name)
	pkg_group_new(&g);

	strlcpy(g->name, name, sizeof(g->name));
+
	if (gidstr != NULL)
+
		strlcpy(g->gidstr, gidstr, sizeof(g->gidstr));
+
	else
+
		g->gidstr[0] = '\0';
+

+
	STAILQ_INSERT_TAIL(&pkg->groups, g, next);

	return (EPKG_OK);
}

int
+
pkg_addgroup(struct pkg *pkg, const char *name)
+
{
+
	return (pkg_addgid(pkg, name, NULL));
+
}
+

+
int
pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version)
{
	struct pkg_dep *d = NULL;
modified libpkg/pkg.h
@@ -444,6 +444,18 @@ int pkg_adduser(struct pkg *pkg, const char *name);
int pkg_addgroup(struct pkg *pkg, const char *group);

/**
+
 * Add a user
+
 * @return An error code.
+
 */
+
int pkg_adduid(struct pkg *pkg, const char *name, const char *uidstr);
+

+
/**
+
 * Add a gid
+
 * @return an error code
+
 */
+
int pkg_addgid(struct pkg *pkg, const char *group, const char *gidstr);
+

+
/**
 * Allocate a new struct pkg_conflict and add it to the conflicts of pkg.
 * @return An error code.
 */
@@ -502,7 +514,9 @@ const char *pkg_category_name(struct pkg_category *);
const char *pkg_license_name(struct pkg_license *);

const char *pkg_user_name(struct pkg_user *);
+
const char *pkg_user_uidstr(struct pkg_user *);
const char *pkg_group_name(struct pkg_group *);
+
const char *pkg_group_gidstr(struct pkg_group *);

/* pkg_conflict */
const char * pkg_conflict_glob(struct pkg_conflict *);
@@ -845,4 +859,7 @@ int pkg_start_rc_scripts(struct pkg *);
int pkg_init(const char *);
int pkg_shutdown(void);

+
int pkg_add_user_group(struct pkg *pkg);
+
int pkg_delete_user_group(struct pkgdb *db, struct pkg *pkg);
+

#endif
modified libpkg/pkg_add.c
@@ -190,6 +190,7 @@ pkg_add(struct pkgdb *db, const char *path, int flags)
		retcode = pkgdb_register_pkg(db, pkg, 0);
	else
		retcode = pkgdb_register_pkg(db, pkg, 1);
+

	if (retcode != EPKG_OK || pkgdb_has_flag(db, PKGDB_FLAG_IN_FLIGHT) == 0)
		goto cleanup_reg;

@@ -199,6 +200,9 @@ pkg_add(struct pkgdb *db, const char *path, int flags)
	if ((flags & PKG_ADD_UPGRADE_NEW) == 0)
		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL);

+
	/* add the user and group if necessary */
+
	pkg_add_user_group(pkg);
+

	/*
	 * Extract the files on disk.
	 */
modified libpkg/pkg_attributes.c
@@ -229,6 +229,12 @@ pkg_user_name(struct pkg_user *u)
	return (u->name);
}

+
const char *
+
pkg_user_uidstr(struct pkg_user *u)
+
{
+
	return (u->uidstr);
+
}
+

/*
 * group
 */
@@ -259,6 +265,12 @@ pkg_group_name(struct pkg_group *g)
	return (g->name);
}

+
const char *
+
pkg_group_gidstr(struct pkg_group *g)
+
{
+
	return (g->gidstr);
+
}
+


/*
 * Script
modified libpkg/pkg_manifest.c
@@ -69,7 +69,8 @@ static struct manifest_key {
	{ "message", PKG_MESSAGE, YAML_SCALAR_NODE, pkg_set_from_node},
	{ "categories", PKG_CATEGORIES, YAML_SEQUENCE_NODE, parse_sequence},
	{ "options", PKG_OPTIONS, YAML_MAPPING_NODE, parse_mapping},
-
	{ "users", PKG_USERS, YAML_SEQUENCE_NODE, parse_sequence},
+
	{ "users", PKG_USERS, YAML_SEQUENCE_NODE, parse_sequence}, /* compatibility with old format */
+
	{ "users", PKG_USERS, YAML_MAPPING_NODE, parse_mapping},
	{ "groups", PKG_GROUPS, YAML_SEQUENCE_NODE, parse_sequence},
	{ NULL, -99, -99, NULL}
};
@@ -228,16 +229,20 @@ parse_sequence(struct pkg * pkg, yaml_node_t *node, yaml_document_t *doc, int at
					pkg_addlicense(pkg, val->data.scalar.value);
				break;
			case PKG_USERS:
-
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
-
					pkg_emit_error("Skipping malformed license");
-
				else
+
				if (val->type == YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_adduser(pkg, val->data.scalar.value);
+
				else if (val->type == YAML_MAPPING_NODE)
+
					parse_mapping(pkg, val, doc, attr);
+
				else
+
					pkg_emit_error("Skipping malformed license");
				break;
			case PKG_GROUPS:
-
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
-
					pkg_emit_error("Skipping malformed license");
-
				else
+
				if (val->type == YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_addgroup(pkg, val->data.scalar.value);
+
				else if (val->type == YAML_MAPPING_NODE)
+
					parse_mapping(pkg, val, doc, attr);
+
				else
+
					pkg_emit_error("Skipping malformed license");
				break;
			case PKG_DIRS:
				if (val->type == YAML_SCALAR_NODE && val->data.scalar.length > 0)
@@ -262,6 +267,7 @@ parse_mapping(struct pkg *pkg, yaml_node_t *item, yaml_document_t *doc, int attr
	pkg_script_t script_type;

	pair = item->data.mapping.pairs.start;
+

	while (pair < item->data.mapping.pairs.top) {
		key = yaml_document_get_node(doc, pair->key);
		val = yaml_document_get_node(doc, pair->value);
@@ -287,6 +293,20 @@ parse_mapping(struct pkg *pkg, yaml_node_t *item, yaml_document_t *doc, int attr
				else
					pkg_set_dirs_from_node(pkg, val, doc, key->data.scalar.value);
				break;
+
			case PKG_USERS:
+
				if (val->type == YAML_SCALAR_NODE && val->data.scalar.length > 0)
+
					pkg_adduid(pkg, key->data.scalar.value, val->data.scalar.value);
+
				else
+
					pkg_emit_error("Skipping malformed users %s",
+
							key->data.scalar.value);
+
				break;
+
			case PKG_GROUPS:
+
				if (val->type == YAML_SCALAR_NODE && val->data.scalar.length > 0)
+
					pkg_addgid(pkg, key->data.scalar.value, val->data.scalar.value);
+
				else
+
					pkg_emit_error("Skipping malformed groups %s",
+
							key->data.scalar.value);
+
				break;
			case PKG_DIRECTORIES:
				if (val->type == YAML_SCALAR_NODE && val->data.scalar.length > 0) {
					urldecode(key->data.scalar.value, &tmp);
@@ -535,12 +555,8 @@ parse_root_node(struct pkg *pkg, yaml_node_t *node, yaml_document_t *doc) {
			if (!strcasecmp(key->data.scalar.value, manifest_key[i].key)) {
				if (val->type == manifest_key[i].valid_type) {
					retcode = manifest_key[i].parse_data(pkg, val, doc, manifest_key[i].type);
-
				} else {
-
					pkg_emit_error("Unsupported format for key: %s",
-
								   key->data.scalar.value);
-
					retcode = EPKG_FATAL;
+
					break;
				}
-
				break;
			}

			if (manifest_key[i].key == NULL)
@@ -630,6 +646,8 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	int depkv;
	int files = -1;
	int dirs = -1;
+
	int users = -1;
+
	int groups = -1;
	int options = -1;
	int scripts = -1;
	const char *script_types = NULL;
@@ -701,13 +719,25 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	while (pkg_categories(pkg, &category) == EPKG_OK)
		manifest_append_seqval(&doc, mapping, &seq, "categories", pkg_category_name(category));

-
	seq = -1;
-
	while (pkg_users(pkg, &user) == EPKG_OK)
-
		manifest_append_seqval(&doc, mapping, &seq, "users", pkg_user_name(user));
+
	while (pkg_users(pkg, &user) == EPKG_OK) {
+
		if (users == -1) {
+
			users = yaml_document_add_mapping(&doc, NULL, YAML_BLOCK_MAPPING_STYLE);
+
			yaml_document_append_mapping_pair(&doc, mapping,
+
					yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t*, "users"), 5, YAML_PLAIN_SCALAR_STYLE),
+
					users);
+
		}
+
		manifest_append_kv(users, pkg_user_name(user), user->uidstr);
+
	}

-
	seq = -1;
-
	while (pkg_groups(pkg, &group) == EPKG_OK)
-
		manifest_append_seqval(&doc, mapping, &seq, "groups", pkg_group_name(group));
+
	while (pkg_groups(pkg, &group) == EPKG_OK) {
+
		if (groups == -1) {
+
			groups = yaml_document_add_mapping(&doc, NULL, YAML_BLOCK_MAPPING_STYLE);
+
			yaml_document_append_mapping_pair(&doc, mapping,
+
					yaml_document_add_scalar(&doc, NULL, __DECONST(yaml_char_t*, "groups"), 6, YAML_PLAIN_SCALAR_STYLE),
+
					groups);
+
		}
+
		manifest_append_kv(groups, pkg_group_name(group), group->gidstr);
+
	}

	seq = -1;
	while (pkg_conflicts(pkg, &conflict) == EPKG_OK)
modified libpkg/pkg_private.h
@@ -120,11 +120,13 @@ struct pkg_remote_repo {

struct pkg_user {
	char name[MAXLOGNAME+1];
+
	char uidstr[8192]; /* taken from pw_util.c */
	STAILQ_ENTRY(pkg_user) next;
};

struct pkg_group {
	char name[MAXLOGNAME+1];
+
	char gidstr[8192]; /* taken from gw_util.c */
	STAILQ_ENTRY(pkg_group) next;
};

modified libpkg/pkgdb.c
@@ -5,6 +5,9 @@
#include <assert.h>
#include <errno.h>
#include <regex.h>
+
#include <grp.h>
+
#include <pwd.h>
+
#include <libutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
@@ -1006,31 +1009,58 @@ pkgdb_load_category(struct pkgdb *db, struct pkg *pkg)
int
pkgdb_load_user(struct pkgdb *db, struct pkg *pkg)
{
+
	struct pkg_user *u = NULL;
+
	struct passwd *pwd = NULL;
+
	int ret;
+

	const char sql[] = ""
		"SELECT users.name "
		"FROM pkg_users, users "
-
		"WHERE package_id ?1 "
+
		"WHERE package_id = ?1 "
		"AND user_id = users.id "
		"ORDER by name DESC";

	assert(db != NULL && pkg != NULL);

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_USERS, pkg_adduser, PKG_USERS));
+
	ret = load_val(db->sqlite, pkg, sql, PKG_LOAD_USERS, pkg_adduser, PKG_USERS);
+

+
	/* get user uidstr from local database */
+
	while (pkg_users(pkg, &u) == EPKG_OK) {
+
		pwd = getpwnam(pkg_user_name(u));
+
		if (pwd == NULL)
+
			continue;
+
		strlcpy(u->uidstr, pw_make(pwd), sizeof(u->uidstr));
+
	}
+

+
	return (ret);
}

int
pkgdb_load_group(struct pkgdb *db, struct pkg *pkg)
{
+
	struct pkg_group *g = NULL;
+
	struct group * grp = NULL;
+
	int ret;
+

	const char sql[] = ""
		"SELECT groups.name "
		"FROM pkg_groups, groups "
-
		"WHERE package_id ?1 "
+
		"WHERE package_id = ?1 "
		"AND group_id = groups.id "
		"ORDER by name DESC";

	assert(db != NULL && pkg != NULL);

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_GROUPS, pkg_addgroup, PKG_GROUPS));
+
	ret = load_val(db->sqlite, pkg, sql, PKG_LOAD_GROUPS, pkg_addgroup, PKG_GROUPS);
+

+
	while (pkg_groups(pkg, &g) == EPKG_OK) {
+
		grp = getgrnam(pkg_group_name(g));
+
		if (grp == NULL)
+
			continue;
+
		strlcpy(g->gidstr, gr_make(grp), sizeof(g->gidstr));
+
	}
+

+
	return (ret);
}

int
@@ -1700,9 +1730,11 @@ pkgdb_unregister_pkg(struct pkgdb *db, const char *origin)
	if (sql_exec(db->sqlite, "DELETE FROM mtree WHERE id NOT IN (SELECT DISTINCT mtree_id FROM packages);") != EPKG_OK)
		return (EPKG_FATAL);

+
	/* TODO print the users that are not used anymore */
	if (sql_exec(db->sqlite, "DELETE FROM users WHERE id NOT IN (SELECT DISTINCT user_id FROM pkg_users);") != EPKG_OK)
		return (EPKG_FATAL);

+
	/* TODO print the groups trhat are not used anymore */
	if (sql_exec(db->sqlite, "DELETE FROM groups WHERE id NOT IN (SELECT DISTINCT group_id FROM pkg_groups);") != EPKG_OK)
		return (EPKG_FATAL);

added libpkg/usergroup.c
@@ -0,0 +1,198 @@
+
#include <grp.h>
+
#include <pwd.h>
+
#include <libutil.h>
+
#include <string.h>
+

+
#include "gr_util.h" /* has to be dropped when gr_* will be in base */
+
#include "pkg.h"
+
#include "pkg_event.h"
+
#include "pkg_private.h"
+

+
int
+
pkg_add_user_group(struct pkg *pkg)
+
{
+
	struct pkg_group *g = NULL;
+
	struct pkg_user *u = NULL;
+
	struct group *gr = NULL;
+
	struct passwd *pw = NULL;
+
	int tfd, pfd;
+

+
	/* loop just to check group and users contains string */
+
	while (pkg_groups(pkg, &g) == EPKG_OK) {
+
		if (g->gidstr[0] == '\0') {
+
			/*
+
			 * old style group ignorring, this is created from
+
			 * scripts
+
			 */
+
			return (EPKG_OK);
+
		}
+
	}
+

+
	/* loop just to check group and users contains string */
+
	while (pkg_users(pkg, &u) == EPKG_OK) {
+
		if (u->uidstr[0] == '\0') {
+
			/*
+
			 * old style group ignorring, this is created from
+
			 * scripts
+
			 */
+
			return (EPKG_OK);
+
		}
+
	}
+

+
	g = NULL;
+
	u = NULL;
+

+
	while (pkg_groups(pkg, &g) == EPKG_OK) {
+
		char *gr_create_str, *tmp;
+

+
		/* simply create the group */
+
		if ((gr = getgrnam(pkg_group_name(g))) == NULL) {
+
			/* remove the members if any */
+
			if (g->gidstr[strlen(g->gidstr) - 1] == ':') {
+
				gr = gr_scan(g->gidstr);
+
			} else {
+
				gr_create_str = strdup(g->gidstr);
+
				tmp = strrchr(gr_create_str, ':');
+
				tmp++;
+
				tmp[0] = '\0';
+
				gr = gr_scan(gr_create_str);
+
				free(gr_create_str);
+
			}
+
		} else {
+
			/* no need to create the group */
+
			continue;
+
		}
+

+
		if (gr == NULL) {
+
			pkg_emit_error("Bad group line, ignoring");
+
			continue;
+
		}
+
		gr_init(NULL, NULL);
+
		if ((pfd = gr_lock()) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if ((tfd = gr_tmp(-1)) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if (gr_copy(pfd, tfd, gr, NULL) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if (gr_mkdb() == -1) {
+
			gr_fini();
+
			continue;
+
		}
+

+
		free(gr);
+
		gr_fini();
+
	}
+

+
	while (pkg_users(pkg, &u) == EPKG_OK) {
+

+
		if ((pw = getpwnam(pkg_user_name(u))) == NULL) {
+
			/* simply create the user */
+
			pw = pw_scan(u->uidstr, PWSCAN_WARN|PWSCAN_MASTER);
+
		} else {
+
			/* user already exists */
+
			continue;
+
		}
+

+
		pw_init(NULL, NULL);
+
		if ((pfd = pw_lock()) == -1) {
+
			pw_fini();
+
			continue;
+
		}
+
		if ((tfd = gr_tmp(-1)) == -1) {
+
			pw_fini();
+
			continue;
+
		}
+
		if (pw_copy(pfd, tfd, pw, NULL) == -1) {
+
			pw_fini();
+
			continue;
+
		}
+
		if (pw_mkdb(pkg_user_name(u)) == -1) {
+
			pw_fini();
+
		}
+
		pw_fini();
+
		if (strcmp(pw->pw_dir, "/nonexistent") && strcmp(pw->pw_dir, "/var/empty")) {
+
			/* now create the homedir if it doesn't exists */
+
			/* TODO: do it recursively */
+
			mkdir(pw->pw_dir, 0644);
+
			chown(pw->pw_dir, pw->pw_uid, pw->pw_gid);
+
		}
+
		free(pw);
+
	}
+

+
	/* now add members to groups if they also are listed in users */
+
	g = NULL;
+

+
	while (pkg_groups(pkg, &g) == EPKG_OK) {
+
		struct group *grlocal;
+
		struct group *grnew;
+
		int i, j;
+
		int nx;
+

+
		if (g->gidstr[strlen(g->gidstr) - 1] == ':')
+
			continue; /* no members, next */
+

+
		gr = gr_scan(g->gidstr);
+
		grlocal = getgrnam(pkg_group_name(g));
+
		grnew = NULL;/* gr_dup(grlocal);*/
+

+
		u = NULL;
+
		for (i = 0; gr->gr_mem[i] != NULL; i++) {
+

+
			while (pkg_users(pkg, &u) == EPKG_OK) {
+
				if (!strcmp(pkg_user_name(u), gr->gr_mem[i])) {
+
					/* check if the user is not already in the local group */
+
					for (j = 0; grlocal->gr_mem[j] != NULL; j++) {
+
						if (!strcmp(grlocal->gr_mem[j], gr->gr_mem[i]))
+
							break;
+
					}
+

+
					if (grlocal->gr_mem[j] != NULL)
+
						continue; /* already in the group */
+

+
					/* adding the user to the group */
+

+
					if (grnew == NULL) {
+
						nx = j - 1;
+
						grnew = gr_dup(grlocal);
+
					}
+

+
					nx++;
+
					grnew->gr_mem = reallocf(grnew->gr_mem, sizeof(*grnew->gr_mem) * (nx + 1));
+
					grnew->gr_mem[nx - 1] = __DECONST(char *, pkg_user_name(u));
+
					grnew->gr_mem[nx] = NULL;
+
				}
+
			}
+
		}
+
		if (grnew == NULL) {
+
			continue;
+
		}
+
		gr_init(NULL, NULL);
+
		if ((pfd = gr_lock()) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if ((tfd = gr_tmp(-1)) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if (gr_copy(pfd, tfd, grnew, grlocal) == -1) {
+
			gr_fini();
+
			continue;
+
		}
+
		if (gr_mkdb() == -1) {
+
			gr_fini();
+
			continue;
+
		}
+

+
		free(grnew);
+
		gr_fini();
+
	}
+

+
	return (EPKG_OK);
+
}
modified pkg/create.c
@@ -28,7 +28,7 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const
	struct pkg *pkg = NULL;
	int query_flags = PKG_LOAD_DEPS | PKG_LOAD_CONFLICTS | PKG_LOAD_FILES | PKG_LOAD_CATEGORIES |
					  PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
-
					  PKG_LOAD_MTREE | PKG_LOAD_LICENSES;
+
					  PKG_LOAD_MTREE | PKG_LOAD_LICENSES | PKG_LOAD_USERS | PKG_LOAD_GROUPS;

	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
		pkgdb_close(db);