| 1 |
#define _XOPEN_SOURCE |
|---|
| 2 |
#include <sys/types.h> |
|---|
| 3 |
#include <stdio.h> |
|---|
| 4 |
#include <string.h> |
|---|
| 5 |
#include <stdlib.h> |
|---|
| 6 |
#include <unistd.h> |
|---|
| 7 |
#include <ctype.h> |
|---|
| 8 |
|
|---|
| 9 |
#define VERSION "0.1.13" |
|---|
| 10 |
|
|---|
| 11 |
char *get_range(char const *input); |
|---|
| 12 |
void usage(char const *name); |
|---|
| 13 |
void make_salt(char *salt, int size); |
|---|
| 14 |
|
|---|
| 15 |
int main(int argc, char **argv) { |
|---|
| 16 |
char *input = "-0-9a-zA-Z`=[]\\;',./~_+{}|:\"<>?", *buffer = 0, *exclude = 0, *excludeinput = 0; |
|---|
| 17 |
int len, i, pwlen = 16, md5 = 0, cryptit = 0, showplain = 1, quiet = 0; |
|---|
| 18 |
char *password = NULL; |
|---|
| 19 |
|
|---|
| 20 |
if (argc > 1) |
|---|
| 21 |
for (i = 1; i < argc; i++) |
|---|
| 22 |
/* options */ |
|---|
| 23 |
if (argv[i][0] == '-') { |
|---|
| 24 |
int j = 1; |
|---|
| 25 |
|
|---|
| 26 |
while (argv[i][j]) { |
|---|
| 27 |
switch (argv[i][j]) { |
|---|
| 28 |
/* numeric size */ |
|---|
| 29 |
case '0' : case '1' : case '2' : case '3' : |
|---|
| 30 |
case '4' : case '5' : case '6' : case '7' : |
|---|
| 31 |
case '8' : case '9' : |
|---|
| 32 |
pwlen = atoi(argv[i] + j); |
|---|
| 33 |
while (argv[i][j] && isdigit(argv[i][j])) j++; |
|---|
| 34 |
j--; |
|---|
| 35 |
break; |
|---|
| 36 |
/* md5 */ |
|---|
| 37 |
case 'm' : |
|---|
| 38 |
md5 = 1; |
|---|
| 39 |
break; |
|---|
| 40 |
case 'v' : |
|---|
| 41 |
printf("%s\n", VERSION); |
|---|
| 42 |
return 0; |
|---|
| 43 |
break; |
|---|
| 44 |
// crypt |
|---|
| 45 |
case 'c' : |
|---|
| 46 |
cryptit = 1; |
|---|
| 47 |
break; |
|---|
| 48 |
case 'n' : |
|---|
| 49 |
input = "0-9"; |
|---|
| 50 |
break; |
|---|
| 51 |
case 'q' : |
|---|
| 52 |
quiet = 1; |
|---|
| 53 |
break; |
|---|
| 54 |
// exclude |
|---|
| 55 |
case 'e' : |
|---|
| 56 |
excludeinput = argv[i] + j; |
|---|
| 57 |
while (argv[i][j]) ++j; |
|---|
| 58 |
--j; |
|---|
| 59 |
break; |
|---|
| 60 |
case 'a' : |
|---|
| 61 |
input = "a-zA-Z"; |
|---|
| 62 |
break; |
|---|
| 63 |
case 'A' : |
|---|
| 64 |
input = "A-Za-z0-9"; |
|---|
| 65 |
break; |
|---|
| 66 |
case 'p' : |
|---|
| 67 |
{ |
|---|
| 68 |
int i; |
|---|
| 69 |
char comp[64]; |
|---|
| 70 |
|
|---|
| 71 |
for (i = 0; i < 2; i++) { |
|---|
| 72 |
showplain = 0; |
|---|
| 73 |
system("stty -echo"); |
|---|
| 74 |
if (i == 1) |
|---|
| 75 |
password = (char*)malloc(64); |
|---|
| 76 |
else |
|---|
| 77 |
password = comp; |
|---|
| 78 |
if (!quiet) printf("Password: "); |
|---|
| 79 |
fflush(stdout); |
|---|
| 80 |
fgets(password, 64, stdin); |
|---|
| 81 |
password[strlen(password) - 1] = 0; |
|---|
| 82 |
system("stty echo"); |
|---|
| 83 |
if (!quiet) printf("\n"); |
|---|
| 84 |
fflush(stdout); |
|---|
| 85 |
} |
|---|
| 86 |
if (strcmp(password, comp)) { |
|---|
| 87 |
fprintf(stderr, "error: passwords do not match\n"); |
|---|
| 88 |
return 1; |
|---|
| 89 |
} |
|---|
| 90 |
} |
|---|
| 91 |
break; |
|---|
| 92 |
case 'P' : |
|---|
| 93 |
password = argv[i] + j + 1; |
|---|
| 94 |
while (argv[i][j]) ++j; |
|---|
| 95 |
--j; |
|---|
| 96 |
break; |
|---|
| 97 |
default : |
|---|
| 98 |
usage(argv[0]); |
|---|
| 99 |
break; |
|---|
| 100 |
} |
|---|
| 101 |
j++; |
|---|
| 102 |
} |
|---|
| 103 |
} else /* specify range of characters to use */ |
|---|
| 104 |
input = argv[i]; |
|---|
| 105 |
|
|---|
| 106 |
srand48(getpid() + time(0)); |
|---|
| 107 |
|
|---|
| 108 |
if ((buffer = get_range(input)) == NULL) { |
|---|
| 109 |
printf("%s: error, too many characters in password character pool (>255)\n", argv[0]); |
|---|
| 110 |
return 1; |
|---|
| 111 |
} |
|---|
| 112 |
|
|---|
| 113 |
if (excludeinput) { |
|---|
| 114 |
char *new = (char*)malloc(strlen(buffer) + 1); |
|---|
| 115 |
int j = 0; |
|---|
| 116 |
|
|---|
| 117 |
if ((exclude = get_range(excludeinput)) == NULL) { |
|---|
| 118 |
printf("%s: error, too many characters in exclude pool (>255)\n", argv[0]); |
|---|
| 119 |
return 1; |
|---|
| 120 |
} |
|---|
| 121 |
for (i = 0; i < strlen(buffer); i++) |
|---|
| 122 |
if (!strchr(exclude, buffer[i])) |
|---|
| 123 |
new[j++] = buffer[i]; |
|---|
| 124 |
new[j] = 0; |
|---|
| 125 |
free(buffer); |
|---|
| 126 |
buffer = new; |
|---|
| 127 |
} |
|---|
| 128 |
|
|---|
| 129 |
len = strlen(buffer); |
|---|
| 130 |
|
|---|
| 131 |
if (password == NULL) { |
|---|
| 132 |
password = (char*)malloc(pwlen + 1); |
|---|
| 133 |
for (i = 0; i < pwlen; i++) |
|---|
| 134 |
password[i] = buffer[(int)(drand48() * len)]; |
|---|
| 135 |
password[i] = 0; |
|---|
| 136 |
} |
|---|
| 137 |
|
|---|
| 138 |
if (showplain) { |
|---|
| 139 |
if (!quiet) printf("Password: "); |
|---|
| 140 |
printf("%s\n", password); |
|---|
| 141 |
} |
|---|
| 142 |
|
|---|
| 143 |
if (md5) { |
|---|
| 144 |
char salt[13]; |
|---|
| 145 |
|
|---|
| 146 |
strcpy(salt, "$1$"); |
|---|
| 147 |
make_salt(salt + 3, 9); |
|---|
| 148 |
if (!quiet) printf("MD5: "); |
|---|
| 149 |
printf("%s\n", crypt(password, salt)); |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
if (cryptit) { |
|---|
| 153 |
char salt[3]; |
|---|
| 154 |
|
|---|
| 155 |
make_salt(salt, 2); |
|---|
| 156 |
if (!quiet) printf("Crypt: "); |
|---|
| 157 |
printf("%s\n", crypt(password, salt)); |
|---|
| 158 |
} |
|---|
| 159 |
return 0; |
|---|
| 160 |
} |
|---|
| 161 |
|
|---|
| 162 |
char *get_range(char const *input) { |
|---|
| 163 |
char *out = (char*)malloc(257), *p = out; |
|---|
| 164 |
|
|---|
| 165 |
if (*input == '-') { |
|---|
| 166 |
*p++ = '-'; |
|---|
| 167 |
input++; |
|---|
| 168 |
} |
|---|
| 169 |
/* return zero-terminated buffer */ |
|---|
| 170 |
while (*input) { |
|---|
| 171 |
|
|---|
| 172 |
if (p - out >= 254) return NULL; |
|---|
| 173 |
if (input[1] == '-') { |
|---|
| 174 |
int i; |
|---|
| 175 |
|
|---|
| 176 |
if (input[2] == 0) |
|---|
| 177 |
*p++ = '-'; |
|---|
| 178 |
else { |
|---|
| 179 |
for (i = input[0]; i <= input[2]; ++i) { |
|---|
| 180 |
if (p - out >= 254) return NULL; |
|---|
| 181 |
*p++ = i; |
|---|
| 182 |
} |
|---|
| 183 |
} |
|---|
| 184 |
input += 3; |
|---|
| 185 |
} else { |
|---|
| 186 |
*p++ = *input; |
|---|
| 187 |
++input; |
|---|
| 188 |
} |
|---|
| 189 |
} |
|---|
| 190 |
*p = 0; |
|---|
| 191 |
return out; |
|---|
| 192 |
} |
|---|
| 193 |
|
|---|
| 194 |
void usage(char const *name) { |
|---|
| 195 |
printf("usage: %s [-<length>] [-m] [-n] [-a] [-A] [<range>]\n" |
|---|
| 196 |
" -<length> specify the length of the password\n" |
|---|
| 197 |
" -m generate the MD5 sum of the resultant password\n" |
|---|
| 198 |
" -c generate crypt of resultant password\n" |
|---|
| 199 |
" -n use numeric characters for password character pool\n" |
|---|
| 200 |
" -a use alpha characters for password character pool\n" |
|---|
| 201 |
" -A use alpha-numeric characters for password character pool\n" |
|---|
| 202 |
" -e<string> exclude the given characters from the password\n" |
|---|
| 203 |
" -p prompt the user for the password\n" |
|---|
| 204 |
" -P<string> use the specified string as the password\n" |
|---|
| 205 |
" -q do not display prompts or field descriptions\n" |
|---|
| 206 |
" <range> specify characters to use for password, ala '[]' regexp\n" |
|---|
| 207 |
" -v show version number\n" |
|---|
| 208 |
"\n" |
|---|
| 209 |
"eg. %s -64m A-Za-z0-9\n" |
|---|
| 210 |
, name, name); |
|---|
| 211 |
exit(1); |
|---|
| 212 |
} |
|---|
| 213 |
|
|---|
| 214 |
void make_salt(char *salt, int size) { |
|---|
| 215 |
char *randomchars = get_range("a-zA-Z0-9./"); |
|---|
| 216 |
int i; |
|---|
| 217 |
|
|---|
| 218 |
for (i = 0; i < size; i++) |
|---|
| 219 |
salt[i] = randomchars[(int)(drand48() * strlen(randomchars))]; |
|---|
| 220 |
salt[size] = 0; |
|---|
| 221 |
free((void*)randomchars); |
|---|
| 222 |
} |
|---|