1/* $OpenBSD: encrypt.c,v 1.52 2022/02/10 13:06:46 robert 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 46extern char *__progname; 47 48static void __dead usage(void); 49static void print_passwd(char *, int, char *); 50 51#define DO_BLF 0 52 53static void __dead 54usage(void) 55{ 56 57 (void)fprintf(stderr, 58 "usage: %s [-b rounds] [-c class] [-p | string]\n", 59 __progname); 60 exit(1); 61} 62 63static void 64print_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 89int 90main(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 %s", _PATH_LOGIN_CONF); 100 if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1) 101 err(1, "unveil %s.db", _PATH_LOGIN_CONF); 102 if (unveil(_PATH_LOGIN_CONF_D, "r") == -1) 103 err(1, "unveil %s", _PATH_LOGIN_CONF_D); 104 if (pledge("stdio rpath tty", NULL) == -1) 105 err(1, "pledge"); 106 107 while ((opt = getopt(argc, argv, "pb:c:")) != -1) { 108 switch (opt) { 109 case 'p': 110 prompt = 1; 111 break; 112 case 'b': /* Blowfish password hash */ 113 if (operation != -1) 114 usage(); 115 operation = DO_BLF; 116 if (strcmp(optarg, "a") != 0) { 117 (void)strtonum(optarg, 4, 31, &errstr); 118 if (errstr != NULL) 119 errx(1, "rounds is %s: %s", errstr, 120 optarg); 121 } 122 extra = optarg; 123 break; 124 case 'c': /* user login class */ 125 extra = optarg; 126 operation = -1; 127 break; 128 default: 129 usage(); 130 } 131 } 132 133 if (((argc - optind) < 1)) { 134 char line[BUFSIZ]; 135 char string[1024]; 136 137 if (prompt) { 138 if (readpassphrase("Enter string: ", string, 139 sizeof(string), RPP_ECHO_OFF) == NULL) 140 err(1, "readpassphrase"); 141 print_passwd(string, operation, extra); 142 (void)fputc('\n', stdout); 143 explicit_bzero(string, sizeof(string)); 144 } else { 145 size_t len; 146 /* Encrypt stdin to stdout. */ 147 while (!feof(stdin) && 148 (fgets(line, sizeof(line), stdin) != NULL)) { 149 len = strlen(line); 150 if (len == 0 || line[0] == '\n') 151 continue; 152 if (line[len - 1] == '\n') 153 line[len - 1] = '\0'; 154 155 print_passwd(line, operation, extra); 156 157 (void)fputc('\n', stdout); 158 } 159 } 160 } else { 161 char *string; 162 163 /* can't combine -p with a supplied string */ 164 if (prompt) 165 usage(); 166 167 /* Perhaps it isn't worth worrying about, but... */ 168 if ((string = strdup(argv[optind])) == NULL) 169 err(1, NULL); 170 /* Wipe the argument. */ 171 explicit_bzero(argv[optind], strlen(argv[optind])); 172 173 print_passwd(string, operation, extra); 174 175 (void)fputc('\n', stdout); 176 177 /* Wipe our copy, before we free it. */ 178 freezero(string, strlen(string)); 179 } 180 return 0; 181} 182