1*af3189ecSmmcc /* $OpenBSD: tokeninit.c,v 1.11 2016/02/12 00:10:59 mmcc Exp $ */ 2851d2d47Smillert 3851d2d47Smillert /*- 4851d2d47Smillert * Copyright (c) 1995 Migration Associates Corp. All Rights Reserved 5851d2d47Smillert * 6851d2d47Smillert * Redistribution and use in source and binary forms, with or without 7851d2d47Smillert * modification, are permitted provided that the following conditions 8851d2d47Smillert * are met: 9851d2d47Smillert * 1. Redistributions of source code must retain the above copyright 10851d2d47Smillert * notice, this list of conditions and the following disclaimer. 11851d2d47Smillert * 2. Redistributions in binary form must reproduce the above copyright 12851d2d47Smillert * notice, this list of conditions and the following disclaimer in the 13851d2d47Smillert * documentation and/or other materials provided with the distribution. 14851d2d47Smillert * 3. All advertising materials mentioning features or use of this software 15851d2d47Smillert * must display the following acknowledgement: 16851d2d47Smillert * This product includes software developed by Berkeley Software Design, 17851d2d47Smillert * Inc. 18851d2d47Smillert * 4. The name of Berkeley Software Design, Inc. may not be used to endorse 19851d2d47Smillert * or promote products derived from this software without specific prior 20851d2d47Smillert * written permission. 21851d2d47Smillert * 22851d2d47Smillert * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND 23851d2d47Smillert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24851d2d47Smillert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25851d2d47Smillert * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE 26851d2d47Smillert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27851d2d47Smillert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28851d2d47Smillert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29851d2d47Smillert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30851d2d47Smillert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31851d2d47Smillert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32851d2d47Smillert * SUCH DAMAGE. 33851d2d47Smillert * 34851d2d47Smillert * BSDI $From: tokeninit.c,v 1.1 1996/08/26 20:27:28 prb Exp 35851d2d47Smillert */ 36851d2d47Smillert 37b9fc9a72Sderaadt #include <sys/signal.h> 38851d2d47Smillert #include <sys/resource.h> 39851d2d47Smillert #include <sys/time.h> 40851d2d47Smillert 41851d2d47Smillert #include <err.h> 42851d2d47Smillert #include <stdio.h> 43851d2d47Smillert #include <syslog.h> 44851d2d47Smillert #include <stdlib.h> 45851d2d47Smillert #include <unistd.h> 46b9fc9a72Sderaadt #include <limits.h> 47851d2d47Smillert #include <string.h> 48b4975d76Smarkus #include <readpassphrase.h> 49851d2d47Smillert 50851d2d47Smillert #include "token.h" 51851d2d47Smillert #include "tokendb.h" 52851d2d47Smillert 53b4975d76Smarkus static char *prompt_for_secret(int, char*); 54851d2d47Smillert static int parse_secret(int, char *, unsigned char *); 55851d2d47Smillert 56851d2d47Smillert int 57851d2d47Smillert main(int argc, char **argv) 58851d2d47Smillert { 592df81937Sderaadt unsigned int cmd = TOKEN_INITUSER; 60851d2d47Smillert int c; 61851d2d47Smillert int errors = 0; 62851d2d47Smillert int verbose = 0; 63851d2d47Smillert int hexformat = 0; 64851d2d47Smillert int modes = 0; 65851d2d47Smillert char seed[80]; 66851d2d47Smillert unsigned char secret[9]; 67851d2d47Smillert char *optstr; 68031569f0Smmcc char *p = NULL; 69851d2d47Smillert 70851d2d47Smillert struct rlimit cds; 71851d2d47Smillert 72851d2d47Smillert (void)signal(SIGQUIT, SIG_IGN); 73851d2d47Smillert (void)signal(SIGINT, SIG_IGN); 74851d2d47Smillert (void)setpriority(PRIO_PROCESS, 0, 0); 75851d2d47Smillert 76851d2d47Smillert openlog(NULL, LOG_ODELAY, LOG_AUTH); 77851d2d47Smillert 78851d2d47Smillert cds.rlim_cur = 0; 79851d2d47Smillert cds.rlim_max = 0; 80851d2d47Smillert if (setrlimit(RLIMIT_CORE, &cds) < 0) 81851d2d47Smillert syslog(LOG_ERR, "couldn't set core dump size to 0: %m"); 82851d2d47Smillert 83851d2d47Smillert if (token_init(argv[0]) < 0) { 84851d2d47Smillert syslog(LOG_ERR, "unknown token type"); 85851d2d47Smillert errx(1, "unknown token type"); 86851d2d47Smillert } 87851d2d47Smillert 88851d2d47Smillert if (tt->options & TOKEN_HEXINIT) 89851d2d47Smillert optstr = "fhm:sv"; 90851d2d47Smillert else 91851d2d47Smillert optstr = "fm:sv"; 92851d2d47Smillert 93d52e83b8Smpech while ((c = getopt(argc, argv, optstr)) != -1) 94851d2d47Smillert switch (c) { 95851d2d47Smillert case 'f': /* force initialize existing user account */ 96851d2d47Smillert cmd |= TOKEN_FORCEINIT; 97851d2d47Smillert break; 98851d2d47Smillert 99851d2d47Smillert case 'h': 10028056f30Sderaadt hexformat = 1; 101851d2d47Smillert break; 102851d2d47Smillert 103851d2d47Smillert case 'm': 104851d2d47Smillert if ((c = token_mode(optarg))) 105851d2d47Smillert modes |= c; 106851d2d47Smillert else 107851d2d47Smillert errx(1, "unknown mode"); 108851d2d47Smillert break; 109851d2d47Smillert 110851d2d47Smillert case 's': /* generate seed during initialization */ 111851d2d47Smillert cmd |= TOKEN_GENSECRET; 112851d2d47Smillert break; 113851d2d47Smillert 114851d2d47Smillert case 'v': /* verbose */ 11528056f30Sderaadt verbose = 1; 116851d2d47Smillert break; 117851d2d47Smillert default: 118851d2d47Smillert fprintf(stderr, 119572c5e09Ssobrado "usage: %sinit [-f%ssv] [-m mode] user ...\n", 120851d2d47Smillert tt->name, (tt->options & TOKEN_HEXINIT) ? "h" : ""); 121851d2d47Smillert exit(1); 122851d2d47Smillert } 123851d2d47Smillert 124851d2d47Smillert if ((modes & ~TOKEN_RIM) == 0) 125851d2d47Smillert modes |= tt->defmode; 126851d2d47Smillert 127851d2d47Smillert argc -= optind; 128851d2d47Smillert argv = &argv[optind]; 129851d2d47Smillert 130851d2d47Smillert while (argc--) { 131851d2d47Smillert if (verbose) { 132851d2d47Smillert printf("Adding %s to %s database\n", *argv, tt->proper); 133851d2d47Smillert fflush(stdout); 134851d2d47Smillert } 135851d2d47Smillert if (!(cmd & TOKEN_GENSECRET)) { 136b4975d76Smarkus p = prompt_for_secret(hexformat, *argv); 137b4975d76Smarkus if (!readpassphrase(p, seed, sizeof(seed), RPP_ECHO_ON) || 138b4975d76Smarkus seed[0] == '\0') { 139851d2d47Smillert fprintf(stderr, 140851d2d47Smillert "%sinit: No seed supplied for token.\n", 141851d2d47Smillert tt->name); 142851d2d47Smillert exit(1); 143851d2d47Smillert } 144851d2d47Smillert memset(secret, 0, sizeof(secret)); 145851d2d47Smillert if (parse_secret(hexformat, seed, secret)) { 146851d2d47Smillert fprintf(stderr, 147851d2d47Smillert "%sinit: Invalid secret entered.\n", 148851d2d47Smillert tt->name); 149851d2d47Smillert exit(1); 150851d2d47Smillert } 151851d2d47Smillert } 152851d2d47Smillert switch (tokenuserinit(cmd, *argv, secret, modes)) { 153851d2d47Smillert case 0: 154851d2d47Smillert syslog(LOG_INFO, "User %s initialized in %s database", 155851d2d47Smillert *argv, tt->proper); 156851d2d47Smillert break; 157851d2d47Smillert case 1: 15846347781Smpech warnx("%s already exists in %s database!", 159851d2d47Smillert *argv, tt->proper); 160851d2d47Smillert syslog(LOG_INFO, "%s already exists in %s database", 161851d2d47Smillert *argv, tt->proper); 162851d2d47Smillert errors++; 163851d2d47Smillert break; 164851d2d47Smillert case -1: 16546347781Smpech warnx("Error initializing user %s in %s database.", 166851d2d47Smillert *argv, tt->proper); 167851d2d47Smillert syslog(LOG_INFO, 168851d2d47Smillert "Error initializing user %s in %s database: %m", 169851d2d47Smillert *argv, tt->proper); 170851d2d47Smillert errors++; 171851d2d47Smillert } 172851d2d47Smillert argv++; 173851d2d47Smillert } 174851d2d47Smillert exit(errors); 175851d2d47Smillert } 176851d2d47Smillert 177851d2d47Smillert /* 178851d2d47Smillert * Parse the 8 octal numbers or a 16 digit hex string into a token secret 179851d2d47Smillert */ 180851d2d47Smillert 181851d2d47Smillert static int 182851d2d47Smillert parse_secret(int hexformat, char *seed, unsigned char *secret) 183851d2d47Smillert { 184851d2d47Smillert int i; 1852df81937Sderaadt unsigned int tmp[8]; 186851d2d47Smillert 187851d2d47Smillert if (hexformat) { 188851d2d47Smillert if ((i = sscanf(seed, "%02x %02x %02x %02x %02x %02x %02x %02x", 189851d2d47Smillert &tmp[0], &tmp[1], &tmp[2], &tmp[3], 190851d2d47Smillert &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 191851d2d47Smillert return (-1); 192851d2d47Smillert } else { 193851d2d47Smillert if ((i = sscanf(seed, "%o %o %o %o %o %o %o %o", 194851d2d47Smillert &tmp[0], &tmp[1], &tmp[2], &tmp[3], 195851d2d47Smillert &tmp[4], &tmp[5], &tmp[6], &tmp[7])) != 8) 196851d2d47Smillert return (-1); 197851d2d47Smillert } 198851d2d47Smillert for (i=0; i < 8; i++) 199851d2d47Smillert secret[i] = tmp[i] & 0xff; 200851d2d47Smillert 201851d2d47Smillert return (0); 202851d2d47Smillert } 203851d2d47Smillert 204851d2d47Smillert /* 205851d2d47Smillert * Prompt user for seed for token 206851d2d47Smillert */ 207851d2d47Smillert 208b4975d76Smarkus static char * 209851d2d47Smillert prompt_for_secret(int hexformat, char* username) 210851d2d47Smillert { 211b4975d76Smarkus static char prompt[1024]; 212851d2d47Smillert if (hexformat) 213b4975d76Smarkus snprintf(prompt, sizeof prompt, 214*af3189ecSmmcc "Enter a 16 digit hexadecimal number " 215851d2d47Smillert "as a seed for %s\'s token:\n", username); 216851d2d47Smillert else 217b4975d76Smarkus snprintf(prompt, sizeof prompt, 218b4975d76Smarkus "Enter a series of 8 3-digit octal numbers " 219851d2d47Smillert "as a seed for %s\'s token:\n", username); 220b4975d76Smarkus return prompt; 221851d2d47Smillert } 222