/*- * Copyright (c) 2013 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include /* Mostly stolen from libpam's pam_unix.c */ #define SALTSIZE 32 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static void to64(char *s, long v, int n) { while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; } } /* Salt suitable for traditional DES and MD5 */ static void makesalt(char salt[SALTSIZE + 1]) { int i; /* These are not really random numbers, they are just * numbers that change to thwart construction of a * dictionary. */ for (i = 0; i < SALTSIZE; i += 4) to64(&salt[i], arc4random(), 4); salt[SALTSIZE] = '\0'; } /* End of the stolen code */ static void usage(const char *prog) { printf("Usage: %s [format]\n", basename(prog)); } static char * read_password(const char *prompt) { char *passwd; passwd = strdup(getpass(prompt)); if (passwd == NULL) errx(EX_OSERR, "out of memory"); return (passwd); } int main(int argc, char *argv[]) { char salt[SALTSIZE + 1]; char *passwd[2]; const char *opt, *prog; prog = argv[0]; if (argc < 1 || argc > 2) { usage(prog); exit(EX_USAGE); } if (argc == 2) { opt = argv[1]; if (strcmp(opt, "-h") == 0 || strcmp(opt, "help") == 0) { usage(prog); return (EX_OK); } if (crypt_set_format(opt) == 0) errx(EX_DATAERR, "invalid crypto %s", opt); } else opt = crypt_get_format(); printf("Generating password hash in %s format.\n", opt); for (;;) { passwd[0] = read_password("\nType password: "); passwd[1] = read_password("Re-type password: "); if (strcmp(passwd[0], passwd[1]) == 0) { free(passwd[1]); break; } free(passwd[0]); free(passwd[1]); printf("\nPasswords do not match. Please try again.\n"); } makesalt(salt); passwd[1] = crypt(passwd[0], salt); printf("\n%s\n", passwd[1]); free(passwd[0]); return (EX_OK); }