Beispiel #1
0
void
log_error(int flags, const char *fmt, ...)
{
    int serrno = errno;
    char *message;
    char *logline;
    va_list ap;

    /* Expand printf-style format + args. */
    va_start(ap, fmt);
    evasprintf(&message, fmt, ap);
    va_end(ap);

    /* Become root if we are not already to avoid user interference */
    set_perms(PERM_ROOT|PERM_NOEXIT);

    if (ISSET(flags, MSG_ONLY))
	logline = message;
    else
	logline = new_logline(message, ISSET(flags, USE_ERRNO) ? serrno : 0);

    /*
     * Tell the user.
     */
    if (!ISSET(flags, NO_STDERR)) {
	if (ISSET(flags, USE_ERRNO))
	    warning("%s", message);
	else
	    warningx("%s", message);
    }
    if (logline != message)
        efree(message);

    /*
     * Send a copy of the error via mail.
     */
    if (!ISSET(flags, NO_MAIL))
	send_mail("%s", logline);

    /*
     * Log to syslog and/or a file.
     */
    if (def_syslog)
	do_syslog(def_syslog_badpri, logline);
    if (def_logfile)
	do_logfile(logline);

    efree(logline);

    restore_perms();

    if (!ISSET(flags, NO_EXIT)) {
	plugin_cleanup(0);
	siglongjmp(error_jmp, 1);
    }
}
Beispiel #2
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);
}
Beispiel #3
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);
}
Beispiel #4
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[])
{
    volatile int sources = 0;
    sigaction_t sa;
    struct sudo_nss *nss;

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

    if (sigsetjmp(error_jmp, 1)) {
	/* called via error(), errorx() or log_error() */
	rewind_perms();
	return -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 settings and user_info */
    sudo_mode = deserialize_info(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 */
    tq_foreach_fwd(snl, nss) {
	if (nss->open(nss) == 0 && nss->parse(nss) == 0) {
	    sources++;
	    if (nss->setdefs(nss) != 0)
		log_error(NO_STDERR|NO_EXIT, _("problem with defaults entries"));
	}
    }
    if (sources == 0) {
	warningx(_("no valid sudoers sources found, quitting"));
	return -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|NO_EXIT, _("problem with defaults entries"));

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

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

    restore_perms();

    return TRUE;
}
Beispiel #5
0
int
verify_user(struct passwd *pw, char *prompt)
{
    int counter = def_passwd_tries + 1;
    int success = AUTH_FAILURE;
    int flags, status, standalone, rval;
    char *p;
    sudo_auth *auth;
    sigaction_t sa, osa;

    /* Enable suspend during password entry. */
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = SIG_DFL;
    (void) sigaction(SIGTSTP, &sa, &osa);

    /* Make sure we have at least one auth method. */
    if (auth_switch[0].name == NULL) {
	audit_failure(NewArgv, "no authentication methods");
    	log_error(0,
	    _("There are no authentication methods compiled into sudo!  "
	    "If you want to turn off authentication, use the "
	    "--disable-authentication configure option."));
	return -1;
    }

    /* Make sure we haven't mixed standalone and shared auth methods. */
    standalone = IS_STANDALONE(&auth_switch[0]);
    if (standalone && auth_switch[1].name != NULL) {
	audit_failure(NewArgv, "invalid authentication methods");
    	log_error(0, _("Invalid authentication methods compiled into sudo!  "
	    "You may mix standalone and non-standalone authentication."));
	return -1;
    }

    /* Set FLAG_ONEANDONLY if there is only one auth method. */
    if (auth_switch[1].name == NULL)
	SET(auth_switch[0].flags, FLAG_ONEANDONLY);

    /* Initialize auth methods and unconfigure the method if necessary. */
    for (auth = auth_switch; auth->name; auth++) {
	if (auth->init && !IS_DISABLED(auth)) {
	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    status = (auth->init)(pw, &prompt, auth);
	    if (status == AUTH_FAILURE)
		SET(auth->flags, FLAG_DISABLED);
	    else if (status == AUTH_FATAL) {	/* XXX log */
		audit_failure(NewArgv, "authentication failure");
		return -1;		/* assume error msg already printed */
	    }

	    if (NEEDS_USER(auth))
		restore_perms();
	}
    }

    while (--counter) {
	/* Do any per-method setup and unconfigure the method if needed */
	for (auth = auth_switch; auth->name; auth++) {
	    if (auth->setup && !IS_DISABLED(auth)) {
		if (NEEDS_USER(auth))
		    set_perms(PERM_USER);

		status = (auth->setup)(pw, &prompt, auth);
		if (status == AUTH_FAILURE)
		    SET(auth->flags, FLAG_DISABLED);
		else if (status == AUTH_FATAL) {/* XXX log */
		    audit_failure(NewArgv, "authentication failure");
		    return -1;		/* assume error msg already printed */
		}

		if (NEEDS_USER(auth))
		    restore_perms();
	    }
	}

	/* Get the password unless the auth function will do it for us */
	if (standalone) {
	    p = prompt;
	} else {
	    p = auth_getpass(prompt, def_passwd_timeout * 60,
		SUDO_CONV_PROMPT_ECHO_OFF);
	    if (p == NULL)
		break;
	}

	/* Call authentication functions. */
	for (auth = auth_switch; auth->name; auth++) {
	    if (IS_DISABLED(auth))
		continue;

	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    success = auth->status = (auth->verify)(pw, p, auth);

	    if (NEEDS_USER(auth))
		restore_perms();

	    if (auth->status != AUTH_FAILURE)
		goto cleanup;
	}
	if (!standalone)
	    zero_bytes(p, strlen(p));
	pass_warn();
    }

cleanup:
    /* Call cleanup routines. */
    for (auth = auth_switch; auth->name; auth++) {
	if (auth->cleanup && !IS_DISABLED(auth)) {
	    if (NEEDS_USER(auth))
		set_perms(PERM_USER);

	    status = (auth->cleanup)(pw, auth);
	    if (status == AUTH_FATAL) {	/* XXX log */
		audit_failure(NewArgv, "authentication failure");
		return -1;		/* assume error msg already printed */
	    }

	    if (NEEDS_USER(auth))
		restore_perms();
	}
    }

    switch (success) {
	case AUTH_SUCCESS:
	    (void) sigaction(SIGTSTP, &osa, NULL);
	    rval = TRUE;
	    break;
	case AUTH_INTR:
	case AUTH_FAILURE:
	    if (counter != def_passwd_tries) {
		if (def_mail_badpass || def_mail_always)
		    flags = 0;
		else
		    flags = NO_MAIL;
		log_error(flags, ngettext("%d incorrect password attempt",
		    "%d incorrect password attempts",
		    def_passwd_tries - counter), def_passwd_tries - counter);
	    }
	    audit_failure(NewArgv, "authentication failure");
	    rval = FALSE;
	    break;
	case AUTH_FATAL:
	default:
	    audit_failure(NewArgv, "authentication failure");
	    rval = -1;
	    break;
    }

    return rval;
}