fsid.c 2.04 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/*
 * Connection Manager
 *
 * Copyright (C) 2016 Jolla Ltd. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "connman.h"

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <sys/fsuid.h>

/* Parses "user[:group]" string and sets fs identity */
void __connman_set_fsid(const char *fs_identity)
{
	char *sep = strchr(fs_identity, ':');
	const char *user;
	char *tmp_user;
	const struct passwd *pw = NULL;
	const struct group *gr = NULL;

	if (sep) {
		/* Group */
		const char *group = sep + 1;

		gr = getgrnam(group);
		user = tmp_user = g_strndup(fs_identity, sep - fs_identity);

		if (!gr) {
			/* Try numeric */
			char *end = NULL;
			long n = strtol(group, &end, 0);
			if (end && end != group &&
					((n != LONG_MAX && n != LONG_MIN) ||
							errno != ERANGE)) {
				gr = getgrgid(n);
			}

			if (!gr) {
				fprintf(stderr, "Invalid group '%s'", group);
			}
		}
	} else {
		user = fs_identity;
                tmp_user = NULL;
	}

	/* User */
	pw = getpwnam(user);
	if (!pw) {
		/* Try numeric */
		char *end = NULL;
		long n = strtol(user, &end, 0);
		if (end && end != user && ((n != LONG_MAX && n != LONG_MIN) ||
							errno != ERANGE)) {
			pw = getpwuid(n);

			if (!pw) {
				fprintf(stderr, "Invalid user '%s'", user);
			}
		}
	}

	/* Set fs identity */
	if (pw) {
		errno = 0;
		setfsuid(pw->pw_uid);
		if (errno) {
			fprintf(stderr, "Failed to set fsuid to %d: %s\n",
						pw->pw_uid, strerror(errno));
		}
	}

	if (gr) {
		errno = 0;
		setfsgid(gr->gr_gid);
		if (errno) {
			fprintf(stderr, "Failed to set fsgid to %d: %s\n",
						gr->gr_gid, strerror(errno));
		}
	}

	g_free(tmp_user);
}