Example #1
0
/*
 * verify that a path generated by mkdtemp() or mkstemp() looks like a
 * reasonable expansion of the template and matches the fd.  Returns true
 * if all the X's were replaced with non-X's
 */
int
check(int fd, char const *kind, char const *path, char const *prefix,
    size_t plen, char const *suffix, size_t slen, int tlen)
{
	struct stat sb, fsb;
	char const *p;

	if (tlen < MIN_Xs) {
		if (fd != -1)
			sudo_fatalx("%s(%s) succeed with too few Xs", kind, path);
		if (errno != EINVAL)
			sudo_fatal("%s(%s) failed with wrong errno: %d", kind, path, errno);
		return 1;
	}
	if (fd == -1)
		sudo_fatal("%s(%s)", kind, path);
	if (stat(path, &sb))
		sudo_fatal("%s: stat(%s)", kind, path);
	if (fd >= 0) {
		if (fstat(fd, &fsb))
			sudo_fatal("%s: fstat(%d==%s)", kind, fd, path);
		if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)
			sudo_fatalx("%s: stat mismatch", kind);
	}
	if (memcmp(path, prefix, plen) != 0)
		sudo_fatalx("%s: prefix changed!  %s vs %s", kind, prefix, path);
	if (memcmp(path + plen + tlen, suffix, slen + 1) != 0)
		sudo_fatalx("%s: suffix changed!  %s vs %s", kind, suffix, path);
	for (p = path + plen; p < path + plen + tlen; p++)
		if (*p == '\0')
			sudo_fatalx("%s: unexpected truncation", kind);
		else if (*p == 'X')
			return 0;
	return 1;
}
Example #2
0
static int
audit_role_change(const security_context_t old_context,
    const security_context_t new_context, const char *ttyn, int result)
{
    int au_fd, rc = -1;
    char *message;
    debug_decl(audit_role_change, SUDO_DEBUG_SELINUX)

    au_fd = audit_open();
    if (au_fd == -1) {
        /* Kernel may not have audit support. */
        if (errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT
)
            sudo_fatal(U_("unable to open audit system"));
    } else {
	/* audit role change using the same format as newrole(1) */
	rc = asprintf(&message, "newrole: old-context=%s new-context=%s",
	    old_context, new_context);
	if (rc == -1)
	    sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE,
	    message, NULL, NULL, ttyn, result);
	if (rc <= 0)
	    sudo_warn(U_("unable to send audit message"));
	free(message);
	close(au_fd);
    }

    debug_return_int(rc);
}
Example #3
0
void
try_mkdtemp(char *p, char const *prefix, int len)
{
	size_t plen = strlen(prefix);
	int fd, tries, ok;

	for (tries = 0; tries < MAX_TRIES; tries++) {
		memcpy(p, prefix, plen);
		memset(p + plen, 'X', len);
		p[plen + len] = '\0';
		fd = mkdtemp(p) ? -2 : -1;
		ok = check(fd, "mkdtemp", p, prefix, plen, "", 0, len);
		rmdir(p);
		if (ok)
			return;
	}
	sudo_fatalx("mkdtemp: exceeded MAX_TRIES");
}
Example #4
0
void
try_mkstemps(char *p, char const *prefix, int len, char const *suffix)
{
	size_t plen = strlen(prefix);
	size_t slen = strlen(suffix);
	int tries, fd, ok;

	for (tries = 0; tries < MAX_TRIES; tries++) {
		memcpy(p, prefix, plen);
		memset(p + plen, 'X', len);
		memcpy(p + plen + len, suffix, slen + 1);
		fd = mkstemps(p, slen);
		ok = check(fd, "mkstemp", p, prefix, plen, suffix, slen, len);
		close(fd);
		unlink(p);
		if (ok)
			return;
	}
	sudo_fatalx("mkstemps: exceeded MAX_TRIES");
}
Example #5
0
File: sesh.c Project: aixoss/sudo
/*
 * Exit codes defined in sudo_exec.h:
 *  SESH_SUCCESS (0)         ... successful operation
 *  SESH_ERR_FAILURE (1)     ... unspecified error
 *  SESH_ERR_INVALID (30)    ... invalid -e arg value
 *  SESH_ERR_BAD_PATHS (31)  ... odd number of paths
 *  SESH_ERR_NO_FILES (32)   ... copy error, no files copied
 *  SESH_ERR_SOME_FILES (33) ... copy error, no files copied
 */
