X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/212380e3f42f585dc1ea927402252eb943f91f7b..d09c55338feb5627da978058432a15dccec16907:/tools/mkpasswd.c diff --git a/tools/mkpasswd.c b/tools/mkpasswd.c index 6c1fed3d..8b8c96c1 100644 --- a/tools/mkpasswd.c +++ b/tools/mkpasswd.c @@ -1,364 +1,441 @@ /* simple password generator by Nelson Minar (minar@reed.edu) -** copyright 1991, all rights reserved. -** You can use this code as long as my name stays with it. -** -** md5 patch by W. Campbell -** Modernization, getopt, etc for the Hybrid IRCD team -** by W. Campbell -** -** /dev/random for salt generation added by -** Aaron Sethman -** -** $Id: mkpasswd.c 6 2005-09-10 01:02:21Z nenolod $ -*/ + * copyright 1991, all rights reserved. + * You can use this code as long as my name stays with it. + * + * md5 patch by W. Campbell + * Modernization, getopt, etc for the Hybrid IRCD team + * by W. Campbell + * + * /dev/random for salt generation added by + * Aaron Sethman + */ #include #include #include #include #include #include +#include "rb_lib.h" +#ifndef __MINGW32__ +#include +#endif + +#define FLAG_MD5 0x00000001 +#define FLAG_SALT 0x00000002 +#define FLAG_PASS 0x00000004 +#define FLAG_LENGTH 0x00000008 +#define FLAG_BLOWFISH 0x00000010 +#define FLAG_ROUNDS 0x00000020 +#define FLAG_SHA256 0x00000040 +#define FLAG_SHA512 0x00000080 + -#define FLAG_MD5 0x00000001 -#define FLAG_DES 0x00000002 -#define FLAG_SALT 0x00000004 -#define FLAG_PASS 0x00000008 -#define FLAG_LENGTH 0x00000010 -#define FLAG_BLOWFISH 0x00000020 -#define FLAG_ROUNDS 0x00000040 -#define FLAG_EXT 0x00000080 - -extern char *getpass(); -extern char *crypt(); - -static char *make_des_salt(void); -static char *make_ext_salt(int); -static char *make_ext_salt_para(int, char *); static char *make_md5_salt(int); static char *make_md5_salt_para(char *); +static char *make_sha256_salt(int); +static char *make_sha256_salt_para(char *); +static char *make_sha512_salt(int); +static char *make_sha512_salt_para(char *); static char *make_bf_salt(int, int); static char *make_bf_salt_para(int, char *); -static char *int_to_base64(int); static char *generate_random_salt(char *, int); static char *generate_poor_salt(char *, int); -static void full_usage(void); -static void brief_usage(void); +static void full_usage(void) __attribute__((noreturn)); +static void brief_usage(void) __attribute__((noreturn)); -static char saltChars[] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; /* 0 .. 63, ascii - 64 */ -extern char *optarg; +#ifdef __MINGW32__ +#include +#ifdef PASS_MAX +#undef PASS_MAX +#endif +#define PASS_MAX 256 +static char getpassbuf[PASS_MAX + 1]; + +static char * +getpass(const char *prompt) +{ + int c; + int i = 0; + + memset(getpassbuf, 0, sizeof(getpassbuf)); + fputs(prompt, stderr); + for(;;) + { + c = _getch(); + if(c == '\r') + { + getpassbuf[i] = '\0'; + break; + } + else if(i < PASS_MAX) + { + getpassbuf[i++] = c; + } + } + fputs("\r\n", stderr); -int main(int argc, char *argv[]) + return getpassbuf; +} +#endif + + +int +main(int argc, char *argv[]) { - char *plaintext = NULL; - int c; - char *saltpara = NULL; - char *salt; - int flag = 0; - int length = 0; /* Not Set */ - int rounds = 0; /* Not set, since extended DES needs 25 and blowfish needs - ** 4 by default, a side effect of this being the encryption - ** type parameter must be specified before the rounds - ** parameter. - */ - - while( (c=getopt(argc, argv, "mdber:h?l:s:p:")) != -1) - { - switch(c) - { - case 'm': - flag |= FLAG_MD5; - break; - case 'd': - flag |= FLAG_DES; - break; - case 'b': - flag |= FLAG_BLOWFISH; - rounds = 4; - break; - case 'e': - flag |= FLAG_EXT; - rounds = 25; - break; - case 'l': - flag |= FLAG_LENGTH; - length = atoi(optarg); - break; - case 'r': - flag |= FLAG_ROUNDS; - rounds = atoi(optarg); - break; - case 's': - flag |= FLAG_SALT; - saltpara = optarg; - break; - case 'p': - flag |= FLAG_PASS; - plaintext = optarg; - break; - case 'h': - full_usage(); - /* NOT REACHED */ - break; - case '?': - brief_usage(); - /* NOT REACHED */ - break; - default: - printf("Invalid Option: -%c\n", c); - break; - } - } - - if (flag & FLAG_MD5) - { - if (length == 0) - length = 8; - if (flag & FLAG_SALT) - salt = make_md5_salt_para(saltpara); - else - salt = make_md5_salt(length); - } - else if (flag & FLAG_BLOWFISH) - { - if (length == 0) - length = 22; - if (flag & FLAG_SALT) - salt = make_bf_salt_para(rounds, saltpara); - else - salt = make_bf_salt(rounds, length); - } - else if (flag & FLAG_EXT) - { - /* XXX - rounds needs to be done */ - if (flag & FLAG_SALT) - { - if ((strlen(saltpara) == 4)) - { - salt = make_ext_salt_para(rounds, saltpara); - } - else - { - printf("Invalid salt, please enter 4 alphanumeric characters\n"); - exit(1); - } - } - else - { - salt = make_ext_salt(rounds); - } - } - else - { - if (flag & FLAG_SALT) - { - if ((strlen(saltpara) == 2)) - { - salt = saltpara; - } - else - { - printf("Invalid salt, please enter 2 alphanumeric characters\n"); - exit(1); - } - } - else - { - salt = make_des_salt(); - } - } - - if (flag & FLAG_PASS) - { - if (!plaintext) - printf("Please enter a valid password\n"); - } - else - { - plaintext = getpass("plaintext: "); - } - - printf("%s\n", crypt(plaintext, salt)); - return 0; + char *plaintext = NULL; + int c; + char *saltpara = NULL; + char *salt; + char *hashed, *hashed2; + int flag = 0; + int length = 0; /* Not Set */ + int rounds = 0; /* Not set, since blowfish needs 4 by default, a side effect + * of this being the encryption type parameter must be + * specified before the rounds parameter. + */ + + while((c = getopt(argc, argv, "xymbr:h?l:s:p:")) != -1) + { + switch (c) + { + case 'm': + flag |= FLAG_MD5; + break; + case 'b': + flag |= FLAG_BLOWFISH; + rounds = 4; + break; + case 'l': + flag |= FLAG_LENGTH; + length = atoi(optarg); + break; + case 'r': + flag |= FLAG_ROUNDS; + rounds = atoi(optarg); + break; + case 's': + flag |= FLAG_SALT; + saltpara = optarg; + break; + case 'p': + flag |= FLAG_PASS; + plaintext = optarg; + break; + case 'x': + flag |= FLAG_SHA256; + break; + case 'y': + flag |= FLAG_SHA512; + break; + case 'h': + full_usage(); + /* NOT REACHED */ + break; + case '?': + brief_usage(); + /* NOT REACHED */ + break; + default: + printf("Invalid Option: -%c\n", c); + break; + } + } + + if(flag & FLAG_MD5) + { + if(length == 0) + length = 8; + if(flag & FLAG_SALT) + salt = make_md5_salt_para(saltpara); + else + salt = make_md5_salt(length); + } + else if(flag & FLAG_BLOWFISH) + { + if(length == 0) + length = 22; + if(flag & FLAG_SALT) + salt = make_bf_salt_para(rounds, saltpara); + else + salt = make_bf_salt(rounds, length); + } + else if(flag & FLAG_SHA256) + { + if(length == 0) + length = 16; + if(flag & FLAG_SALT) + salt = make_sha256_salt_para(saltpara); + else + salt = make_sha256_salt(length); + } + else + { + if(length == 0) + length = 16; + if(flag & FLAG_SALT) + salt = make_sha512_salt_para(saltpara); + else + salt = make_sha512_salt(length); + } + + if(flag & FLAG_PASS) + { + if(!plaintext) + { + fprintf(stderr, "Please enter a valid password\n"); + return 1; + } + + hashed = rb_crypt(plaintext, salt); + } + else + { + plaintext = getpass("plaintext: "); + hashed = rb_crypt(plaintext, salt); + if (!hashed) + { + fprintf(stderr, "rb_crypt() failed\n"); + return 1; + } + hashed = strdup(hashed); + + plaintext = getpass("again: "); + hashed2 = rb_crypt(plaintext, salt); + if (!hashed2) + { + fprintf(stderr, "rb_crypt() failed\n"); + return 1; + } + + if (strcmp(hashed, hashed2) != 0) + { + fprintf(stderr, "Passwords do not match\n"); + return 1; + } + } + + printf("%s\n", hashed); + return 0; } -static char *make_des_salt() +char * +make_md5_salt_para(char *saltpara) { - static char salt[3]; - generate_random_salt(salt, 2); - salt[2] = '\0'; - return salt; + static char salt[21]; + if(saltpara && (strlen(saltpara) <= 16)) + { + /* sprintf used because of portability requirements, the length + ** is checked above, so it should not be too much of a concern + */ + sprintf(salt, "$1$%s$", saltpara); + return salt; + } + printf("Invalid Salt, please use up to 16 random alphanumeric characters\n"); + exit(1); + + /* NOT REACHED */ + return NULL; } -char *int_to_base64(int value) +char * +make_md5_salt(int length) { - static char buf[5]; - int i; - - for (i = 0; i < 4; i++) - { - buf[i] = saltChars[value & 63]; - value >>= 6; /* Right shifting 6 places is the same as dividing by 64 */ - } - - buf[i] = '\0'; /* not REALLY needed as it's static, and thus initialized - ** to \0. - */ - return buf; + static char salt[21]; + if(length > 16) + { + printf("MD5 salt length too long\n"); + exit(0); + } + salt[0] = '$'; + salt[1] = '1'; + salt[2] = '$'; + generate_random_salt(&salt[3], length); + salt[length + 3] = '$'; + salt[length + 4] = '\0'; + return salt; } -char *make_ext_salt(int rounds) +char * +make_sha256_salt_para(char *saltpara) { - static char salt[10]; + static char salt[21]; + if(saltpara && (strlen(saltpara) <= 16)) + { + /* sprintf used because of portability requirements, the length + ** is checked above, so it should not be too much of a concern + */ + sprintf(salt, "$5$%s$", saltpara); + return salt; + } + printf("Invalid Salt, please use up to 16 random alphanumeric characters\n"); + exit(1); - sprintf(salt, "_%s", int_to_base64(rounds)); - generate_random_salt(&salt[5], 4); - salt[9] = '\0'; - return salt; + /* NOT REACHED */ + return NULL; } -char *make_ext_salt_para(int rounds, char *saltpara) +char * +make_sha512_salt_para(char *saltpara) { - static char salt[10]; + static char salt[21]; + if(saltpara && (strlen(saltpara) <= 16)) + { + /* sprintf used because of portability requirements, the length + ** is checked above, so it should not be too much of a concern + */ + sprintf(salt, "$6$%s$", saltpara); + return salt; + } + printf("Invalid Salt, please use up to 16 random alphanumeric characters\n"); + exit(1); - sprintf(salt, "_%s%s", int_to_base64(rounds), saltpara); - return salt; + /* NOT REACHED */ + return NULL; } -char *make_md5_salt_para(char *saltpara) + +char * +make_sha256_salt(int length) { - static char salt[21]; - if (saltpara && (strlen(saltpara) <= 16)) - { - /* sprintf used because of portability requirements, the length - ** is checked above, so it should not be too much of a concern - */ - sprintf(salt, "$1$%s$", saltpara); - return salt; - } - printf("Invalid Salt, please use up to 16 random alphanumeric characters\n"); - exit(1); - - /* NOT REACHED */ - return NULL; + static char salt[21]; + if(length > 16) + { + printf("SHA256 salt length too long\n"); + exit(0); + } + salt[0] = '$'; + salt[1] = '5'; + salt[2] = '$'; + generate_random_salt(&salt[3], length); + salt[length + 3] = '$'; + salt[length + 4] = '\0'; + return salt; } - -char *make_md5_salt(int length) + +char * +make_sha512_salt(int length) { - static char salt[21]; - if (length > 16) - { - printf("MD5 salt length too long\n"); - exit(0); - } - salt[0] = '$'; - salt[1] = '1'; - salt[2] = '$'; - generate_random_salt(&salt[3], length); - salt[length+3] = '$'; - salt[length+4] = '\0'; - return salt; + static char salt[21]; + if(length > 16) + { + printf("SHA512 salt length too long\n"); + exit(0); + } + salt[0] = '$'; + salt[1] = '6'; + salt[2] = '$'; + generate_random_salt(&salt[3], length); + salt[length + 3] = '$'; + salt[length + 4] = '\0'; + return salt; } -char *make_bf_salt_para(int rounds, char *saltpara) +char * +make_bf_salt_para(int rounds, char *saltpara) { - static char salt[31]; - char tbuf[3]; - if (saltpara && (strlen(saltpara) <= 22)) - { - /* sprintf used because of portability requirements, the length - ** is checked above, so it should not be too much of a concern - */ - sprintf(tbuf, "%02d", rounds); - sprintf(salt, "$2a$%s$%s$", tbuf, saltpara); - return salt; - } - printf("Invalid Salt, please use up to 22 random alphanumeric characters\n"); - exit(1); - - /* NOT REACHED */ - return NULL; + static char salt[31]; + char tbuf[3]; + if(saltpara && (strlen(saltpara) <= 22)) + { + /* sprintf used because of portability requirements, the length + ** is checked above, so it should not be too much of a concern + */ + sprintf(tbuf, "%02d", rounds); + sprintf(salt, "$2a$%s$%s$", tbuf, saltpara); + return salt; + } + printf("Invalid Salt, please use up to 22 random alphanumeric characters\n"); + exit(1); + + /* NOT REACHED */ + return NULL; } -char *make_bf_salt(int rounds, int length) +char * +make_bf_salt(int rounds, int length) { - static char salt[31]; - char tbuf[3]; - if (length > 22) - { - printf("BlowFish salt length too long\n"); - exit(0); - } - sprintf(tbuf, "%02d", rounds); - sprintf(salt, "$2a$%s$", tbuf); - generate_random_salt(&salt[7], length); - salt[length+7] = '$'; - salt[length+8] = '\0'; - return salt; + static char salt[31]; + char tbuf[3]; + if(length > 22) + { + printf("Blowfish salt length too long\n"); + exit(0); + } + sprintf(tbuf, "%02d", rounds); + sprintf(salt, "$2a$%s$", tbuf); + generate_random_salt(&salt[7], length); + salt[length + 7] = '$'; + salt[length + 8] = '\0'; + return salt; } -char *generate_poor_salt(char *salt, int length) +char * +generate_poor_salt(char *salt, int length) { - int i; - srandom(time(NULL)); - for(i = 0; i < length; i++) - { - salt[i] = saltChars[random() % 64]; - } - return(salt); + int i; + srand(time(NULL)); + for(i = 0; i < length; i++) + { + salt[i] = saltChars[rand() % 64]; + } + return (salt); } -char *generate_random_salt(char *salt, int length) +char * +generate_random_salt(char *salt, int length) { - char *buf; - int fd, i; - if((fd = open("/dev/random", O_RDONLY)) < 0) - { - return(generate_poor_salt(salt, length)); - } - buf = calloc(1, length); - if(read(fd, buf, length) != length) - { - free(buf); - return(generate_poor_salt(salt, length)); - } - - for(i = 0; i < length; i++) - { - salt[i] = saltChars[abs(buf[i]) % 64]; - } - free(buf); - return(salt); + char *buf; + int fd, i; + if((fd = open("/dev/random", O_RDONLY)) < 0) + { + return (generate_poor_salt(salt, length)); + } + buf = calloc(1, length); + if(read(fd, buf, length) != length) + { + free(buf); + return (generate_poor_salt(salt, length)); + } + + for(i = 0; i < length; i++) + { + salt[i] = saltChars[abs(buf[i]) % 64]; + } + free(buf); + return (salt); } -void full_usage() +void +full_usage() { - printf("mkpasswd [-m|-d|-b|-e] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n"); - printf("-m Generate an MD5 password\n"); - printf("-d Generate a DES password\n"); - printf("-b Generate a BlowFish password\n"); - printf("-e Generate an Extended DES password\n"); - printf("-l Specify a length for a random MD5 or BlowFish salt\n"); - printf("-r Specify a number of rounds for a BlowFish or Extended DES password\n"); - printf(" BlowFish: default 4, no more than 6 recommended\n"); - printf(" Extended DES: default 25\n"); - printf("-s Specify a salt, 2 alphanumeric characters for DES, up to 16 for MD5,\n"); - printf(" up to 22 for BlowFish, and 4 for Extended DES\n"); - printf("-p Specify a plaintext password to use\n"); - printf("Example: mkpasswd -m -s 3dr -p test\n"); - exit(0); + printf("mkpasswd [-m|-b|-x|-y] [-l saltlength] [-r rounds] [-s salt] [-p plaintext]\n"); + printf("-x Generate a SHA256 password\n"); + printf("-y Generate a SHA512 password\n"); + printf("-m Generate an MD5 password\n"); + printf("-b Generate a Blowfish password\n"); + printf("-l Specify a length for a random MD5 or Blowfish salt\n"); + printf("-r Specify a number of rounds for a Blowfish password\n"); + printf(" Default 4, no more than 6 recommended\n"); + printf("-s Specify a salt, up to 16 for MD5, SHA256, and SHA512\n"); + printf(" up to 22 for Blowfish\n"); + printf("-p Specify a plaintext password to use\n"); + printf("Example: mkpasswd -m -s 3dr -p test\n"); + exit(0); } -void brief_usage() +void +brief_usage() { - printf("mkpasswd - password hash generator\n"); - printf("Standard DES: mkpasswd [-d] [-s salt] [-p plaintext]\n"); - printf("Extended DES: mkpasswd -e [-r rounds] [-s salt] [-p plaintext]\n"); - printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n"); - printf(" BlowFish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n"); - printf(" [-p plaintext]\n"); - printf("Use -h for full usage\n"); - exit(0); + printf("mkpasswd - password hash generator\n"); + printf(" SHA512: mkpasswd [-y] [-l saltlength] [-s salt] [-p plaintext]\n"); + printf(" SHA256: mkpasswd -x [-l saltlength] [-s salt] [-p plaintext]\n"); + printf(" MD5: mkpasswd -m [-l saltlength] [-s salt] [-p plaintext]\n"); + printf("Blowfish: mkpasswd -b [-r rounds] [-l saltlength] [-s salt]\n"); + printf(" [-p plaintext]\n"); + printf("Use -h for full usage\n"); + exit(0); }