1 /* $OpenBSD: tokeninit.c,v 1.11 2016/02/12 00:10:59 mmcc 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 cds.rlim_cur = 0; 79 cds.rlim_max = 0; 80 if (setrlimit(RLIMIT_CORE, &cds) < 0) 81 syslog(LOG_ERR, "couldn't set core dump size to 0: %m"); 82 83 if (token_init(argv[0]) < 0) { 84 syslog(LOG_ERR, "unknown token type"); 85 errx(1, "unknown token type"); 86 } 87 88 if (tt->options & TOKEN_HEXINIT) 89 optstr = "fhm:sv"; 90 else 91 optstr = "fm:sv"; 92 93 while ((c = getopt(argc, argv, optstr)) != -1) 94 switch (c) { 95 case 'f': /* force initialize existing user account */ 96 cmd |= TOKEN_FORCEINIT; 97 break; 98 99 case 'h': 100 hexformat = 1; 101 break; 102 103 case 'm': 104 if ((c = token_mode(optarg))) 105 modes |= c; 106 else 107 errx(1, "unknown mode"); 108 break; 109 110 case 's': /* generate seed during initialization */ 111 cmd |= TOKEN_GENSECRET; 112 break; 113 114 case 'v': /* verbose */ 115 verbose = 1; 116 break; 117 default: 118 fprintf(stderr, 119 "usage: %sinit [-f%ssv] [-m mode] user ...\n", 120 tt->name, (tt->options & TOKEN_HEXINIT) ? "h" : ""); 121 exit(1); 122 } 123 124 if ((modes & ~TOKEN_RIM) == 0) 125 modes |= tt->defmode; 126 127 argc -= optind; 128 argv = &argv[optind]; 129 130 while (argc--) { 131 if (verbose) { 132 printf("Adding %s to %s database\n", *argv, tt->proper); 133 fflush(stdout); 134 } 135 if (!(cmd & TOKEN_GENSECRET)) { 136 p = prompt_for_secret(hexformat, *argv); 137 if (!readpassphrase(p, seed, sizeof(seed), RPP_ECHO_ON) || 138 seed[0] == '\0') { 139 fprintf(stderr, 140 "%sinit: No seed supplied for token.\n", 141 tt->name); 142 exit(1); 143 } 144 memset(secret, 0, sizeof(secret)); 145 if (parse_secret(hexformat, seed, secret)) { 146 fprintf(stderr, 147 "%sinit: Invalid secret entered.\n", 148 tt->name); 149 exit(1); 150 } 151 } 152 switch (tokenuserinit(cmd, *argv, secret, modes)) { 153 case 0: 154 syslog(LOG_INFO, "User %s initialized in %s database", 155 *argv, tt->proper); 156 break; 157 case 1: 158 warnx("%s already exists in %s database!", 159 *argv, tt->proper); 160 syslog(LOG_INFO, "%s already exists in %s database", 161 *argv, tt->proper); 162 errors++; 163 break; 164 case -1: 165 warnx("Error initializing user %s in %s database.", 166 *argv, tt->proper); 167 syslog(LOG_INFO, 168 "Error initializing user %s in %s database: %m", 169 *argv, tt->proper); 170 errors++; 171 } 172 argv++; 173 } 174 exit(errors); 175 } 176 177 /* 178 * Parse the 8 octal numbers or a 16 digit hex string into a token secret 179 */ 180 181 static int 182 parse_secret(int hexformat, char *seed, unsigned char *secret) 183 { 184 int i; 185 unsigned int tmp[8]; 186 187 if (hexformat) { 188 if ((i = sscanf(seed, "%02x %02x %02x %02x %02x %02x %02x %02x", 189 &tmp[0], &tmp[1], &tmp[2], &tmp[3], 190 &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 191 return (-1); 192 } else { 193 if ((i = sscanf(seed, "%o %o %o %o %o %o %o %o", 194 &tmp[0], &tmp[1], &tmp[2], &tmp[3], 195 &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 196 return (-1); 197 } 198 for (i=0; i < 8; i++) 199 secret[i] = tmp[i] & 0xff; 200 201 return (0); 202 } 203 204 /* 205 * Prompt user for seed for token 206 */ 207 208 static char * 209 prompt_for_secret(int hexformat, char* username) 210 { 211 static char prompt[1024]; 212 if (hexformat) 213 snprintf(prompt, sizeof prompt, 214 "Enter a 16 digit hexadecimal number " 215 "as a seed for %s\'s token:\n", username); 216 else 217 snprintf(prompt, sizeof prompt, 218 "Enter a series of 8 3-digit octal numbers " 219 "as a seed for %s\'s token:\n", username); 220 return prompt; 221 } 222