Exemplo n.º 1
0
bool
fill_txt(const char *src, size_t len, size_t olen)
{
    char *dst;
    int h;
    debug_decl(fill_txt, SUDOERS_DEBUG_PARSER)

    dst = olen ? realloc(sudoerslval.string, olen + len + 1) : malloc(len + 1);
    if (dst == NULL) {
	sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	sudoerserror(NULL);
	debug_return_bool(false);
    }
    sudoerslval.string = dst;

    /* Copy the string and collapse any escaped characters. */
    dst += olen;
    while (len--) {
	if (*src == '\\' && len) {
	    if (src[1] == 'x' && len >= 3 && (h = hexchar(src + 2)) != -1) {
		*dst++ = h;
		src += 4;
		len -= 3;
	    } else {
		src++;
		len--;
		*dst++ = *src++;
	    }
	} else {
	    *dst++ = *src++;
	}
    }
    *dst = '\0';
    debug_return_bool(true);
}
Exemplo n.º 2
0
bool
fill_cmnd(const char *src, size_t len)
{
    char *dst;
    size_t i;
    debug_decl(fill_cmnd, SUDOERS_DEBUG_PARSER)

    arg_len = arg_size = 0;

    dst = sudoerslval.command.cmnd = malloc(len + 1);
    if (dst == NULL) {
	sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	sudoerserror(NULL);
	debug_return_bool(false);
    }
    sudoerslval.command.args = NULL;

    /* Copy the string and collapse any escaped sudo-specific characters. */
    for (i = 0; i < len; i++) {
	if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1]))
	    *dst++ = src[++i];
	else
	    *dst++ = src[i];
    }
    *dst = '\0';

    debug_return_bool(true);
}
Exemplo n.º 3
0
Arquivo: dce.c Projeto: mer-tools/sudo
/* Returns 0 for DCE "ok" status, 1 otherwise */
static int
check_dce_status(error_status_t input_status, char *comment)
{
    int error_stat;
    unsigned char error_string[dce_c_error_string_len];
    debug_decl(check_dce_status, SUDO_DEBUG_AUTH)

    if (input_status == rpc_s_ok)
	debug_return_bool(0);
    dce_error_inq_text(input_status, error_string, &error_stat);
    (void) fprintf(stderr, "%s %s\n", comment, error_string);
    debug_return_bool(1);
}
static bool
addr_matches_if(const char *n)
{
    union sudo_in_addr_un addr;
    struct interface *ifp;
#ifdef HAVE_STRUCT_IN6_ADDR
    unsigned int j;
#endif
    unsigned int family;
    debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)

#ifdef HAVE_STRUCT_IN6_ADDR
    if (inet_pton(AF_INET6, n, &addr.ip6) == 1) {
	family = AF_INET6;
    } else
#endif /* HAVE_STRUCT_IN6_ADDR */
    if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
	family = AF_INET;
    } else {
	debug_return_bool(false);
    }

    SLIST_FOREACH(ifp, get_interfaces(), entries) {
	if (ifp->family != family)
	    continue;
	switch (family) {
	    case AF_INET:
		if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
		    (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
		    == addr.ip4.s_addr)
		    debug_return_bool(true);
		break;
#ifdef HAVE_STRUCT_IN6_ADDR
	    case AF_INET6:
		if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
		    sizeof(addr.ip6.s6_addr)) == 0)
		    debug_return_bool(true);
		for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
		    if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
			break;
		}
		if (j == sizeof(addr.ip6.s6_addr))
		    debug_return_bool(true);
		break;
#endif /* HAVE_STRUCT_IN6_ADDR */
	}
    }

    debug_return_bool(false);
}
Exemplo n.º 5
0
bool
get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid)
{
    char *line;
    bool rval = false;
    debug_decl(get_pty, SUDO_DEBUG_PTY)

    *master = posix_openpt(O_RDWR|O_NOCTTY);
    if (*master != -1) {
	(void) grantpt(*master); /* may fork */
	if (unlockpt(*master) != 0) {
	    close(*master);
	    goto done;
	}
	line = ptsname(*master);
	if (line == NULL) {
	    close(*master);
	    goto done;
	}
	*slave = open(line, O_RDWR|O_NOCTTY, 0);
	if (*slave == -1) {
	    close(*master);
	    goto done;
	}
# if defined(I_PUSH) && !defined(_AIX)
	ioctl(*slave, I_PUSH, "ptem");	/* pseudo tty emulation module */
	ioctl(*slave, I_PUSH, "ldterm");	/* line discipline module */
# endif
	(void) chown(line, ttyuid, -1);
	strlcpy(name, line, namesz);
	rval = true;
    }
done:
    debug_return_bool(rval);
}
Exemplo n.º 6
0
/*
 * Log and audit that user was not allowed to run the command.
 */
