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

Annotation of src/usr.bin/htpasswd/htpasswd.c, Revision 1.1

1.1     ! florian     1: /*     $OpenBSD$ */
        !             2: /*
        !             3:  * Copyright (c) 2014 Florian Obser <florian@openbsd.org>
        !             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:
        !            18: #include <sys/stat.h>
        !            19:
        !            20: #include <err.h>
        !            21: #include <errno.h>
        !            22: #include <limits.h>
        !            23: #include <pwd.h>
        !            24: #include <readpassphrase.h>
        !            25: #include <stdio.h>
        !            26: #include <stdlib.h>
        !            27: #include <string.h>
        !            28: #include <unistd.h>
        !            29:
        !            30: __dead void    usage(void);
        !            31: void           nag(char*);
        !            32:
        !            33: extern char *__progname;
        !            34:
        !            35: __dead void
        !            36: usage(void)
        !            37: {
        !            38:        fprintf(stderr, "usage:\t%s [file] login\n", __progname);
        !            39:        exit(1);
        !            40: }
        !            41:
        !            42: int
        !            43: main(int argc, char** argv)
        !            44: {
        !            45:        FILE *in, *out;
        !            46:        size_t linesize;
        !            47:        ssize_t linelen;
        !            48:        int fd, loginlen;
        !            49:        char hash[_PASSWORD_LEN], *file, *line, *login, pass[1024], pass2[1024];
        !            50:        char salt[_PASSWORD_LEN], tmpl[sizeof("/tmp/htpasswd-XXXXXXXXXX")];
        !            51:
        !            52:        file = NULL;
        !            53:        login = NULL;
        !            54:        in = NULL;
        !            55:        out = NULL;
        !            56:        line = NULL;
        !            57:        linesize = 0;
        !            58:
        !            59:        switch (argc) {
        !            60:        case 2:
        !            61:                if ((loginlen = asprintf(&login, "%s:", argv[1])) == -1)
        !            62:                        err(1, "asprintf");
        !            63:                break;
        !            64:        case 3:
        !            65:                file = argv[1];
        !            66:                if ((loginlen = asprintf(&login, "%s:", argv[2])) == -1)
        !            67:                        err(1, "asprintf");
        !            68:                break;
        !            69:        default:
        !            70:                usage();
        !            71:                /* NOT REACHED */
        !            72:                break;
        !            73:        }
        !            74:
        !            75:        if (!readpassphrase("Password: ", pass, sizeof(pass), RPP_ECHO_OFF))
        !            76:                err(1, "unable to read password");
        !            77:        if (!readpassphrase("Retype Password: ", pass2, sizeof(pass2),
        !            78:            RPP_ECHO_OFF)) {
        !            79:                explicit_bzero(pass, sizeof(pass));
        !            80:                err(1, "unable to read password");
        !            81:        }
        !            82:        if (strcmp(pass, pass2) != 0) {
        !            83:                explicit_bzero(pass, sizeof(pass));
        !            84:                explicit_bzero(pass2, sizeof(pass2));
        !            85:                errx(1, "passwords don't match");
        !            86:        }
        !            87:
        !            88:        explicit_bzero(pass2, sizeof(pass2));
        !            89:        if (strlcpy(salt, bcrypt_gensalt(8), sizeof(salt)) >= sizeof(salt))
        !            90:                err(1, "salt too long");
        !            91:        if (strlcpy(hash, bcrypt(pass, salt), sizeof(hash)) >= sizeof(hash))
        !            92:                err(1, "hash too long");
        !            93:        explicit_bzero(pass, sizeof(pass));
        !            94:
        !            95:        if (file == NULL)
        !            96:                printf("%s%s\n", login, hash);
        !            97:        else {
        !            98:                if ((in = fopen(file, "r+")) == NULL) {
        !            99:                        if (errno == ENOENT) {
        !           100:                                if ((out = fopen(file, "w")) == NULL)
        !           101:                                        err(1, "cannot open password file for"
        !           102:                                            " reading or writing");
        !           103:                                if (fchmod(fileno(out), S_IRUSR | S_IWUSR)
        !           104:                                    == -1)
        !           105:                                        err(1, "cannot chmod new password"
        !           106:                                            " file");
        !           107:                        } else
        !           108:                                err(1, "cannot open password file for reading");
        !           109:                }
        !           110:                /* file already exits, copy content and filter login out */
        !           111:                if (out == NULL) {
        !           112:                        strlcpy(tmpl, "/tmp/htpasswd-XXXXXXXXXX", sizeof(tmpl));
        !           113:                        if ((fd = mkstemp(tmpl)) == -1)
        !           114:                                err(1, "mkstemp");
        !           115:
        !           116:                        if ((out = fdopen(fd, "w+")) == NULL)
        !           117:                                err(1, "cannot open tempfile");
        !           118:
        !           119:                        while ((linelen = getline(&line, &linesize, in))
        !           120:                            != -1) {
        !           121:                                if (strncmp(line, login, loginlen) != 0) {
        !           122:                                        if (fprintf(out, "%s", line) == -1)
        !           123:                                                err(1, "cannot write to temp "
        !           124:                                                    "file");
        !           125:                                        nag(line);
        !           126:                                }
        !           127:                        }
        !           128:                }
        !           129:                if (fprintf(out, "%s%s\n", login, hash) == -1)
        !           130:                        err(1, "cannot write new password hash");
        !           131:
        !           132:                /* file already exists, overwrite it */
        !           133:                if (in != NULL) {
        !           134:                        if (fseek(in, 0, SEEK_SET) == -1)
        !           135:                                err(1, "cannot seek in password file");
        !           136:                        if (ftruncate(fileno(in), 0) == -1)
        !           137:                                err(1, "cannot truncate password file");
        !           138:                        if (fseek(out, 0, SEEK_SET) == -1)
        !           139:                                err(1, "cannot seek in temp file");
        !           140:                        while ((linelen = getline(&line, &linesize, out))
        !           141:                            != -1)
        !           142:                                if (fprintf(in, "%s", line) == -1)
        !           143:                                        err(1, "cannot write to password file");
        !           144:                        if (fclose(in) == EOF)
        !           145:                                err(1, "cannot close password file");
        !           146:                }
        !           147:                if (fclose(out) == EOF) {
        !           148:                        if (in != NULL)
        !           149:                                err(1, "cannot close temp file");
        !           150:                        else
        !           151:                                err(1, "cannot close password file");
        !           152:                }
        !           153:                if (in != NULL && unlink(tmpl) == -1)
        !           154:                        err(1, "cannot delete temp file (%s)", tmpl);
        !           155:        }
        !           156:        exit(0);
        !           157: }
        !           158:
        !           159: void
        !           160: nag(char* line)
        !           161: {
        !           162:        char *tok;
        !           163:        if (strtok(line, ":") != NULL)
        !           164:                if ((tok = strtok(NULL, ":")) != NULL)
        !           165:                        if (strncmp(tok, "$2a$", 4) != 0 &&
        !           166:                             strncmp(tok, "$2b$", 4) != 0)
        !           167:                                fprintf(stderr, "%s doesn't use bcrypt."
        !           168:                                    " Update the password.\n", line);
        !           169: }