1 /* $NetBSD: pwhash.c,v 1.14 2006/03/05 08:50:58 christos Exp $ */ 2 /* $OpenBSD: encrypt.c,v 1.16 2002/02/16 21:27:45 millert Exp $ */ 3 4 /* 5 * Copyright (c) 1996, Jason Downs. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 #include <sys/cdefs.h> 29 30 #ifndef lint 31 __RCSID("$NetBSD: pwhash.c,v 1.14 2006/03/05 08:50:58 christos Exp $"); 32 #endif 33 34 #include <sys/types.h> 35 #include <ctype.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <pwd.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <limits.h> 44 #include <login_cap.h> 45 #include <util.h> 46 47 /* 48 * Very simple little program, for encrypting passwords from the command 49 * line. Useful for scripts and such. 50 */ 51 52 #define DO_MAKEKEY 0 53 #define DO_DES 1 54 #define DO_MD5 2 55 #define DO_BLF 3 56 #define DO_SHA1 4 57 58 static void 59 usage(void) 60 { 61 62 (void)fprintf(stderr, 63 "Usage: %s [-km] [-b rounds] [-S rounds] [-s salt] [-p | string]\n", 64 getprogname()); 65 exit(1); 66 } 67 68 static char * 69 trim(char *line) 70 { 71 char *ptr; 72 73 for (ptr = &line[strlen(line) - 1]; ptr > line; ptr--) { 74 if (!isspace((unsigned char)*ptr)) 75 break; 76 } 77 ptr[1] = '\0'; 78 79 for (ptr = line; *ptr && isspace((unsigned char)*ptr); ptr++) 80 continue; 81 82 return ptr; 83 } 84 85 static void 86 print_passwd(char *string, int operation, const char *extra) 87 { 88 char buf[_PASSWORD_LEN]; 89 char option[LINE_MAX], *key, *opt; 90 int error = 0; 91 const char *salt = buf; 92 93 switch(operation) { 94 case DO_MAKEKEY: 95 /* 96 * makekey mode: parse string into separate DES key and salt. 97 */ 98 if (strlen(string) != 10) { 99 /* To be compatible... */ 100 error = EFTYPE; 101 break; 102 } 103 salt = &string[8]; 104 break; 105 106 case DO_MD5: 107 error = pw_gensalt(buf, _PASSWORD_LEN, "md5", extra); 108 break; 109 110 case DO_SHA1: 111 error = pw_gensalt(buf, _PASSWORD_LEN, "sha1", extra); 112 break; 113 114 case DO_BLF: 115 error = pw_gensalt(buf, _PASSWORD_LEN, "blowfish", extra); 116 break; 117 118 case DO_DES: 119 salt = extra; 120 break; 121 122 default: 123 pw_getconf(option, sizeof(option), "default", "localcipher"); 124 opt = option; 125 key = strsep(&opt, ","); 126 error = pw_gensalt(buf, _PASSWORD_LEN, key, opt); 127 break; 128 } 129 130 if (error) 131 err(1, "Cannot generate salt"); 132 133 (void)fputs(crypt(string, salt), stdout); 134 } 135 136 int 137 main(int argc, char **argv) 138 { 139 int opt; 140 int operation = -1; 141 int prompt = 0; 142 const char *extra = NULL; /* Store salt or number of rounds */ 143 144 setprogname(argv[0]); 145 146 if (strcmp(getprogname(), "makekey") == 0) 147 operation = DO_MAKEKEY; 148 149 while ((opt = getopt(argc, argv, "kmpS:s:b:")) != -1) { 150 switch (opt) { 151 case 'k': /* Stdin/Stdout Unix crypt */ 152 if (operation != -1 || prompt) 153 usage(); 154 operation = DO_MAKEKEY; 155 break; 156 157 case 'm': /* MD5 password hash */ 158 if (operation != -1) 159 usage(); 160 operation = DO_MD5; 161 extra = NULL; 162 break; 163 164 case 'p': 165 if (operation == DO_MAKEKEY) 166 usage(); 167 prompt = 1; 168 break; 169 170 case 'S': /* SHA1 password hash */ 171 if (operation != -1) 172 usage(); 173 operation = DO_SHA1; 174 extra = optarg; 175 break; 176 177 case 's': /* Unix crypt (DES) */ 178 if (operation != -1 || optarg[0] == '$') 179 usage(); 180 operation = DO_DES; 181 extra = optarg; 182 break; 183 184 case 'b': /* Blowfish password hash */ 185 if (operation != -1) 186 usage(); 187 operation = DO_BLF; 188 extra = optarg; 189 break; 190 191 default: 192 usage(); 193 } 194 } 195 196 if (((argc - optind) < 1) || operation == DO_MAKEKEY) { 197 char line[LINE_MAX], *string; 198 199 if (prompt) { 200 string = getpass("Enter string: "); 201 print_passwd(string, operation, extra); 202 (void)fputc('\n', stdout); 203 } else { 204 /* Encrypt stdin to stdout. */ 205 while (!feof(stdin) && 206 (fgets(line, sizeof(line), stdin) != NULL)) { 207 /* Kill the whitesapce. */ 208 string = trim(line); 209 if (*string == '\0') 210 continue; 211 212 print_passwd(string, operation, extra); 213 214 if (operation == DO_MAKEKEY) { 215 (void)fflush(stdout); 216 break; 217 } 218 (void)fputc('\n', stdout); 219 } 220 } 221 } else { 222 char *string; 223 224 /* can't combine -p with a supplied string */ 225 if (prompt) 226 usage(); 227 228 /* Perhaps it isn't worth worrying about, but... */ 229 if ((string = strdup(argv[optind])) == NULL) 230 err(1, NULL); 231 /* Wipe the argument. */ 232 (void)memset(argv[optind], 0, strlen(argv[optind])); 233 234 print_passwd(string, operation, extra); 235 236 (void)fputc('\n', stdout); 237 238 /* Wipe our copy, before we free it. */ 239 (void)memset(string, 0, strlen(string)); 240 free(string); 241 } 242 return 0; 243 } 244