bool
log_failure(int status, int flags)
{
    bool ret, inform_user = true;
    debug_decl(log_failure, SUDOERS_DEBUG_LOGGING)

    /* The user doesn't always get to see the log message (path info). */
    if (!ISSET(status, FLAG_NO_USER | FLAG_NO_HOST) && def_path_info &&
	(flags == NOT_FOUND_DOT || flags == NOT_FOUND))
	inform_user = false;
    ret = log_denial(status, inform_user);

    if (!inform_user) {
	/*
	 * We'd like to not leak path info at all here, but that can
	 * *really* confuse the users.  To really close the leak we'd
	 * have to say "not allowed to run foo" even when the problem
	 * is just "no foo in path" since the user can trivially set
	 * their path to just contain a single dir.
	 */
	if (flags == NOT_FOUND)
	    sudo_warnx(U_("%s: command not found"), user_cmnd);
	else if (flags == NOT_FOUND_DOT)
	    sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), user_cmnd, user_cmnd, user_cmnd);
    }

    debug_return_bool(ret);
}
/*
 * Checks if the user is exempt from supplying a password.
 */
bool
user_is_exempt(void)
{
    bool rval = false;
    debug_decl(user_is_exempt, SUDO_DEBUG_AUTH)

    if (def_exempt_group)
	rval = user_in_group(sudo_user.pw, def_exempt_group);
    debug_return_bool(rval);
}
Exemplo n.º 8
0
bool
fill_args(const char *s, size_t len, int addspace)
{
    unsigned int new_len;
    char *p;
    debug_decl(fill_args, SUDOERS_DEBUG_PARSER)

    if (arg_size == 0) {
	addspace = 0;
	new_len = len;
    } else
	new_len = arg_len + len + addspace;

    if (new_len >= arg_size) {
	/* Allocate in increments of 128 bytes to avoid excessive realloc(). */
	arg_size = (new_len + 1 + 127) & ~127;

	p = realloc(sudoerslval.command.args, arg_size);
	if (p == NULL) {
	    sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	    goto bad;
	} else
	    sudoerslval.command.args = p;
    }

    /* Efficiently append the arg (with a leading space if needed). */
    p = sudoerslval.command.args + arg_len;
    if (addspace)
	*p++ = ' ';
    len = arg_size - (p - sudoerslval.command.args);
    if (strlcpy(p, s, len) >= len) {
	sudo_warnx(U_("internal error, %s overflow"), __func__);
	goto bad;
    }
    arg_len = new_len;
    debug_return_bool(true);
bad:
    sudoerserror(NULL);
    free(sudoerslval.command.args);
    sudoerslval.command.args = NULL;
    arg_len = arg_size = 0;
    debug_return_bool(false);
}
    SLIST_FOREACH(ifp, get_interfaces(), entries) {
	if (ifp->family != family)
	    continue;
	switch (family) {
	    case AF_INET:
		if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
		    debug_return_bool(true);
		break;
#ifdef HAVE_STRUCT_IN6_ADDR
	    case AF_INET6:
		for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
		    if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
			break;
		}
		if (j == sizeof(addr.ip6.s6_addr))
		    debug_return_bool(true);
		break;
#endif /* HAVE_STRUCT_IN6_ADDR */
	}
    }
Exemplo n.º 10
0
bool
append(const char *src, size_t len)
{
    int olen = 0;
    debug_decl(append, SUDOERS_DEBUG_PARSER)

    if (sudoerslval.string != NULL)
	olen = strlen(sudoerslval.string);

    debug_return_bool(fill_txt(src, len, olen));
}
Exemplo n.º 11
0
/*
 * Log and potentially mail the allowed command.
 */
bool
log_allowed(int status)
{
    char *logline;
    int oldlocale;
    bool uid_changed, ret = true;
    debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING)

    /* Log and mail messages should be in the sudoers locale. */
    sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);

    if ((logline = new_logline(NULL, 0)) == NULL)
	debug_return_bool(false);

    /* Become root if we are not already. */
    uid_changed = set_perms(PERM_ROOT);

    /* XXX - return value */
    if (should_mail(status))
	send_mail("%s", logline);	/* send mail based on status */

    /*
     * Log via syslog and/or a file.
     */
    if (def_syslog)
	do_syslog(def_syslog_goodpri, logline);
    if (def_logfile && !do_logfile(logline))
	ret = false;

    if (uid_changed) {
	if (!restore_perms())
	    ret = false;		/* XXX - return -1 instead? */
    }

    free(logline);

    sudoers_setlocale(oldlocale, NULL);

    debug_return_bool(ret);
}
Exemplo n.º 12
0
/*
 * Returns true if the user successfully authenticates, false if not
 * or -1 on error.
 */
