File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / check.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years, 3 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    1: /*
    2:  * Copyright (c) 1993-1996,1998-2005, 2007-2013
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  *
   17:  * Sponsored in part by the Defense Advanced Research Projects
   18:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   19:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   20:  */
   21: 
   22: #include <config.h>
   23: 
   24: #include <sys/types.h>
   25: #include <sys/time.h>
   26: #include <stdio.h>
   27: #ifdef STDC_HEADERS
   28: # include <stdlib.h>
   29: # include <stddef.h>
   30: #else
   31: # ifdef HAVE_STDLIB_H
   32: #  include <stdlib.h>
   33: # endif
   34: #endif /* STDC_HEADERS */
   35: #ifdef HAVE_STRING_H
   36: # include <string.h>
   37: #endif /* HAVE_STRING_H */
   38: #ifdef HAVE_STRINGS_H
   39: # include <strings.h>
   40: #endif /* HAVE_STRINGS_H */
   41: #ifdef HAVE_UNISTD_H
   42: # include <unistd.h>
   43: #endif /* HAVE_UNISTD_H */
   44: #ifdef TIME_WITH_SYS_TIME
   45: # include <time.h>
   46: #endif
   47: #include <errno.h>
   48: #include <fcntl.h>
   49: #include <pwd.h>
   50: #include <grp.h>
   51: 
   52: #include "sudoers.h"
   53: #include "check.h"
   54: 
   55: static bool display_lecture(int);
   56: static struct passwd *get_authpw(int);
   57: 
   58: /*
   59:  * Returns true if the user successfully authenticates, false if not
   60:  * or -1 on error.
   61:  */
   62: static int
   63: check_user_interactive(int validated, int mode, struct passwd *auth_pw)
   64: {
   65:     int status, rval = true;
   66:     debug_decl(check_user_interactive, SUDO_DEBUG_AUTH)
   67: 
   68:     /* Always need a password when -k was specified with the command. */
   69:     if (ISSET(mode, MODE_IGNORE_TICKET))
   70: 	SET(validated, FLAG_CHECK_USER);
   71: 
   72:     if (build_timestamp(auth_pw) == -1) {
   73: 	rval = -1;
   74: 	goto done;
   75:     }
   76: 
   77:     status = timestamp_status(auth_pw);
   78: 
   79:     if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
   80: 	char *prompt;
   81: 	bool lectured;
   82: 
   83: 	/* Bail out if we are non-interactive and a password is required */
   84: 	if (ISSET(mode, MODE_NONINTERACTIVE)) {
   85: 	    validated |= FLAG_NON_INTERACTIVE;
   86: 	    log_auth_failure(validated, 0);
   87: 	    rval = -1;
   88: 	    goto done;
   89: 	}
   90: 
   91: 	/* XXX - should not lecture if askpass helper is being used. */
   92: 	lectured = display_lecture(status);
   93: 
   94: 	/* Expand any escapes in the prompt. */
   95: 	prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
   96: 	    auth_pw->pw_name);
   97: 
   98: 	rval = verify_user(auth_pw, prompt, validated);
   99: 	if (rval == true && lectured)
  100: 	    set_lectured();
  101: 	efree(prompt);
  102:     }
  103:     /* Only update timestamp if user was validated. */
  104:     if (rval == true && ISSET(validated, VALIDATE_OK) &&
  105: 	!ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
  106: 	update_timestamp(auth_pw);
  107: done:
  108:     debug_return_bool(rval);
  109: }
  110: 
  111: /*
  112:  * Returns true if the user successfully authenticates, false if not
  113:  * or -1 on error.
  114:  */
  115: int
  116: check_user(int validated, int mode)
  117: {
  118:     struct passwd *auth_pw;
  119:     int rval = true;
  120:     debug_decl(check_user, SUDO_DEBUG_AUTH)
  121: 
  122:     /*
  123:      * Init authentication system regardless of whether we need a password.
  124:      * Required for proper PAM session support.
  125:      */
  126:     auth_pw = get_authpw(mode);
  127:     if (sudo_auth_init(auth_pw) == -1) {
  128: 	rval = -1;
  129: 	goto done;
  130:     }
  131: 
  132:     /*
  133:      * Don't prompt for the root passwd or if the user is exempt.
  134:      * If the user is not changing uid/gid, no need for a password.
  135:      */
  136:     if (!def_authenticate || user_is_exempt())
  137: 	goto done;
  138:     if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
  139: 	(!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name)))) {
  140: #ifdef HAVE_SELINUX
  141: 	if (user_role == NULL && user_type == NULL)
  142: #endif
  143: #ifdef HAVE_PRIV_SET
  144: 	if (runas_privs == NULL && runas_limitprivs == NULL)
  145: #endif
  146: 	    goto done;
  147:     }
  148: 
  149:     rval = check_user_interactive(validated, mode, auth_pw);
  150: 
  151: done:
  152:     sudo_auth_cleanup(auth_pw);
  153:     sudo_pw_delref(auth_pw);
  154: 
  155:     debug_return_bool(rval);
  156: }
  157: 
  158: /*
  159:  * Display sudo lecture (standard or custom).
  160:  * Returns true if the user was lectured, else false.
  161:  */
  162: static bool
  163: display_lecture(int status)
  164: {
  165:     FILE *fp;
  166:     char buf[BUFSIZ];
  167:     ssize_t nread;
  168:     struct sudo_conv_message msg;
  169:     struct sudo_conv_reply repl;
  170:     debug_decl(lecture, SUDO_DEBUG_AUTH)
  171: 
  172:     if (def_lecture == never ||
  173: 	(def_lecture == once && already_lectured(status)))
  174: 	debug_return_bool(false);
  175: 
  176:     memset(&msg, 0, sizeof(msg));
  177:     memset(&repl, 0, sizeof(repl));
  178: 
  179:     if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) {
  180: 	while ((nread = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) != 0) {
  181: 	    buf[nread] = '\0';
  182: 	    msg.msg_type = SUDO_CONV_ERROR_MSG;
  183: 	    msg.msg = buf;
  184: 	    sudo_conv(1, &msg, &repl);
  185: 	}
  186: 	fclose(fp);
  187:     } else {
  188: 	msg.msg_type = SUDO_CONV_ERROR_MSG;
  189: 	msg.msg = _("\n"
  190: 	    "We trust you have received the usual lecture from the local System\n"
  191: 	    "Administrator. It usually boils down to these three things:\n\n"
  192: 	    "    #1) Respect the privacy of others.\n"
  193: 	    "    #2) Think before you type.\n"
  194: 	    "    #3) With great power comes great responsibility.\n\n");
  195: 	sudo_conv(1, &msg, &repl);
  196:     }
  197:     debug_return_bool(true);
  198: }
  199: 
  200: /*
  201:  * Checks if the user is exempt from supplying a password.
  202:  */
  203: bool
  204: user_is_exempt(void)
  205: {
  206:     bool rval = false;
  207:     debug_decl(user_is_exempt, SUDO_DEBUG_AUTH)
  208: 
  209:     if (def_exempt_group)
  210: 	rval = user_in_group(sudo_user.pw, def_exempt_group);
  211:     debug_return_bool(rval);
  212: }
  213: 
  214: /*
  215:  * Get passwd entry for the user we are going to authenticate as.
  216:  * By default, this is the user invoking sudo.  In the most common
  217:  * case, this matches sudo_user.pw or runas_pw.
  218:  */
  219: static struct passwd *
  220: get_authpw(int mode)
  221: {
  222:     struct passwd *pw;
  223:     debug_decl(get_authpw, SUDO_DEBUG_AUTH)
  224: 
  225:     if (ISSET(mode, (MODE_CHECK|MODE_LIST))) {
  226: 	/* In list mode we always prompt for the user's password. */
  227: 	sudo_pw_addref(sudo_user.pw);
  228: 	pw = sudo_user.pw;
  229:     } else {
  230: 	if (def_rootpw) {
  231: 	    if ((pw = sudo_getpwuid(ROOT_UID)) == NULL)
  232: 		log_fatal(0, N_("unknown uid: %u"), ROOT_UID);
  233: 	} else if (def_runaspw) {
  234: 	    if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
  235: 		log_fatal(0, N_("unknown user: %s"), def_runas_default);
  236: 	} else if (def_targetpw) {
  237: 	    if (runas_pw->pw_name == NULL)
  238: 		log_fatal(NO_MAIL|MSG_ONLY, N_("unknown uid: %u"),
  239: 		    (unsigned int) runas_pw->pw_uid);
  240: 	    sudo_pw_addref(runas_pw);
  241: 	    pw = runas_pw;
  242: 	} else {
  243: 	    sudo_pw_addref(sudo_user.pw);
  244: 	    pw = sudo_user.pw;
  245: 	}
  246:     }
  247: 
  248:     debug_return_ptr(pw);
  249: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>