Annotation of src/usr.bin/encrypt/encrypt.c, Revision 1.12
1.12 ! provos 1: /* $OpenBSD: encrypt.c,v 1.11 1999/09/03 18:13:37 deraadt 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 <stdio.h>
29: #include <sys/types.h>
30: #include <err.h>
1.3 downsj 31: #include <errno.h>
1.7 kstailey 32: #include <stdlib.h>
1.1 downsj 33: #include <string.h>
34: #include <unistd.h>
1.5 provos 35: #include <pwd.h>
1.10 art 36: #include <ctype.h>
1.1 downsj 37:
38: /*
39: * Very simple little program, for encrypting passwords from the command
40: * line. Useful for scripts and such.
41: */
42:
1.5 provos 43: #define DO_MAKEKEY 0
44: #define DO_DES 1
45: #define DO_MD5 2
46: #define DO_BLF 3
47:
1.1 downsj 48: extern char *optarg;
49: extern int optind;
50:
1.3 downsj 51: char *progname;
1.5 provos 52: char buffer[_PASSWORD_LEN];
1.3 downsj 53:
1.1 downsj 54: void usage()
55: {
1.9 alex 56: fprintf(stderr, "usage: %s [-k] [-b rounds] [-m] [-s salt] [-p | string]\n",
1.8 alex 57: progname);
58: exit(1);
1.1 downsj 59: }
60:
1.2 downsj 61: char *trim(line)
62: char *line;
63: {
64: char *ptr;
65:
66: for (ptr = &line[strlen(line)-1]; ptr > line; ptr--) {
67: if (!isspace(*ptr))
68: break;
69: }
70: ptr[1] = '\0';
71:
72: for (ptr = line; *ptr && isspace(*ptr); ptr++);
73:
74: return(ptr);
75: }
76:
1.5 provos 77: void print_passwd(char *string, int operation, void *extra)
78: {
79: char msalt[3], *salt;
80: struct passwd pwd;
1.10 art 81: extern int pwd_gensalt __P((char *, int, struct passwd *, char));
82: extern void to64 __P((char *, int32_t, int n));
1.5 provos 83:
84: switch(operation) {
85: case DO_MAKEKEY:
86: /*
1.12 ! provos 87: * makekey mode: parse string into separate DES key and salt.
1.5 provos 88: */
89: if (strlen(string) != 10) {
90: /* To be compatible... */
91: fprintf (stderr, "%s: %s\n", progname, strerror(EFTYPE));
92: exit (1);
93: }
94: strcpy(msalt, &string[8]);
95: salt = msalt;
96: break;
97: case DO_MD5:
98: strcpy(buffer, "$1$");
99: to64(&buffer[3], arc4random(), 4);
100: to64(&buffer[7], arc4random(), 4);
101: strcpy(buffer+11, "$");
102: salt = buffer;
103: break;
104: case DO_BLF:
105: strncpy(buffer, bcrypt_gensalt(*(int *)extra), _PASSWORD_LEN - 1);
106: buffer[_PASSWORD_LEN-1] = 0;
107: salt = buffer;
108: break;
109: case DO_DES:
110: salt = extra;
111: break;
112: default:
113: pwd.pw_name = "default";
114: if (!pwd_gensalt(buffer, _PASSWORD_LEN, &pwd, 'l')) {
115: fprintf (stderr, "%s: Can't generate salt\n", progname);
116: exit (1);
117: }
118: salt = buffer;
119: break;
120: }
121:
122: fputs(crypt(string, salt), stdout);
123: }
124:
1.1 downsj 125: int main(argc, argv)
126: int argc;
127: char *argv[];
128: {
129: int opt;
1.5 provos 130: int operation = -1;
1.9 alex 131: int prompt = 0;
1.5 provos 132: int rounds;
133: void *extra; /* Store salt or number of rounds */
1.1 downsj 134:
1.3 downsj 135: if ((progname = strrchr(argv[0], '/')))
136: progname++;
137: else
138: progname = argv[0];
139:
140: if (strcmp(progname, "makekey") == 0)
1.5 provos 141: operation = DO_MAKEKEY;
1.3 downsj 142:
1.9 alex 143: while ((opt = getopt(argc, argv, "kmps:b:")) != -1) {
1.1 downsj 144: switch (opt) {
1.5 provos 145: case 'k': /* Stdin/Stdout Unix crypt */
146: if (operation != -1)
147: usage();
148: operation = DO_MAKEKEY;
1.3 downsj 149: break;
1.5 provos 150: case 'm': /* MD5 password hash */
1.9 alex 151: if (operation != -1 || prompt)
152: usage();
153: operation = DO_MD5;
154: break;
155: case 'p':
1.5 provos 156: if (operation != -1)
157: usage();
1.9 alex 158: prompt = 1;
1.1 downsj 159: break;
1.5 provos 160: case 's': /* Unix crypt (DES) */
161: if (operation != -1)
162: usage();
163: operation = DO_DES;
164: if (optarg[0] == '$') /* -s is only for DES. */
1.4 downsj 165: usage();
1.5 provos 166: extra = optarg;
1.1 downsj 167: break;
1.5 provos 168: case 'b': /* Blowfish password hash */
169: if (operation != -1)
170: usage();
171: operation = DO_BLF;
172: rounds = atoi(optarg);
173: extra = &rounds;
174: break;
1.1 downsj 175: default:
176: usage();
177: }
178: }
179:
1.5 provos 180: if (((argc - optind) < 1) || operation == DO_MAKEKEY) {
181: char line[BUFSIZ], *string;
1.1 downsj 182:
1.9 alex 183: if (prompt) {
184: string = getpass("Enter string: ");
1.5 provos 185: print_passwd(string, operation, extra);
1.9 alex 186: fputc('\n', stdout);
187: } else {
188: /* Encrypt stdin to stdout. */
189: while (!feof(stdin) && (fgets(line, sizeof(line), stdin) != NULL)) {
190: /* Kill the whitesapce. */
191: string = trim(line);
192: if (*string == '\0')
193: continue;
194:
195: print_passwd(string, operation, extra);
196:
197: if (operation == DO_MAKEKEY) {
198: fflush(stdout);
199: break;
200: }
201: fputc('\n', stdout);
1.3 downsj 202: }
1.1 downsj 203: }
204: } else {
205: char *string;
1.9 alex 206:
207: /* can't combine -p with a supplied string */
208: if (prompt)
209: usage();
1.1 downsj 210:
211: /* Perhaps it isn't worth worrying about, but... */
212: string = strdup(argv[optind]);
1.6 kstailey 213: if (string == NULL)
1.1 downsj 214: err(1, NULL);
215: /* Wipe the argument. */
216: bzero(argv[optind], strlen(argv[optind]));
217:
1.5 provos 218: print_passwd(string, operation, extra);
219:
1.1 downsj 220: fputc('\n', stdout);
221:
222: /* Wipe our copy, before we free it. */
223: bzero(string, strlen(string));
224: free(string);
225: }
226: exit(0);
227: }