static int
check_user_interactive(int validated, int mode, struct passwd *auth_pw)
{
    int status, rval = true;
    debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH)

    /* Always need a password when -k was specified with the command. */
    if (ISSET(mode, MODE_IGNORE_TICKET))
	SET(validated, FLAG_CHECK_USER);

    if (build_timestamp(auth_pw) == -1) {
	rval = -1;
	goto done;
    }

    status = timestamp_status(auth_pw);

    if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
	char *prompt;
	bool lectured;

	/* Bail out if we are non-interactive and a password is required */
	if (ISSET(mode, MODE_NONINTERACTIVE)) {
	    validated |= FLAG_NON_INTERACTIVE;
	    log_auth_failure(validated, 0);
	    rval = -1;
	    goto done;
	}

	/* XXX - should not lecture if askpass helper is being used. */
	lectured = display_lecture(status);

	/* Expand any escapes in the prompt. */
	prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
	    auth_pw->pw_name);
	if (prompt == NULL) {
	    rval = -1;
	    goto done;
	}

	rval = verify_user(auth_pw, prompt, validated);
	if (rval == true && lectured)
	    set_lectured();
	sudo_efree(prompt);
    }
    /* Only update timestamp if user was validated. */
    if (rval == true && ISSET(validated, VALIDATE_SUCCESS) &&
	!ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
	update_timestamp(auth_pw);
done:
    debug_return_bool(rval);
}
Exemplo n.º 13
0
bool
get_boottime(struct timespec *ts)
{
    size_t size;
    int mib[2];
    struct timeval tv;
    debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)

    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    size = sizeof(tv);
    if (sysctl(mib, 2, &tv, &size, NULL, 0) != -1) {
	sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
	    "KERN_BOOTTIME: %lld, %ld", (long long)tv.tv_sec, (long)tv.tv_usec);
	TIMEVAL_TO_TIMESPEC(&tv, ts);
	debug_return_bool(true);
    }

    sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
	"KERN_BOOTTIME: %s", strerror(errno));
    debug_return_bool(false);
}
/*
 * Display sudo lecture (standard or custom).
 * Returns true if the user was lectured, else false.
 */
static bool
display_lecture(int status)
{
    FILE *fp;
    char buf[BUFSIZ];
    ssize_t nread;
    struct sudo_conv_message msg;
    struct sudo_conv_reply repl;
    debug_decl(lecture, SUDO_DEBUG_AUTH)

    if (def_lecture == never ||
	(def_lecture == once && already_lectured(status)))
	debug_return_bool(false);

    memset(&msg, 0, sizeof(msg));
    memset(&repl, 0, sizeof(repl));

    if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) {
	while ((nread = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) != 0) {
	    buf[nread] = '\0';
	    msg.msg_type = SUDO_CONV_ERROR_MSG;
	    msg.msg = buf;
	    sudo_conv(1, &msg, &repl);
	}
	fclose(fp);
    } else {
	msg.msg_type = SUDO_CONV_ERROR_MSG;
	msg.msg = _("\n"
	    "We trust you have received the usual lecture from the local System\n"
	    "Administrator. It usually boils down to these three things:\n\n"
	    "    #1) Respect the privacy of others.\n"
	    "    #2) Think before you type.\n"
	    "    #3) With great power comes great responsibility.\n\n");
	sudo_conv(1, &msg, &repl);
    }
    debug_return_bool(true);
}
Exemplo n.º 15
0
/*
 * Returns true if the user successfully authenticates, false if not
 * or -1 on error.
 */
int
check_user(int validated, int mode)
{
    struct passwd *auth_pw;
    int rval = -1;
    debug_decl(check_user, SUDOERS_DEBUG_AUTH)

    /*
     * Init authentication system regardless of whether we need a password.
     * Required for proper PAM session support.
     */
    if ((auth_pw = get_authpw(mode)) == NULL)
	goto done;
    if (sudo_auth_init(auth_pw) == -1)
	goto done;

    /*
     * Don't prompt for the root passwd or if the user is exempt.
     * If the user is not changing uid/gid, no need for a password.
     */
    if (!def_authenticate || user_is_exempt()) {
	rval = true;
	goto done;
    }
    if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
	(!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name)))) {
#ifdef HAVE_SELINUX
	if (user_role == NULL && user_type == NULL)
#endif
#ifdef HAVE_PRIV_SET
	if (runas_privs == NULL && runas_limitprivs == NULL)
#endif
	{
	    rval = true;
	    goto done;
	}
    }

    rval = check_user_interactive(validated, mode, auth_pw);