int
main(int argc, char *argv[], char *envp[])
{
    int ret;
    debug_decl(main, SUDO_DEBUG_MAIN)

    initprogname(argc > 0 ? argv[0] : "sesh");

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE_NAME, LOCALEDIR);
    textdomain(PACKAGE_NAME);

    if (argc < 2)
	sudo_fatalx(U_("requires at least one argument"));

    /* Read sudo.conf and initialize the debug subsystem. */
    if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
	exit(EXIT_FAILURE);
    sudo_debug_register(getprogname(), NULL, NULL,
	sudo_conf_debug_files(getprogname()));

    if (strcmp(argv[1], "-e") == 0) {
	ret = sesh_sudoedit(argc, argv);
    } else {
	bool login_shell, noexec = false;
	char *cp, *cmnd;
	int fd = -1;

	/* If the first char of argv[0] is '-', we are running a login shell. */
	login_shell = argv[0][0] == '-';

	/* If argv[0] ends in -noexec, pass the flag to sudo_execve() */
	if ((cp = strrchr(argv[0], '-')) != NULL && cp != argv[0])
	    noexec = strcmp(cp, "-noexec") == 0;

	/* If argv[1] is --execfd=%d, extract the fd to exec with. */
	if (strncmp(argv[1], "--execfd=", 9) == 0) {
	    const char *errstr;

	    cp = argv[1] + 9;
	    fd = strtonum(cp, 0, INT_MAX, &errstr);
	    if (errstr != NULL)
		sudo_fatalx(U_("invalid file descriptor number: %s"), cp);
	    argv++;
	    argc--;
	}

	/* Shift argv and make a copy of the command to execute. */
	argv++;
	argc--;
	if ((cmnd = strdup(argv[0])) == NULL)
	    sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));

	/* If invoked as a login shell, modify argv[0] accordingly. */
	if (login_shell) {
	    if ((cp = strrchr(argv[0], '/')) == NULL)
		sudo_fatal(U_("unable to run %s as a login shell"), argv[0]);
	    *cp = '-';
	    argv[0] = cp;
	}
	sudo_execve(fd, cmnd, argv, envp, noexec);
	sudo_warn(U_("unable to execute %s"), cmnd);
	ret = SESH_ERR_FAILURE;
    }
    sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, ret);
    _exit(ret);
}
Example #6
0
struct log_info *
parse_logfile(const char *logfile)
{
    FILE *fp;
    char *buf = NULL, *cp, *ep;
    const char *errstr;
    size_t bufsize = 0, cwdsize = 0, cmdsize = 0;
    struct log_info *li = NULL;
    debug_decl(parse_logfile, SUDO_DEBUG_UTIL)

    fp = fopen(logfile, "r");
    if (fp == NULL) {
	sudo_warn(U_("unable to open %s"), logfile);
	goto bad;
    }

    /*
     * ID file has three lines:
     *  1) a log info line
     *  2) cwd
     *  3) command with args
     */
    if ((li = calloc(1, sizeof(*li))) == NULL)
	sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
    if (getdelim(&buf, &bufsize, '\n', fp) == -1 ||
	getdelim(&li->cwd, &cwdsize, '\n', fp) == -1 ||
	getdelim(&li->cmd, &cmdsize, '\n', fp) == -1) {
	sudo_warn(U_("%s: invalid log file"), logfile);
	goto bad;
    }

    /* Strip the newline from the cwd and command. */
    li->cwd[strcspn(li->cwd, "\n")] = '\0';
    li->cmd[strcspn(li->cmd, "\n")] = '\0';

    /*
     * Crack the log line (rows and cols not present in old versions).
     *	timestamp:user:runas_user:runas_group:tty:rows:cols
     * XXX - probably better to use strtok and switch on the state.
     */
    buf[strcspn(buf, "\n")] = '\0';
    cp = buf;

    /* timestamp */
    if ((ep = strchr(cp, ':')) == NULL) {
	sudo_warn(U_("%s: time stamp field is missing"), logfile);
	goto bad;
    }
    *ep = '\0';
    li->tstamp = strtonum(cp, 0, TIME_T_MAX, &errstr);
    if (errstr != NULL) {
	sudo_warn(U_("%s: time stamp %s: %s"), logfile, cp, errstr);
	goto bad;
    }

    /* user */
    cp = ep + 1;
    if ((ep = strchr(cp, ':')) == NULL) {
	sudo_warn(U_("%s: user field is missing"), logfile);
	goto bad;
    }
    if ((li->user = strndup(cp, (size_t)(ep - cp))) == NULL)
	sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));

    /* runas user */
    cp = ep + 1;
    if ((ep = strchr(cp, ':')) == NULL) {
	sudo_warn(U_("%s: runas user field is missing"), logfile);
	goto bad;
    }
    if ((li->runas_user = strndup(cp, (size_t)(ep - cp))) == NULL)
	sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));

    /* runas group */
    cp = ep + 1;
    if ((ep = strchr(cp, ':')) == NULL) {
	sudo_warn(U_("%s: runas group field is missing"), logfile);
	goto bad;
    }
    if (cp != ep) {
	if ((li->runas_group = strndup(cp, (size_t)(ep - cp))) == NULL)
	    sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
    }

    /* tty, followed by optional rows + columns */
    cp = ep + 1;
    if ((ep = strchr(cp, ':')) == NULL) {
	/* just the tty */
	if ((li->tty = strdup(cp)) == NULL)
	    sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
    } else {
	/* tty followed by rows + columns */
	if ((li->tty = strndup(cp, (size_t)(ep - cp))) == NULL)
	    sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	cp = ep + 1;
	/* need to NULL out separator to use strtonum() */
	if ((ep = strchr(cp, ':')) != NULL) {
	    *ep = '\0';
	}
	li->rows = strtonum(cp, 1, INT_MAX, &errstr);
	if (errstr != NULL) {
	    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
		"%s: tty rows %s: %s", logfile, cp, errstr);
	}
	if (ep != NULL) {
	    cp = ep + 1;
	    li->cols = strtonum(cp, 1, INT_MAX, &errstr);
	    if (errstr != NULL) {
		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
		    "%s: tty cols %s: %s", logfile, cp, errstr);
	    }
	}
    }
    fclose(fp);
    free(buf);
    debug_return_ptr(li);

bad:
    if (fp != NULL)
	fclose(fp);
    free(buf);
    free_log_info(li);
    debug_return_ptr(NULL);
}