1 /* $OpenBSD: encrypt.c,v 1.49 2018/08/03 04:47:56 deraadt Exp $ */ 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> 29 #include <ctype.h> 30 #include <err.h> 31 #include <errno.h> 32 #include <pwd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <login_cap.h> 38 #include <limits.h> 39 #include <readpassphrase.h> 40 41 /* 42 * Very simple little program, for encrypting passwords from the command 43 * line. Useful for scripts and such. 44 */ 45 46 extern char *__progname; 47 48 static void __dead usage(void); 49 static void print_passwd(char *, int, char *); 50 51 #define DO_BLF 0 52 53 static void __dead 54 usage(void) 55 { 56 57 (void)fprintf(stderr, 58 "usage: %s [-b rounds] [-c class] [-p | string]\n", 59 __progname); 60 exit(1); 61 } 62 63 static void 64 print_passwd(char *string, int operation, char *extra) 65 { 66 char buffer[_PASSWORD_LEN]; 67 const char *pref; 68 char prefbuf[64]; 69 70 if (operation == DO_BLF) { 71 if (snprintf(prefbuf, sizeof(prefbuf), "blowfish,%s", extra) >= 72 sizeof(prefbuf)) 73 errx(1, "pref too long"); 74 pref = prefbuf; 75 } else { 76 login_cap_t *lc; 77 78 if ((lc = login_getclass(extra)) == NULL) 79 errx(1, "unable to get login class `%s'", 80 extra ? (char *)extra : "default"); 81 pref = login_getcapstr(lc, "localcipher", NULL, NULL); 82 } 83 if (crypt_newhash(string, pref, buffer, sizeof(buffer)) != 0) 84 err(1, "can't generate hash"); 85 86 fputs(buffer, stdout); 87 } 88 89 int 90 main(int argc, char **argv) 91 { 92 int opt; 93 int operation = -1; 94 int prompt = 0; 95 char *extra = NULL; /* Store login class or number of rounds */ 96 const char *errstr; 97 98 if (unveil(_PATH_LOGIN_CONF, "r") == -1) 99 err(1, "unveil"); 100 if (pledge("stdio rpath tty", NULL) == -1) 101 err(1, "pledge"); 102 103 while ((opt = getopt(argc, argv, "pb:c:")) != -1) { 104 switch (opt) { 105 case 'p': 106 prompt = 1; 107 break; 108 case 'b': /* Blowfish password hash */ 109 if (operation != -1) 110 usage(); 111 operation = DO_BLF; 112 if (strcmp(optarg, "a") != 0) { 113 (void)strtonum(optarg, 4, 31, &errstr); 114 if (errstr != NULL) 115 errx(1, "rounds is %s: %s", errstr, 116 optarg); 117 } 118 extra = optarg; 119 break; 120 case 'c': /* user login class */ 121 extra = optarg; 122 operation = -1; 123 break; 124 default: 125 usage(); 126 } 127 } 128 129 if (((argc - optind) < 1)) { 130 char line[BUFSIZ]; 131 char string[1024]; 132 133 if (prompt) { 134 if (readpassphrase("Enter string: ", string, 135 sizeof(string), RPP_ECHO_OFF) == NULL) 136 err(1, "readpassphrase"); 137 print_passwd(string, operation, extra); 138 (void)fputc('\n', stdout); 139 explicit_bzero(string, sizeof(string)); 140 } else { 141 size_t len; 142 /* Encrypt stdin to stdout. */ 143 while (!feof(stdin) && 144 (fgets(line, sizeof(line), stdin) != NULL)) { 145 len = strlen(line); 146 if (len == 0 || line[0] == '\n') 147 continue; 148 if (line[len - 1] == '\n') 149 line[len - 1] = '\0'; 150 151 print_passwd(line, operation, extra); 152 153 (void)fputc('\n', stdout); 154 } 155 } 156 } else { 157 char *string; 158 159 /* can't combine -p with a supplied string */ 160 if (prompt) 161 usage(); 162 163 /* Perhaps it isn't worth worrying about, but... */ 164 if ((string = strdup(argv[optind])) == NULL) 165 err(1, NULL); 166 /* Wipe the argument. */ 167 explicit_bzero(argv[optind], strlen(argv[optind])); 168 169 print_passwd(string, operation, extra); 170 171 (void)fputc('\n', stdout); 172 173 /* Wipe our copy, before we free it. */ 174 freezero(string, strlen(string)); 175 } 176 return 0; 177 } 178