done:
    sudo_auth_cleanup(auth_pw);
    sudo_pw_delref(auth_pw);

    debug_return_bool(rval);
}
Exemplo n.º 16
0
/*
 * Check to make sure an IPv6 address does not contain multiple instances
 * of the string "::".  Assumes strlen(s) >= 1.
 * Returns true if address is valid else false.
 */
bool
ipv6_valid(const char *s)
{
    int nmatch = 0;
    debug_decl(ipv6_valid, SUDOERS_DEBUG_PARSER)

    for (; *s != '\0'; s++) {
	if (s[0] == ':' && s[1] == ':') {
	    if (++nmatch > 1)
		break;
	}
	if (s[0] == '/')
	    nmatch = 0;			/* reset if we hit netmask */
    }

    debug_return_bool(nmatch <= 1);
}
Exemplo n.º 17
0
bool
get_boottime(struct timespec *ts)
{
    struct utmpx *ut, key;
    debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)

    memset(&key, 0, sizeof(key));
    key.ut_type = BOOT_TIME;
    setutxent();
    if ((ut = getutxid(&key)) != NULL) {
	sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
	    "BOOT_TIME: %lld, %ld", (long long)ut->ut_tv.tv_sec,
	    (long)ut->ut_tv.tv_usec);
	TIMEVAL_TO_TIMESPEC(&ut->ut_tv, ts);
    }
    endutxent();
    debug_return_bool(ut != NULL);
}
Exemplo n.º 18
0
bool
get_boottime(struct timespec *ts)
{
    struct utmp *ut, key;
    debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)

    memset(&key, 0, sizeof(key));
    key.ut_type = BOOT_TIME;
    setutent();
    if ((ut = getutid(&key)) != NULL) {
	sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
	    "BOOT_TIME: %lld", (long long)ut->ut_time);
	ts->tv_sec = ut->ut_time;
	ts->tv_nsec = 0;
    }
    endutent();
    debug_return_bool(ut != NULL);
}
Exemplo n.º 19
0
bool
get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid)
{
    struct group *gr;
    gid_t ttygid = -1;
    bool rval = false;
    debug_decl(get_pty, SUDO_DEBUG_PTY)

    if ((gr = getgrnam("tty")) != NULL)
	ttygid = gr->gr_gid;

    if (openpty(master, slave, name, NULL, NULL) == 0) {
	if (chown(name, ttyuid, ttygid) == 0)
	    rval = true;
    }

    debug_return_bool(rval);
}
Exemplo n.º 20
0
bool
get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid)
{
    char *bank, *cp;
    struct group *gr;
    gid_t ttygid = -1;
    bool rval = false;
    debug_decl(get_pty, SUDO_DEBUG_PTY)

    if ((gr = getgrnam("tty")) != NULL)
	ttygid = gr->gr_gid;

    for (bank = "pqrs"; *bank != '\0'; bank++) {
	line[sizeof("/dev/ptyX") - 2] = *bank;
	for (cp = "0123456789abcdef"; *cp != '\0'; cp++) {
	    line[sizeof("/dev/ptyXX") - 2] = *cp;
	    *master = open(line, O_RDWR|O_NOCTTY, 0);
	    if (*master == -1) {
		if (errno == ENOENT)
		    goto done; /* out of ptys */
		continue; /* already in use */
	    }
	    line[sizeof("/dev/p") - 2] = 't';
	    (void) chown(line, ttyuid, ttygid);
	    (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
# ifdef HAVE_REVOKE
	    (void) revoke(line);
# endif
	    *slave = open(line, O_RDWR|O_NOCTTY, 0);
	    if (*slave != -1) {
		    strlcpy(name, line, namesz);
		    rval = true; /* success */
		    goto done;
	    }
	    (void) close(*master);
	}
    }
done:
    debug_return_bool(rval);
}
Exemplo n.º 21
0
static int
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
    sudo_printf_t plugin_printf, char * const settings[],
    char * const user_info[], char * const envp[], char * const args[])
{
    struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
    struct sudoers_policy_open_info info;
    const char *plugin_path = NULL;
    char * const *cur;
    debug_decl(sudoers_policy_open, SUDOERS_DEBUG_PLUGIN)

    sudo_version = version;
    sudo_conv = conversation;
    sudo_printf = plugin_printf;

    /* Plugin args are only specified for API version 1.2 and higher. */
    if (sudo_version < SUDO_API_MKVERSION(1, 2))
	args = NULL;

    /* Initialize the debug subsystem.  */
    for (cur = settings; *cur != NULL; cur++) {
	if (strncmp(*cur, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
	    sudoers_debug_parse_flags(&debug_files,
		*cur + sizeof("debug_flags=") - 1);
	    continue;
	}
	if (strncmp(*cur, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
	    plugin_path = *cur + sizeof("plugin_path=") - 1;
	    continue;
	}
    }
    sudoers_debug_register(plugin_path, &debug_files);

    /* Call the sudoers init function. */
    info.settings = settings;
    info.user_info = user_info;
    info.plugin_args = args;
    debug_return_bool(sudoers_policy_init(&info, envp));
}
Exemplo n.º 22
0
bool
get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid)
{
    char *line;
    bool rval = false;
    debug_decl(get_pty, SUDO_DEBUG_PTY)

    /* IRIX-style dynamic ptys (may fork) */
    line = _getpty(master, O_RDWR, S_IRUSR|S_IWUSR|S_IWGRP, 0);
    if (line != NULL) {
	*slave = open(line, O_RDWR|O_NOCTTY, 0);
	if (*slave != -1) {
	    (void) chown(line, ttyuid, -1);
	    strlcpy(name, line, namesz);
	    rval = true;
	} else {
	    close(*master);
	    *master = -1;
	}
    }
    debug_return_bool(rval);
}
Exemplo n.º 23
0
/*
 * Log and audit that user was not able to authenticate themselves.
 */
bool
log_auth_failure(int status, unsigned int tries)
{
    int flags = 0;
    bool ret = true;
    debug_decl(log_auth_failure, SUDOERS_DEBUG_LOGGING)

    /* Handle auditing first. */
    audit_failure(NewArgc, NewArgv, N_("authentication failure"));

    /*
     * Do we need to send mail?
     * We want to avoid sending multiple messages for the same command
     * so if we are going to send an email about the denial, that takes
     * precedence.
     */
    if (ISSET(status, VALIDATE_SUCCESS)) {
	/* Command allowed, auth failed; do we need to send mail? */
	if (def_mail_badpass || def_mail_always)
	    SET(flags, SLOG_SEND_MAIL);
    } else {
	/* Command denied, auth failed; make sure we don't send mail twice. */
	if (def_mail_badpass && !should_mail(status))
	    SET(flags, SLOG_SEND_MAIL);
	/* Don't log the bad password message, we'll log a denial instead. */
	SET(flags, SLOG_NO_LOG);
    }

    /*
     * If sudoers denied the command we'll log that separately.
     */
    if (ISSET(status, FLAG_BAD_PASSWORD))
	ret = log_warningx(flags, INCORRECT_PASSWORD_ATTEMPT, tries);
    else if (ISSET(status, FLAG_NON_INTERACTIVE))
	ret = log_warningx(flags, N_("a password is required"));

    debug_return_bool(ret);
}
Exemplo n.º 24
0
bool
get_boottime(struct timespec *ts)
{
    char *line = NULL;
    size_t linesize = 0;
    bool found = false;
    long long llval;
    ssize_t len;
    FILE *fp;
    debug_decl(get_boottime, SUDOERS_DEBUG_UTIL)

    /* read btime from /proc/stat */
    fp = fopen("/proc/stat", "r");
    if (fp != NULL) {
	while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
	    if (strncmp(line, "btime ", 6) == 0) {
		if (line[len - 1] == '\n')
		    line[len - 1] = '\0';
		llval = strtonum(line + 6, 1, LLONG_MAX, NULL);
		if (llval > 0) {
		    ts->tv_sec = (time_t)llval;
		    ts->tv_nsec = 0;
		    found = true;
		    sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
			"found btime in /proc/stat: %lld", llval);
		    break;
		} else {
		    sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
			"invalid btime in /proc/stat: %s", line);
		}
	    }
	}
	fclose(fp);
	free(line);
    }

    debug_return_bool(found);
}
Exemplo n.º 25
0
static int
sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
    sudo_printf_t plugin_printf, char * const settings[],
    char * const user_info[], char * const envp[], char * const args[])
{
    volatile int sources = 0;
    sigaction_t sa;
    struct sudo_nss *nss;
    struct sudo_nss *nss_next;
    debug_decl(sudoers_policy_open, SUDO_DEBUG_PLUGIN)

    sudo_version = version;
    if (!sudo_conv)
	sudo_conv = conversation;
    if (!sudo_printf)
	sudo_printf = plugin_printf;

    /* Plugin args are only specified for API version 1.2 and higher. */
    if (sudo_version < SUDO_API_MKVERSION(1, 2))
	args = NULL;

    if (sigsetjmp(error_jmp, 1)) {
	/* called via error(), errorx() or log_fatal() */
	rewind_perms();
	debug_return_bool(-1);
    }

    bindtextdomain("sudoers", LOCALEDIR);

    /*
     * Signal setup:
     *	Ignore keyboard-generated signals so the user cannot interrupt
     *  us at some point and avoid the logging.
     *  Install handler to wait for children when they exit.
     */
    zero_bytes(&sa, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = SIG_IGN;
    (void) sigaction(SIGINT, &sa, &saved_sa_int);
    (void) sigaction(SIGQUIT, &sa, &saved_sa_quit);
    (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp);

    sudo_setpwent();
    sudo_setgrent();

    /* Initialize environment functions (including replacements). */
    env_init(envp);

    /* Setup defaults data structures. */
    init_defaults();

    /* Parse args, settings and user_info */
    sudo_mode = deserialize_info(args, settings, user_info);

    init_vars(envp);		/* XXX - move this later? */

    /* Parse nsswitch.conf for sudoers order. */
    snl = sudo_read_nss();

    /* LDAP or NSS may modify the euid so we need to be root for the open. */
    set_perms(PERM_INITIAL);
    set_perms(PERM_ROOT);

    /* Open and parse sudoers, set global defaults */
    for (nss = snl->first; nss != NULL; nss = nss_next) {
        nss_next = nss->next;
        if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
            sources++;
            if (nss->setdefs(nss) != 0)
                log_error(NO_STDERR, _("problem with defaults entries"));
        } else {
            tq_remove(snl, nss);
        }
    }
    if (sources == 0) {
	warningx(_("no valid sudoers sources found, quitting"));
	debug_return_bool(-1);
    }

    /* XXX - collect post-sudoers parse settings into a function */

    /*
     * Initialize external group plugin, if any.
     */
    if (def_group_plugin) {
	if (group_plugin_load(def_group_plugin) != true)
	    def_group_plugin = NULL;
    }

    /*
     * Set runas passwd/group entries based on command line or sudoers.
     * Note that if runas_group was specified without runas_user we
     * defer setting runas_pw so the match routines know to ignore it.
     */
    if (runas_group != NULL) {
	set_runasgr(runas_group);
	if (runas_user != NULL)
	    set_runaspw(runas_user);
    } else
	set_runaspw(runas_user ? runas_user : def_runas_default);

    if (!update_defaults(SETDEF_RUNAS))
	log_error(NO_STDERR, _("problem with defaults entries"));

    if (def_fqdn)
	set_fqdn();	/* deferred until after sudoers is parsed */

    /* Set login class if applicable. */
    set_loginclass(runas_pw ? runas_pw : sudo_user.pw);

    restore_perms();

    debug_return_bool(true);
}
Exemplo n.º 26
0
/*
 * Log, audit and mail the denial message, optionally informing the user.
 */
