[BACK]Return to pwd_check.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / passwd

Annotation of src/usr.bin/passwd/pwd_check.c, Revision 1.10

1.10    ! moritz      1: /*     $OpenBSD: pwd_check.c,v 1.9 2004/07/13 21:29:12 millert Exp $   */
1.9       millert     2:
1.1       provos      3: /*
                      4:  * Copyright 2000 Niels Provos <provos@citi.umich.edu>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed by Niels Provos.
                     18:  * 4. The name of the author may not be used to endorse or promote products
                     19:  *    derived from this software without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/types.h>
                     34: #include <sys/wait.h>
1.2       millert    35:
                     36: #include <stdio.h>
1.1       provos     37: #include <stdlib.h>
1.2       millert    38: #include <string.h>
1.1       provos     39: #include <unistd.h>
                     40: #include <limits.h>
1.2       millert    41: #include <errno.h>
1.3       millert    42: #include <err.h>
1.1       provos     43: #include <regex.h>
                     44: #include <grp.h>
                     45: #include <paths.h>
1.4       millert    46: #include <login_cap.h>
1.1       provos     47:
                     48: struct pattern {
                     49:        char *match;
                     50:        int flags;
                     51:        char *response;
                     52: };
                     53:
                     54: struct pattern patterns[] = {
                     55:        {
1.6       deraadt    56:                "^[0-9]*$",
1.1       provos     57:                REG_EXTENDED|REG_NOSUB,
                     58:                "Please don't use all-digit passwords."
                     59:        },
                     60:        {
                     61:                "^[a-z]{1,9}$",
                     62:                REG_EXTENDED|REG_NOSUB,
                     63:                "Please don't use an all-lower case password."
                     64:        },
                     65:        {
                     66:                "^[a-z]{1,6}[0-9]+$",
                     67:                REG_EXTENDED|REG_NOSUB|REG_ICASE,
                     68:                "Please use a more complicated password."
                     69:        },
                     70:        {
                     71:                "^([a-z][0-9]){1,4}$",
                     72:                REG_EXTENDED|REG_NOSUB|REG_ICASE,
                     73:                "Please use a more complicated password."
                     74:        },
                     75:        {
                     76:                "^([0-9][a-z]){1,4}$",
                     77:                REG_EXTENDED|REG_NOSUB|REG_ICASE,
                     78:                "Please use a more complicated password."
                     79:        }
                     80: };
                     81:
                     82: int
1.8       millert    83: pwd_check(login_cap_t *lc, char *password)
1.1       provos     84: {
                     85:        regex_t rgx;
1.4       millert    86:        int i, res, min_len;
1.9       millert    87:        char *checker;
1.1       provos     88:        int pipefds[2];
1.7       tedu       89:        pid_t child;
1.6       deraadt    90:
1.9       millert    91:        min_len = (int)login_getcapnum(lc, "minpasswordlen", 6, 6);
1.4       millert    92:        if (min_len > 0 && strlen(password) < min_len) {
1.1       provos     93:                printf("Please enter a longer password.\n");
                     94:                return (0);
                     95:        }
                     96:
1.9       millert    97:        for (i = 0; i < sizeof(patterns) / sizeof(struct pattern); i++) {
1.1       provos     98:                if (regcomp(&rgx, patterns[i].match, patterns[i].flags) != 0)
                     99:                        continue;
                    100:                res = regexec(&rgx, password, 0, NULL, 0);
                    101:                regfree(&rgx);
                    102:                if (!res) {
                    103:                        printf("%s\nUnusual capitalization, control characters or digits are suggested.\n", patterns[i].response);
                    104:                        return (0);
                    105:                }
                    106:        }
                    107:
1.9       millert   108:        /* If no external checker is specified, just accept the password */
                    109:        checker = login_getcapstr(lc, "passwordcheck", NULL, NULL);
                    110:        if (checker == NULL)
1.1       provos    111:                return (1);
                    112:
1.8       millert   113:        /* Okay, now pass control to an external program */
1.1       provos    114:        if (pipe(pipefds) == -1) {
                    115:                warn("pipe");
                    116:                goto out;
                    117:        }
                    118:
1.7       tedu      119:        child = fork();
                    120:        if (child == 0) {
1.1       provos    121:                char *argp[] = { "sh", "-c", NULL, NULL};
1.6       deraadt   122:
1.1       provos    123:                /* Drop privileges */
                    124:                seteuid(getuid());
                    125:                setuid(getuid());
                    126:
                    127:                if (dup2(pipefds[0], STDIN_FILENO) == -1)
                    128:                        exit(1);
                    129:
                    130:                close(pipefds[0]);
                    131:                close(pipefds[1]);
                    132:
1.9       millert   133:                argp[2] = checker;
1.1       provos    134:                if (execv(_PATH_BSHELL, argp) == -1)
                    135:                        exit(1);
                    136:                /* NOT REACHED */
1.7       tedu      137:        } else if (child == -1) {
1.1       provos    138:                warn("fork");
                    139:                goto out;
                    140:        }
                    141:        close(pipefds[0]);
                    142:
                    143:        /* Send the password to STDIN of child */
                    144:        write(pipefds[1], password, strlen(password) + 1);
                    145:        close(pipefds[1]);
                    146:
                    147:        /* get the return value from the child */
1.7       tedu      148:        wait(&child);
1.9       millert   149:        if (WIFEXITED(child) && WEXITSTATUS(child) == 0) {
                    150:                free(checker);
1.1       provos    151:                return (1);
1.9       millert   152:        }
1.1       provos    153:
                    154:  out:
1.9       millert   155:        free(checker);
1.6       deraadt   156:        printf("Please use a different password. Unusual capitalization,\n");
                    157:        printf("control characters, or digits are suggested.\n");
1.1       provos    158:        return (0);
                    159: }
                    160:
1.6       deraadt   161: int
1.8       millert   162: pwd_gettries(login_cap_t *lc)
1.4       millert   163: {
                    164:        quad_t ntries;
                    165:
                    166:        if ((ntries = login_getcapnum(lc, "passwordtries", -1, -1)) != -1) {
1.10    ! moritz    167:                if (ntries >= 0 && ntries <= INT_MAX)
1.9       millert   168:                        return((int)ntries);
                    169:                fprintf(stderr,
                    170:                    "Warning: pwdtries out of range in /etc/login.conf");
1.4       millert   171:        }
1.1       provos    172:
1.8       millert   173:        /*
1.9       millert   174:         * If no amount of tries is specified, return a default of 3,
                    175:         * meaning that after 3 attempts where the user is foiled by the
                    176:         * password checks, it will no longer be checked and they can set
                    177:         * it to whatever they like.  This is the historic BSD behavior.
1.1       provos    178:         */
1.9       millert   179:        return (3);
1.1       provos    180: }