Annotation of src/usr.bin/encrypt/encrypt.c, Revision 1.36
1.36 ! deraadt 1: /* $OpenBSD: encrypt.c,v 1.35 2014/12/29 17:07:17 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.15 millert 45: extern char *__progname;
1.19 deraadt 46:
47: void usage(void);
1.30 deraadt 48: int ideal_rounds(void);
1.19 deraadt 49: void print_passwd(char *, int, void *);
1.3 downsj 50:
1.34 tedu 51: #define DO_BLF 0
52:
1.15 millert 53: void
54: usage(void)
1.1 downsj 55: {
1.15 millert 56:
57: (void)fprintf(stderr,
1.34 tedu 58: "usage: %s [-b rounds] [-c class] [-p | string]\n",
1.15 millert 59: __progname);
60: exit(1);
1.1 downsj 61: }
62:
1.29 tedu 63: /*
64: * Time how long 8 rounds takes to measure this system's performance.
65: * We are aiming for something that takes between 0.25 and 0.5 seconds.
66: */
67: int
1.30 deraadt 68: ideal_rounds(void)
1.29 tedu 69: {
70: clock_t before, after;
71: int r = 8;
72: char buf[_PASSWORD_LEN];
73: int duration;
74:
75: strlcpy(buf, bcrypt_gensalt(r), _PASSWORD_LEN);
76: before = clock();
77: crypt("testpassword", buf);
78: after = clock();
79:
80: duration = after - before;
81:
82: /* too quick? slow it down. */
1.35 tedu 83: while (r < 16 && duration <= CLOCKS_PER_SEC / 4) {
1.29 tedu 84: r += 1;
85: duration *= 2;
86: }
87: /* too slow? speed it up. */
1.35 tedu 88: while (r > 4 && duration > CLOCKS_PER_SEC / 2) {
1.29 tedu 89: r -= 1;
90: duration /= 2;
91: }
92:
93: return r;
94: }
95:
96:
1.15 millert 97: void
98: print_passwd(char *string, int operation, void *extra)
1.5 provos 99: {
1.34 tedu 100: char buffer[_PASSWORD_LEN];
1.15 millert 101:
1.33 tedu 102: if (operation == DO_BLF) {
1.34 tedu 103: int rounds = *(int *)extra;
104: if (bcrypt_newhash(string, rounds, buffer, sizeof(buffer)) != 0)
1.33 tedu 105: errx(1, "bcrypt newhash failed");
106: fputs(buffer, stdout);
107: return;
1.34 tedu 108: } else {
109: login_cap_t *lc;
110: const char *pref;
1.15 millert 111:
1.18 millert 112: if ((lc = login_getclass(extra)) == NULL)
113: errx(1, "unable to get login class `%s'",
114: extra ? (char *)extra : "default");
1.34 tedu 115: pref = login_getcapstr(lc, "localcipher", NULL, NULL);
116: if (crypt_newhash(string, pref, buffer, sizeof(buffer)) != 0)
117: errx(1, "can't generate hash");
1.15 millert 118: }
119:
1.34 tedu 120: fputs(buffer, stdout);
1.5 provos 121: }
122:
1.15 millert 123: int
124: main(int argc, char **argv)
1.1 downsj 125: {
1.15 millert 126: int opt;
127: int operation = -1;
128: int prompt = 0;
129: int rounds;
1.18 millert 130: void *extra = NULL; /* Store salt or number of rounds */
1.27 jdixon 131: const char *errstr;
1.15 millert 132:
1.34 tedu 133: while ((opt = getopt(argc, argv, "pb:c:")) != -1) {
1.15 millert 134: switch (opt) {
135: case 'p':
136: prompt = 1;
137: break;
138: case 'b': /* Blowfish password hash */
139: if (operation != -1)
140: usage();
141: operation = DO_BLF;
1.29 tedu 142: if (strcmp(optarg, "a") == 0)
143: rounds = ideal_rounds();
1.36 ! deraadt 144: else {
1.29 tedu 145: rounds = strtonum(optarg, 1, INT_MAX, &errstr);
1.36 ! deraadt 146: if (errstr != NULL)
! 147: errx(1, "%s: %s", errstr, optarg);
! 148: }
1.15 millert 149: extra = &rounds;
1.18 millert 150: break;
151: case 'c': /* user login class */
152: extra = optarg;
153: operation = -1;
1.15 millert 154: break;
155: default:
156: usage();
157: }
1.1 downsj 158: }
159:
1.34 tedu 160: if (((argc - optind) < 1)) {
1.15 millert 161: char line[BUFSIZ], *string;
1.1 downsj 162:
1.15 millert 163: if (prompt) {
1.20 otto 164: if ((string = getpass("Enter string: ")) == NULL)
165: err(1, "getpass");
1.15 millert 166: print_passwd(string, operation, extra);
167: (void)fputc('\n', stdout);
168: } else {
1.28 krw 169: size_t len;
1.15 millert 170: /* Encrypt stdin to stdout. */
171: while (!feof(stdin) &&
172: (fgets(line, sizeof(line), stdin) != NULL)) {
1.28 krw 173: len = strlen(line);
174: if (len == 0 || line[0] == '\n')
1.15 millert 175: continue;
1.28 krw 176: if (line[len - 1] == '\n')
177: line[len - 1] = '\0';
178:
179: print_passwd(line, operation, extra);
1.15 millert 180:
181: (void)fputc('\n', stdout);
182: }
183: }
1.9 alex 184: } else {
1.15 millert 185: char *string;
186:
187: /* can't combine -p with a supplied string */
188: if (prompt)
189: usage();
190:
191: /* Perhaps it isn't worth worrying about, but... */
192: if ((string = strdup(argv[optind])) == NULL)
193: err(1, NULL);
194: /* Wipe the argument. */
195: memset(argv[optind], 0, strlen(argv[optind]));
196:
1.9 alex 197: print_passwd(string, operation, extra);
198:
1.15 millert 199: (void)fputc('\n', stdout);
200:
201: /* Wipe our copy, before we free it. */
202: memset(string, 0, strlen(string));
203: free(string);
1.1 downsj 204: }
1.15 millert 205: exit(0);
1.1 downsj 206: }