Annotation of src/usr.bin/encrypt/encrypt.c, Revision 1.27
1.27 ! jdixon 1: /* $OpenBSD: encrypt.c,v 1.26 2007/03/20 03:50:39 tedu Exp $ */
1.1 downsj 2:
3: /*
4: * Copyright (c) 1996, Jason Downs. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
1.15 millert 29: #include <ctype.h>
1.1 downsj 30: #include <err.h>
1.3 downsj 31: #include <errno.h>
1.15 millert 32: #include <pwd.h>
33: #include <stdio.h>
1.7 kstailey 34: #include <stdlib.h>
1.1 downsj 35: #include <string.h>
36: #include <unistd.h>
1.14 millert 37: #include <login_cap.h>
1.27 ! jdixon 38: #include <limits.h>
1.1 downsj 39:
40: /*
41: * Very simple little program, for encrypting passwords from the command
42: * line. Useful for scripts and such.
43: */
44:
1.5 provos 45: #define DO_MAKEKEY 0
46: #define DO_DES 1
47: #define DO_MD5 2
48: #define DO_BLF 3
49:
1.15 millert 50: extern char *__progname;
1.5 provos 51: char buffer[_PASSWORD_LEN];
1.19 deraadt 52:
53: void usage(void);
54: char *trim(char *);
55: void print_passwd(char *, int, void *);
1.3 downsj 56:
1.15 millert 57: void
58: usage(void)
1.1 downsj 59: {
1.15 millert 60:
61: (void)fprintf(stderr,
1.25 jmc 62: "usage: %s [-km] [-b rounds] [-c class] [-p | string] [-s salt]\n",
1.15 millert 63: __progname);
64: exit(1);
1.1 downsj 65: }
66:
1.15 millert 67: char *
68: trim(char *line)
1.2 downsj 69: {
1.15 millert 70: char *ptr;
1.24 ray 71:
72: if (line[0] == '\0')
73: return (line);
1.2 downsj 74:
1.15 millert 75: for (ptr = &line[strlen(line)-1]; ptr > line; ptr--) {
76: if (!isspace(*ptr))
77: break;
78: }
79: ptr[1] = '\0';
1.2 downsj 80:
1.26 tedu 81: for (ptr = line; isspace(*ptr); ptr++)
1.15 millert 82: ;
1.2 downsj 83:
1.15 millert 84: return(ptr);
1.2 downsj 85: }
86:
1.15 millert 87: void
88: print_passwd(char *string, int operation, void *extra)
1.5 provos 89: {
1.23 moritz 90: char msalt[3], *salt, *cryptstr;
1.15 millert 91: login_cap_t *lc;
1.21 millert 92: int pwd_gensalt(char *, int, login_cap_t *, char);
1.22 deraadt 93: void to64(char *, u_int32_t, int n);
1.15 millert 94:
95: switch(operation) {
96: case DO_MAKEKEY:
97: /*
98: * makekey mode: parse string into separate DES key and salt.
99: */
100: if (strlen(string) != 10) {
101: /* To be compatible... */
102: errx(1, "%s", strerror(EFTYPE));
103: }
1.17 deraadt 104: strlcpy(msalt, &string[8], sizeof msalt);
1.15 millert 105: salt = msalt;
106: break;
107:
108: case DO_MD5:
1.17 deraadt 109: strlcpy(buffer, "$1$", sizeof buffer);
1.15 millert 110: to64(&buffer[3], arc4random(), 4);
111: to64(&buffer[7], arc4random(), 4);
1.17 deraadt 112: strlcpy(buffer + 11, "$", sizeof buffer - 11);
1.15 millert 113: salt = buffer;
114: break;
115:
116: case DO_BLF:
117: strlcpy(buffer, bcrypt_gensalt(*(int *)extra), _PASSWORD_LEN);
118: salt = buffer;
119: break;
120:
121: case DO_DES:
122: salt = extra;
123: break;
124:
125: default:
1.18 millert 126: if ((lc = login_getclass(extra)) == NULL)
127: errx(1, "unable to get login class `%s'",
128: extra ? (char *)extra : "default");
1.21 millert 129: if (!pwd_gensalt(buffer, _PASSWORD_LEN, lc, 'l'))
1.15 millert 130: errx(1, "can't generate salt");
131: salt = buffer;
132: break;
133: }
134:
1.23 moritz 135: if ((cryptstr = crypt(string, salt)) == NULL)
136: errx(1, "crypt failed");
137: fputs(cryptstr, stdout);
1.5 provos 138: }
139:
1.15 millert 140: int
141: main(int argc, char **argv)
1.1 downsj 142: {
1.15 millert 143: int opt;
144: int operation = -1;
145: int prompt = 0;
146: int rounds;
1.18 millert 147: void *extra = NULL; /* Store salt or number of rounds */
1.27 ! jdixon 148: const char *errstr;
1.15 millert 149:
150: if (strcmp(__progname, "makekey") == 0)
151: operation = DO_MAKEKEY;
152:
1.18 millert 153: while ((opt = getopt(argc, argv, "kmps:b:c:")) != -1) {
1.15 millert 154: switch (opt) {
155: case 'k': /* Stdin/Stdout Unix crypt */
156: if (operation != -1 || prompt)
157: usage();
158: operation = DO_MAKEKEY;
159: break;
160:
161: case 'm': /* MD5 password hash */
162: if (operation != -1)
163: usage();
164: operation = DO_MD5;
165: break;
166:
167: case 'p':
168: if (operation == DO_MAKEKEY)
169: usage();
170: prompt = 1;
171: break;
172:
173: case 's': /* Unix crypt (DES) */
174: if (operation != -1 || optarg[0] == '$')
175: usage();
176: operation = DO_DES;
177: extra = optarg;
178: break;
179:
180: case 'b': /* Blowfish password hash */
181: if (operation != -1)
182: usage();
183: operation = DO_BLF;
1.27 ! jdixon 184: rounds = strtonum(optarg, 1, INT_MAX, &errstr);
! 185: if (errstr != NULL)
! 186: errx(1, "%s: %s", errstr, optarg);
1.15 millert 187: extra = &rounds;
1.18 millert 188: break;
189:
190: case 'c': /* user login class */
191: extra = optarg;
192: operation = -1;
1.15 millert 193: break;
194:
195: default:
196: usage();
197: }
1.1 downsj 198: }
199:
1.15 millert 200: if (((argc - optind) < 1) || operation == DO_MAKEKEY) {
201: char line[BUFSIZ], *string;
1.1 downsj 202:
1.15 millert 203: if (prompt) {
1.20 otto 204: if ((string = getpass("Enter string: ")) == NULL)
205: err(1, "getpass");
1.15 millert 206: print_passwd(string, operation, extra);
207: (void)fputc('\n', stdout);
208: } else {
209: /* Encrypt stdin to stdout. */
210: while (!feof(stdin) &&
211: (fgets(line, sizeof(line), stdin) != NULL)) {
212: /* Kill the whitesapce. */
213: string = trim(line);
214: if (*string == '\0')
215: continue;
216:
217: print_passwd(string, operation, extra);
218:
219: if (operation == DO_MAKEKEY) {
220: fflush(stdout);
221: break;
222: }
223: (void)fputc('\n', stdout);
224: }
225: }
1.9 alex 226: } else {
1.15 millert 227: char *string;
228:
229: /* can't combine -p with a supplied string */
230: if (prompt)
231: usage();
232:
233: /* Perhaps it isn't worth worrying about, but... */
234: if ((string = strdup(argv[optind])) == NULL)
235: err(1, NULL);
236: /* Wipe the argument. */
237: memset(argv[optind], 0, strlen(argv[optind]));
238:
1.9 alex 239: print_passwd(string, operation, extra);
240:
1.15 millert 241: (void)fputc('\n', stdout);
242:
243: /* Wipe our copy, before we free it. */
244: memset(string, 0, strlen(string));
245: free(string);
1.1 downsj 246: }
1.15 millert 247: exit(0);
1.1 downsj 248: }