Annotation of embedaddon/sudo/plugins/sudoers/check.c, revision 1.1.1.5

1.1       misho       1: /*
1.1.1.4   misho       2:  * Copyright (c) 1993-1996,1998-2005, 2007-2013
1.1       misho       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: #if 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"
1.1.1.4   misho      53: #include "check.h"
1.1       misho      54: 
1.1.1.4   misho      55: static bool display_lecture(int);
                     56: static struct passwd *get_authpw(void);
1.1       misho      57: 
                     58: /*
1.1.1.4   misho      59:  * Returns true if the user successfully authenticates, false if not
                     60:  * or -1 on error.
1.1       misho      61:  */
1.1.1.4   misho      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:            user_name, user_shost);
                     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: }
1.1       misho     110: 
                    111: /*
1.1.1.3   misho     112:  * Returns true if the user successfully authenticates, false if not
                    113:  * or -1 on error.
1.1       misho     114:  */
                    115: int
                    116: check_user(int validated, int mode)
                    117: {
                    118:     struct passwd *auth_pw;
1.1.1.4   misho     119:     int rval = true;
1.1.1.2   misho     120:     debug_decl(check_user, SUDO_DEBUG_AUTH)
1.1       misho     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();
                    127:     if (sudo_auth_init(auth_pw) == -1) {
                    128:        rval = -1;
                    129:        goto done;
                    130:     }
                    131: 
1.1.1.3   misho     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:      */
1.1.1.5 ! misho     136:     if (!def_authenticate || user_is_exempt())
1.1       misho     137:        goto done;
1.1.1.5 ! misho     138:     if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
        !           139:        (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name)))) {
1.1.1.3   misho     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: 
1.1.1.4   misho     149:     rval = check_user_interactive(validated, mode, auth_pw);
1.1       misho     150: 
                    151: done:
                    152:     sudo_auth_cleanup(auth_pw);
1.1.1.3   misho     153:     sudo_pw_delref(auth_pw);
1.1       misho     154: 
1.1.1.2   misho     155:     debug_return_bool(rval);
1.1       misho     156: }
                    157: 
                    158: /*
1.1.1.4   misho     159:  * Display sudo lecture (standard or custom).
                    160:  * Returns true if the user was lectured, else false.
1.1       misho     161:  */
1.1.1.4   misho     162: static bool
                    163: display_lecture(int status)
1.1       misho     164: {
                    165:     FILE *fp;
                    166:     char buf[BUFSIZ];
                    167:     ssize_t nread;
                    168:     struct sudo_conv_message msg;
                    169:     struct sudo_conv_reply repl;
1.1.1.2   misho     170:     debug_decl(lecture, SUDO_DEBUG_AUTH)
1.1       misho     171: 
                    172:     if (def_lecture == never ||
1.1.1.4   misho     173:        (def_lecture == once && already_lectured(status)))
                    174:        debug_return_bool(false);
1.1       misho     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) {
1.1.1.2   misho     181:            buf[nread] = '\0';
1.1       misho     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;
1.1.1.4   misho     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");
1.1       misho     195:        sudo_conv(1, &msg, &repl);
                    196:     }
1.1.1.4   misho     197:     debug_return_bool(true);
1.1       misho     198: }
                    199: 
                    200: /*
                    201:  * Checks if the user is exempt from supplying a password.
                    202:  */
1.1.1.2   misho     203: bool
1.1       misho     204: user_is_exempt(void)
                    205: {
1.1.1.2   misho     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);
1.1       misho     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(void)
                    221: {
                    222:     struct passwd *pw;
1.1.1.2   misho     223:     debug_decl(get_authpw, SUDO_DEBUG_AUTH)
1.1       misho     224: 
                    225:     if (def_rootpw) {
                    226:        if ((pw = sudo_getpwuid(ROOT_UID)) == NULL)
1.1.1.4   misho     227:            log_fatal(0, N_("unknown uid: %u"), ROOT_UID);
1.1       misho     228:     } else if (def_runaspw) {
                    229:        if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
1.1.1.4   misho     230:            log_fatal(0, N_("unknown user: %s"), def_runas_default);
1.1       misho     231:     } else if (def_targetpw) {
                    232:        if (runas_pw->pw_name == NULL)
1.1.1.4   misho     233:            log_fatal(NO_MAIL|MSG_ONLY, N_("unknown uid: %u"),
1.1       misho     234:                (unsigned int) runas_pw->pw_uid);
1.1.1.3   misho     235:        sudo_pw_addref(runas_pw);
1.1       misho     236:        pw = runas_pw;
                    237:     } else {
1.1.1.3   misho     238:        sudo_pw_addref(sudo_user.pw);
1.1       misho     239:        pw = sudo_user.pw;
                    240:     }
                    241: 
1.1.1.2   misho     242:     debug_return_ptr(pw);
1.1       misho     243: }

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