bool
log_denial(int status, bool inform_user)
{
    const char *message;
    char *logline;
    int oldlocale;
    bool uid_changed, ret = true;
    debug_decl(log_denial, SUDOERS_DEBUG_LOGGING)

    /* Handle auditing first (audit_failure() handles the locale itself). */
    if (ISSET(status, FLAG_NO_USER | FLAG_NO_HOST))
	audit_failure(NewArgc, NewArgv, N_("No user or host"));
    else
	audit_failure(NewArgc, NewArgv, N_("validation failure"));

    /* Log and mail messages should be in the sudoers locale. */
    sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);

    /* Set error message. */
    if (ISSET(status, FLAG_NO_USER))
	message = _("user NOT in sudoers");
    else if (ISSET(status, FLAG_NO_HOST))
	message = _("user NOT authorized on host");
    else
	message = _("command not allowed");

    logline = new_logline(message, 0);
    if (logline == NULL)
	debug_return_bool(false);

    /* Become root if we are not already. */
    uid_changed = set_perms(PERM_ROOT);

    if (should_mail(status))
	send_mail("%s", logline);	/* send mail based on status */

    /*
     * Log via syslog and/or a file.
     */
    if (def_syslog)
	do_syslog(def_syslog_badpri, logline);
    if (def_logfile && !do_logfile(logline))
	ret = false;

    if (uid_changed) {
	if (!restore_perms())
	    ret = false;		/* XXX - return -1 instead? */
    }

    free(logline);

    /* Restore locale. */
    sudoers_setlocale(oldlocale, NULL);

    /* Inform the user if they failed to authenticate (in their locale).  */
    if (inform_user) {
	sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);

	if (ISSET(status, FLAG_NO_USER)) {
	    sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not in the sudoers "
		"file.  This incident will be reported.\n"), user_name);
	} else if (ISSET(status, FLAG_NO_HOST)) {
	    sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not allowed to run sudo "
		"on %s.  This incident will be reported.\n"),
		user_name, user_srunhost);
	} else if (ISSET(status, FLAG_NO_CHECK)) {
	    sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s may not run "
		"sudo on %s.\n"), user_name, user_srunhost);
	} else {
	    sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s is not allowed "
		"to execute '%s%s%s' as %s%s%s on %s.\n"),
		user_name, user_cmnd, user_args ? " " : "",
		user_args ? user_args : "",
		list_pw ? list_pw->pw_name : runas_pw ?
		runas_pw->pw_name : user_name, runas_gr ? ":" : "",
		runas_gr ? runas_gr->gr_name : "", user_host);
	}
	sudoers_setlocale(oldlocale, NULL);
    }
    debug_return_bool(ret);
}
Exemplo n.º 27
0
static bool
do_logfile(const char *msg)
{
    static bool warned = false;
    const char *timestr;
    int len, oldlocale;
    bool ret = false;
    char *full_line;
    mode_t oldmask;
    FILE *fp;
    debug_decl(do_logfile, SUDOERS_DEBUG_LOGGING)

    sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);

    oldmask = umask(S_IRWXG|S_IRWXO);
    fp = fopen(def_logfile, "a");
    (void) umask(oldmask);
    if (fp == NULL) {
	if (!warned) {
	    log_warning(SLOG_SEND_MAIL|SLOG_NO_LOG,
		N_("unable to open log file: %s"), def_logfile);
	    warned = true;
	}
	goto done;
    }
    if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
	if (!warned) {
	    log_warning(SLOG_SEND_MAIL|SLOG_NO_LOG,
		N_("unable to lock log file: %s"), def_logfile);
	    warned = true;
	}
	goto done;
    }

    timestr = get_timestr(time(NULL), def_log_year);
    if (timestr == NULL)
	timestr = "invalid date";
    if (def_log_host) {
	len = asprintf(&full_line, "%s : %s : HOST=%s : %s",
	    timestr, user_name, user_srunhost, msg);
    } else {
	len = asprintf(&full_line, "%s : %s : %s",
	    timestr, user_name, msg);
    }
    if (len == -1) {
	sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
	goto done;
    }
    if ((size_t)def_loglinelen < sizeof(LOG_INDENT)) {
	/* Don't pretty-print long log file lines (hard to grep). */
	(void) fputs(full_line, fp);
	(void) fputc('\n', fp);
    } else {
	/* Write line with word wrap around def_loglinelen chars. */
	writeln_wrap(fp, full_line, len, def_loglinelen);
    }
    free(full_line);
    (void) fflush(fp);
    if (ferror(fp)) {
	if (!warned) {
	    log_warning(SLOG_SEND_MAIL|SLOG_NO_LOG,
		N_("unable to write log file: %s"), def_logfile);
	    warned = true;
	}
	goto done;
    }
    ret = true;

