*/
#include <ctype.h>
-#ifdef HAVE_LIBSELINUX
-#include <selinux/selinux.h>
-#include <selinux/context.h>
-#endif
-
#include "strutils.h"
#include "mountP.h"
return rc;
}
-/*
- * @optstr: string with comma separated list of options
- * @value: pointer to the begin of the context value
- * @valsz: size of the value
- * @next: returns pointer to the next option (optional argument)
- *
- * Translates SELinux context from human to raw format. The function does not
- * modify @optstr and returns zero if libmount is compiled without SELinux
- * support.
- *
- * Returns: 0 on success, a negative number in case of error.
- */
-#ifndef HAVE_LIBSELINUX
-int mnt_optstr_fix_secontext(char **optstr __attribute__ ((__unused__)),
- char *value __attribute__ ((__unused__)),
- size_t valsz __attribute__ ((__unused__)),
- char **next __attribute__ ((__unused__)))
-{
- return 0;
-}
-#else
-int mnt_optstr_fix_secontext(char **optstr,
- char *value,
- size_t valsz,
- char **next)
-{
- int rc = 0;
- char *p, *val, *begin, *end, *raw = NULL;
- size_t sz;
-
- if (!optstr || !*optstr || !value || !valsz)
- return -EINVAL;
-
- DBG(CXT, ul_debug("fixing SELinux context"));
-
- begin = value;
- end = value + valsz;
-
- /* the selinux contexts are quoted */
- if (*value == '"') {
- if (valsz <= 2 || *(value + valsz - 1) != '"')
- return -EINVAL; /* improperly quoted option string */
- value++;
- valsz -= 2;
- }
-
- p = strndup(value, valsz);
- if (!p)
- return -ENOMEM;
-
-
- /* translate the context */
- rc = selinux_trans_to_raw_context(p, &raw);
-
- DBG(CXT, ul_debug("SELinux context '%s' translated to '%s'",
- p, rc == -1 ? "FAILED" : (char *) raw));
-
- free(p);
- if (rc == -1 || !raw)
- return -EINVAL;
-
-
- /* create a quoted string from the raw context */
- sz = strlen((char *) raw);
- if (!sz) {
- freecon(raw);
- return -EINVAL;
- }
-
- p = val = malloc(valsz + 3);
- if (!val) {
- freecon(raw);
- return -ENOMEM;
- }
-
- *p++ = '"';
- memcpy(p, raw, sz);
- p += sz;
- *p++ = '"';
- *p = '\0';
-
- freecon(raw);
-
- /* set new context */
- mnt_optstr_remove_option_at(optstr, begin, end);
- rc = insert_value(optstr, begin, val, next);
- free(val);
-
- return rc;
-}
-#endif
-
-static int set_uint_value(char **optstr, unsigned int num,
- char *begin, char *end, char **next)
-{
- char buf[40];
- snprintf(buf, sizeof(buf), "%u", num);
-
- mnt_optstr_remove_option_at(optstr, begin, end);
- return insert_value(optstr, begin, buf, next);
-}
-
-/*
- * @optstr: string with a comma separated list of options
- * @value: pointer to the beginning of the uid value
- * @valsz: size of the value
- * @next: returns pointer to the next option (optional argument)
- *
- * Translates "username" or "useruid" to the real UID.
- *
- * For example:
- * if (!mnt_optstr_get_option(optstr, "uid", &val, &valsz))
- * mnt_optstr_fix_uid(&optstr, val, valsz, NULL);
- *
- * Returns: 0 on success, a negative number in case of error.
- */
-int mnt_optstr_fix_uid(char **optstr, char *value, size_t valsz, char **next)
-{
- char *end;
-
- if (!optstr || !*optstr || !value || !valsz)
- return -EINVAL;
-
- DBG(CXT, ul_debug("fixing uid"));
-
- end = value + valsz;
-
- if (valsz == 7 && !strncmp(value, "useruid", 7) &&
- (*(value + 7) == ',' || !*(value + 7)))
- return set_uint_value(optstr, getuid(), value, end, next);
-
- if (!isdigit(*value)) {
- uid_t id;
- int rc;
- char *p = strndup(value, valsz);
- if (!p)
- return -ENOMEM;
- rc = mnt_get_uid(p, &id);
- free(p);
-
- if (!rc)
- return set_uint_value(optstr, id, value, end, next);
- }
-
- if (next) {
- /* no change, let's keep the original value */
- *next = value + valsz;
- if (**next == ',')
- (*next)++;
- }
-
- return 0;
-}
-
-/*
- * @optstr: string with a comma separated list of options
- * @value: pointer to the beginning of the uid value
- * @valsz: size of the value
- * @next: returns pointer to the next option (optional argument)
-
- * Translates "groupname" or "usergid" to the real GID.
- *
- * Returns: 0 on success, a negative number in case of error.
- */
-int mnt_optstr_fix_gid(char **optstr, char *value, size_t valsz, char **next)
-{
- char *end;
-
- if (!optstr || !*optstr || !value || !valsz)
- return -EINVAL;
-
- DBG(CXT, ul_debug("fixing gid"));
-
- end = value + valsz;
-
- if (valsz == 7 && !strncmp(value, "usergid", 7) &&
- (*(value + 7) == ',' || !*(value + 7)))
- return set_uint_value(optstr, getgid(), value, end, next);
-
- if (!isdigit(*value)) {
- int rc;
- gid_t id;
- char *p = strndup(value, valsz);
- if (!p)
- return -ENOMEM;
- rc = mnt_get_gid(p, &id);
- free(p);
-
- if (!rc)
- return set_uint_value(optstr, id, value, end, next);
-
- }
-
- if (next) {
- /* nothing */
- *next = value + valsz;
- if (**next == ',')
- (*next)++;
- }
- return 0;
-}
-
-/*
- * Converts "user" to "user=<username>".
- *
- * Returns: 0 on success, negative number in case of error.
- */
-int mnt_optstr_fix_user(char **optstr)
-{
- char *username;
- struct libmnt_optloc ol = MNT_INIT_OPTLOC;
- int rc = 0;
-
- DBG(CXT, ul_debug("fixing user"));
-
- rc = mnt_optstr_locate_option(*optstr, "user", &ol);
- if (rc)
- return rc == 1 ? 0 : rc; /* 1: user= not found */
-
- username = mnt_get_username(getuid());
- if (!username)
- return -ENOMEM;
-
- if (!ol.valsz || (ol.value && strncmp(ol.value, username, ol.valsz) != 0)) {
- if (ol.valsz)
- /* remove old value */
- mnt_optstr_remove_option_at(optstr, ol.value, ol.end);
-
- rc = insert_value(optstr, ol.value ? ol.value : ol.end,
- username, NULL);
- }
-
- free(username);
- return rc;
-}
-
/*
* Converts value from @optstr addressed by @name to uid.
*
return rc;
}
-static int test_fix(struct libmnt_test *ts, int argc, char *argv[])
-{
- char *optstr;
- int rc = 0;
- char *name, *val, *next;
- size_t valsz, namesz;
-
- if (argc < 2)
- return -EINVAL;
-
- next = optstr = xstrdup(argv[1]);
-
- printf("optstr: %s\n", optstr);
-
- while (!mnt_optstr_next_option(&next, &name, &namesz, &val, &valsz)) {
-
- if (!strncmp(name, "uid", 3))
- rc = mnt_optstr_fix_uid(&optstr, val, valsz, &next);
- else if (!strncmp(name, "gid", 3))
- rc = mnt_optstr_fix_gid(&optstr, val, valsz, &next);
- else if (!strncmp(name, "context", 7))
- rc = mnt_optstr_fix_secontext(&optstr, val, valsz, &next);
- if (rc)
- break;
- }
- if (rc)
- rc = mnt_optstr_fix_user(&optstr);
-
- printf("fixed: %s\n", optstr);
-
- free(optstr);
- return rc;
-
-}
-
int main(int argc, char *argv[])
{
struct libmnt_test tss[] = {
{ "--split", test_split, "<optstr> split into FS, VFS and userspace" },
{ "--flags", test_flags, "<optstr> convert options to MS_* flags" },
{ "--apply", test_apply, "--{linux,user} <optstr> <mask> apply mask to optstr" },
- { "--fix", test_fix, "<optstr> fix uid=, gid=, user, and context=" },
{ NULL }
};