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