done:
    if (fp != NULL)
	(void) fclose(fp);
    sudoers_setlocale(oldlocale, NULL);

    debug_return_bool(ret);
}
static bool
addr_matches_if_netmask(const char *n, const char *m)
{
    unsigned int i;
    union sudo_in_addr_un addr, mask;
    struct interface *ifp;
#ifdef HAVE_STRUCT_IN6_ADDR
    unsigned int j;
#endif
    unsigned int family;
    const char *errstr;
    debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)

#ifdef HAVE_STRUCT_IN6_ADDR
    if (inet_pton(AF_INET6, n, &addr.ip6) == 1)
	family = AF_INET6;
    else
#endif /* HAVE_STRUCT_IN6_ADDR */
    if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
	family = AF_INET;
    } else {
	debug_return_bool(false);
    }

    if (family == AF_INET) {
	if (strchr(m, '.')) {
	    if (inet_pton(AF_INET, m, &mask.ip4) != 1) {
		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
		    "IPv4 netmask %s: %s", m, "invalid value");
		debug_return_bool(false);
	    }
	} else {
	    i = strtonum(m, 0, 32, &errstr);
	    if (errstr != NULL) {
		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
		    "IPv4 netmask %s: %s", m, errstr);
		debug_return_bool(false);
	    }
	    if (i == 0)
		mask.ip4.s_addr = 0;
	    else if (i == 32)
		mask.ip4.s_addr = 0xffffffff;
	    else
		mask.ip4.s_addr = 0xffffffff - (1 << (32 - i)) + 1;
	    mask.ip4.s_addr = htonl(mask.ip4.s_addr);
	}
	addr.ip4.s_addr &= mask.ip4.s_addr;
    }
