1 /* $OpenBSD: tokeninit.c,v 1.13 2017/05/03 09:51:39 mestre Exp $ */ 2 3 /*- 4 * Copyright (c) 1995 Migration Associates Corp. 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Berkeley Software Design, 17 * Inc. 18 * 4. The name of Berkeley Software Design, Inc. may not be used to endorse 19 * or promote products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * BSDI $From: tokeninit.c,v 1.1 1996/08/26 20:27:28 prb Exp 35 */ 36 37 #include <sys/signal.h> 38 #include <sys/resource.h> 39 #include <sys/time.h> 40 41 #include <err.h> 42 #include <stdio.h> 43 #include <syslog.h> 44 #include <stdlib.h> 45 #include <unistd.h> 46 #include <limits.h> 47 #include <string.h> 48 #include <readpassphrase.h> 49 50 #include "token.h" 51 #include "tokendb.h" 52 53 static char *prompt_for_secret(int, char*); 54 static int parse_secret(int, char *, unsigned char *); 55 56 int 57 main(int argc, char **argv) 58 { 59 unsigned int cmd = TOKEN_INITUSER; 60 int c; 61 int errors = 0; 62 int verbose = 0; 63 int hexformat = 0; 64 int modes = 0; 65 char seed[80]; 66 unsigned char secret[9]; 67 char *optstr; 68 char *p = NULL; 69 70 struct rlimit cds; 71 72 (void)signal(SIGQUIT, SIG_IGN); 73 (void)signal(SIGINT, SIG_IGN); 74 (void)setpriority(PRIO_PROCESS, 0, 0); 75 76 openlog(NULL, LOG_ODELAY, LOG_AUTH); 77 78 /* 79 * Make sure we never dump core as we might have a 80 * valid user shared-secret in memory. 81 */ 82 83 cds.rlim_cur = 0; 84 cds.rlim_max = 0; 85 if (setrlimit(RLIMIT_CORE, &cds) < 0) 86 syslog(LOG_ERR, "couldn't set core dump size to 0: %m"); 87 88 if (pledge("stdio rpath wpath cpath fattr flock getpw tty", NULL) == -1) 89 err(1, "pledge"); 90 91 if (token_init(argv[0]) < 0) { 92 syslog(LOG_ERR, "unknown token type"); 93 errx(1, "unknown token type"); 94 } 95 96 if (tt->options & TOKEN_HEXINIT) 97 optstr = "fhm:sv"; 98 else 99 optstr = "fm:sv"; 100 101 while ((c = getopt(argc, argv, optstr)) != -1) 102 switch (c) { 103 case 'f': /* force initialize existing user account */ 104 cmd |= TOKEN_FORCEINIT; 105 break; 106 107 case 'h': 108 hexformat = 1; 109 break; 110 111 case 'm': 112 if ((c = token_mode(optarg))) 113 modes |= c; 114 else 115 errx(1, "unknown mode"); 116 break; 117 118 case 's': /* generate seed during initialization */ 119 cmd |= TOKEN_GENSECRET; 120 break; 121 122 case 'v': /* verbose */ 123 verbose = 1; 124 break; 125 default: 126 fprintf(stderr, 127 "usage: %sinit [-f%ssv] [-m mode] user ...\n", 128 tt->name, (tt->options & TOKEN_HEXINIT) ? "h" : ""); 129 exit(1); 130 } 131 132 if ((modes & ~TOKEN_RIM) == 0) 133 modes |= tt->defmode; 134 135 argc -= optind; 136 argv = &argv[optind]; 137 138 while (argc--) { 139 if (verbose) { 140 printf("Adding %s to %s database\n", *argv, tt->proper); 141 fflush(stdout); 142 } 143 if (!(cmd & TOKEN_GENSECRET)) { 144 p = prompt_for_secret(hexformat, *argv); 145 if (!readpassphrase(p, seed, sizeof(seed), RPP_ECHO_ON) || 146 seed[0] == '\0') { 147 fprintf(stderr, 148 "%sinit: No seed supplied for token.\n", 149 tt->name); 150 exit(1); 151 } 152 explicit_bzero(secret, sizeof(secret)); 153 if (parse_secret(hexformat, seed, secret)) { 154 fprintf(stderr, 155 "%sinit: Invalid secret entered.\n", 156 tt->name); 157 exit(1); 158 } 159 } 160 switch (tokenuserinit(cmd, *argv, secret, modes)) { 161 case 0: 162 syslog(LOG_INFO, "User %s initialized in %s database", 163 *argv, tt->proper); 164 break; 165 case 1: 166 warnx("%s already exists in %s database!", 167 *argv, tt->proper); 168 syslog(LOG_INFO, "%s already exists in %s database", 169 *argv, tt->proper); 170 errors++; 171 break; 172 case -1: 173 warnx("Error initializing user %s in %s database.", 174 *argv, tt->proper); 175 syslog(LOG_INFO, 176 "Error initializing user %s in %s database: %m", 177 *argv, tt->proper); 178 errors++; 179 } 180 argv++; 181 } 182 exit(errors); 183 } 184 185 /* 186 * Parse the 8 octal numbers or a 16 digit hex string into a token secret 187 */ 188 189 static int 190 parse_secret(int hexformat, char *seed, unsigned char *secret) 191 { 192 int i; 193 unsigned int tmp[8]; 194 195 if (hexformat) { 196 if ((i = sscanf(seed, "%02x %02x %02x %02x %02x %02x %02x %02x", 197 &tmp[0], &tmp[1], &tmp[2], &tmp[3], 198 &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 199 return (-1); 200 } else { 201 if ((i = sscanf(seed, "%o %o %o %o %o %o %o %o", 202 &tmp[0], &tmp[1], &tmp[2], &tmp[3], 203 &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 204 return (-1); 205 } 206 for (i=0; i < 8; i++) 207 secret[i] = tmp[i] & 0xff; 208 209 return (0); 210 } 211 212 /* 213 * Prompt user for seed for token 214 */ 215 216 static char * 217 prompt_for_secret(int hexformat, char* username) 218 { 219 static char prompt[1024]; 220 if (hexformat) 221 snprintf(prompt, sizeof prompt, 222 "Enter a 16 digit hexadecimal number " 223 "as a seed for %s\'s token:\n", username); 224 else 225 snprintf(prompt, sizeof prompt, 226 "Enter a series of 8 3-digit octal numbers " 227 "as a seed for %s\'s token:\n", username); 228 return prompt; 229 } 230