#ifdef HAVE_STRUCT_IN6_ADDR
    else {
	if (inet_pton(AF_INET6, m, &mask.ip6) != 1) {
	    j = strtonum(m, 0, 128, &errstr);
	    if (errstr != NULL) {
		sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
		    "IPv6 netmask %s: %s", m, errstr);
		debug_return_bool(false);
	    }
	    for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
		if (j < i * 8)
		    mask.ip6.s6_addr[i] = 0;
		else if (i * 8 + 8 <= j)
		    mask.ip6.s6_addr[i] = 0xff;
		else
		    mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
		addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
	    }
	}
    }
Exemplo n.º 29
0
/*
 * Returns true if the user successfully authenticates, false if not
 * or -1 on error.
 */
int
check_user(int validated, int mode)
{
    struct passwd *auth_pw;
    char *timestampdir = NULL;
    char *timestampfile = NULL;
    char *prompt;
    struct stat sb;
    int status, rval = true;
    debug_decl(check_user, SUDO_DEBUG_AUTH)

    /*
     * Init authentication system regardless of whether we need a password.
     * Required for proper PAM session support.
     */
    auth_pw = get_authpw();
    if (sudo_auth_init(auth_pw) == -1) {
	rval = -1;
	goto done;
    }

    /*
     * Don't prompt for the root passwd or if the user is exempt.
     * If the user is not changing uid/gid, no need for a password.
     */
    if (!def_authenticate || user_uid == 0 || user_is_exempt())
	goto done;
    if (user_uid == runas_pw->pw_uid &&
	(!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name))) {
#ifdef HAVE_SELINUX
	if (user_role == NULL && user_type == NULL)
#endif
#ifdef HAVE_PRIV_SET
	if (runas_privs == NULL && runas_limitprivs == NULL)
#endif
	    goto done;
    }

    /* Always need a password when -k was specified with the command. */
    if (ISSET(mode, MODE_IGNORE_TICKET))
	SET(validated, FLAG_CHECK_USER);

    /* Stash the tty's ctime for tty ticket comparison. */
    if (def_tty_tickets && user_ttypath && stat(user_ttypath, &sb) == 0) {
	tty_info.dev = sb.st_dev;
	tty_info.ino = sb.st_ino;
	tty_info.rdev = sb.st_rdev;
	if (tty_is_devpts(user_ttypath))
	    ctim_get(&sb, &tty_info.ctime);
    }

    if (build_timestamp(&timestampdir, &timestampfile) == -1) {
	rval = -1;
	goto done;
    }

    status = timestamp_status(timestampdir, timestampfile, user_name,
	TS_MAKE_DIRS);

    if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
	/* Bail out if we are non-interactive and a password is required */
	if (ISSET(mode, MODE_NONINTERACTIVE)) {
	    validated |= FLAG_NON_INTERACTIVE;
	    log_auth_failure(validated, 0);
	    rval = -1;
	    goto done;
	}

	/* XXX - should not lecture if askpass helper is being used. */
	lecture(status);

	/* Expand any escapes in the prompt. */
	prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
	    user_name, user_shost);

	rval = verify_user(auth_pw, prompt, validated);
    }
    /* Only update timestamp if user was validated. */
    if (rval == true && ISSET(validated, VALIDATE_OK) &&
	!ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
	update_timestamp(timestampdir, timestampfile);
    efree(timestampdir);
    efree(timestampfile);

done:
    sudo_auth_cleanup(auth_pw);
    sudo_pw_delref(auth_pw);

    debug_return_bool(rval);
}
Exemplo n.º 30
0
/*
 * Returns true if there are no aliases, else false.
 */
bool
no_aliases(void)
{
    debug_decl(no_aliases, SUDOERS_DEBUG_ALIAS)
    debug_return_bool(rbisempty(aliases));
}