(void)strcpy(defaultseed, skey.seed); defaultseed[l - 1] = '0'; defaultseed[l] = '0'; defaultseed[l + 1] = '\0';
(void)strcpy(seed, skey.seed); seed[l - 1] = '0'; seed[l] = '0'; seed[l + 1] = '\0';
main(int argc, char **argv){	int     rval, i, l, n, defaultsetup, rmkey, hexmode, enable, convert;	char	hostname[MAXHOSTNAMELEN];	char	seed[SKEY_MAX_SEED_LEN + 2], defaultseed[SKEY_MAX_SEED_LEN + 1];	char    buf[256], key[SKEY_BINKEY_SIZE], filename[PATH_MAX], *ht;	char    lastc, me[UT_NAMESIZE + 1], *p, *auth_type;	struct skey skey;	struct passwd *pp;	n = rmkey = hexmode = enable = convert = 0;	defaultsetup = 1;	ht = auth_type = NULL;	/* Build up a default seed based on the hostname and time */	if (gethostname(hostname, sizeof(hostname)) < 0)		err(1, "gethostname");	for (i = 0, p = defaultseed; hostname[i] && i < SKEY_NAMELEN; i++) {		if (isalpha(hostname[i])) {			if (isupper(hostname[i]))				hostname[i] = tolower(hostname[i]);			*p++ = hostname[i];		} else if (isdigit(hostname[i]))			*p++ = hostname[i];	}	*p = '\0';	if ((pp = getpwuid(getuid())) == NULL)		err(1, "no user with uid %d", getuid());	(void)strcpy(me, pp->pw_name);	if ((pp = getpwnam(me)) == NULL)		err(1, "Who are you?");	for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) {		if (argv[i][2] == '\0') {			/* Single character switch */			switch (argv[i][1]) {			case 'a':				if (argv[++i] == NULL || argv[i][0] == '\0')					usage();				auth_type = argv[i];				break;			case 's':				defaultsetup = 0;				auth_type = "skey";				break;			case 'x':				hexmode = 1;				break;			case 'r':				rmkey = 1;				break;			case 'n':				if (argv[++i] == NULL || argv[i][0] == '\0')					usage();				if ((n = atoi(argv[i])) < 1 || n >= SKEY_MAX_SEQ)					errx(1, "count must be > 0 and < %d",					     SKEY_MAX_SEQ);				break;			case 'C':				convert = 1;				break;			case 'D':				enable = -1;				break;			case 'E':				enable = 1;				break;			default:				usage();			}		} else {			/* Multi character switches are hash types */			if ((ht = skey_set_algorithm(&argv[i][1])) == NULL) {				warnx("Unknown hash algorithm %s", &argv[i][1]);				usage();			}		}		i++;	}	argv += i;	argc -= i;	if (argc > 1 || (enable && convert) || (enable && argc) ||	    (convert && argc))		usage();	/* Handle -C, -D, and -E */	if (convert || enable) {		if (convert)			convert_db();		else			enable_db(enable);		exit(0);	}	/* Check for optional user string. */	if (argc == 1) {		if ((pp = getpwnam(argv[0])) == NULL) {			if (getuid() == 0) {				static struct passwd _pp;				_pp.pw_name = argv[0];				pp = &_pp;				warnx("Warning, user unknown: %s", argv[0]);			} else {				errx(1, "User unknown: %s", argv[0]);			}		} else if (strcmp(pp->pw_name, me) != 0 && getuid() != 0) {			/* Only root can change other's S/Keys. */			errx(1, "Permission denied.");		}	}	if (defaultsetup)		fputs("Reminder - Only use this method if you are directly "		    "connected\n           or have an encrypted channel.  If "		    "you are using telnet,\n           hit return now and use "		    "skeyinit -s.\n", stderr);	if (getuid() != 0) {		if ((pp = pw_dup(pp)) == NULL)			err(1, NULL);		if (!auth_userokay(pp->pw_name, auth_type, NULL, NULL))			errx(1, "Password incorrect");	}	/*	 * Lookup and lock the record we are about to modify.	 * If this is a new entry this will prevent other users	 * from appending new entries (and clobbering ours).	 */	rval = skeylookup(&skey, pp->pw_name);	switch (rval) {		case -1:			if (errno == ENOENT)				errx(1, "S/Key disabled");			else				err(1, "cannot open database");			break;		case 0:			/* remove user if asked to do so */			if (rmkey) {				if (snprintf(filename, sizeof(filename),				    "%s/%s", _PATH_SKEYDIR, pp->pw_name)				    >= sizeof(filename)) {					errno = ENAMETOOLONG;					err(1, "Cannot remove S/Key entry");				}				if (unlink(filename) != 0)					err(1, "Cannot remove S/Key entry");				printf("S/Key entry for %s removed.\n",				    pp->pw_name);				exit(0);			}			(void)printf("[Updating %s with %s]\n", pp->pw_name,			    ht ? ht : skey_get_algorithm());			(void)printf("Old seed: [%s] %s\n",				     skey_get_algorithm(), skey.seed);			/*			 * Sanity check old seed.			 */			l = strlen(skey.seed);			for (p = skey.seed; *p; p++) {				if (isalpha(*p)) {					if (isupper(*p))						*p = tolower(*p);				} else if (!isdigit(*p)) {					memmove(p, p + 1, l - (p - skey.seed));					l--;				}			}			/* If the seed ends in 0-8 just add one.  */			if (l > 0) {				lastc = skey.seed[l - 1];				if (isdigit(lastc) && lastc != '9') {					(void)strcpy(defaultseed, skey.seed);					defaultseed[l - 1] = lastc + 1;				}				if (isdigit(lastc) && lastc == '9' && l < 16) {					(void)strcpy(defaultseed, skey.seed);					defaultseed[l - 1] = '0';					defaultseed[l] = '0';					defaultseed[l + 1] = '\0';				}			}			break;		case 1:			if (rmkey)				errx(1, "You have no entry to remove.");			(void)printf("[Adding %s with %s]\n", pp->pw_name,			    ht ? ht : skey_get_algorithm());			if (snprintf(filename, sizeof(filename), "%s/%s",			    _PATH_SKEYDIR, pp->pw_name) >= sizeof(filename)) {				errno = ENAMETOOLONG;				err(1, "Cannot create S/Key entry");			}			if ((l = open(filename,			    O_RDWR | O_NONBLOCK | O_CREAT | O_TRUNC |O_NOFOLLOW,			    S_IRUSR | S_IWUSR)) == -1 ||			    flock(l, LOCK_EX) != 0 ||			    (skey.keyfile = fdopen(l, "r+")) == NULL)				err(1, "Cannot create S/Key entry");			break;	}	if (fchown(fileno(skey.keyfile), pp->pw_uid, -1) != 0 ||	    fchmod(fileno(skey.keyfile), S_IRUSR | S_IWUSR) != 0)		err(1, "can't set owner/mode for %s", pp->pw_name);	if (n == 0)		n = 99;	/* Set hash type if asked to */	if (ht && strcmp(ht, skey_get_algorithm()) != 0)		skey_set_algorithm(ht);	alarm(180);	if (!defaultsetup)		secure_mode(&n, key, seed, defaultseed, buf, sizeof(buf));	else		normal_mode(pp->pw_name, n, key, seed, defaultseed);	alarm(0);	/* XXX - why use malloc here? */	if ((skey.val = (char *)malloc(16 + 1)) == NULL)		err(1, "Can't allocate memory");	btoa8(skey.val, key);	(void)fseek(skey.keyfile, 0L, SEEK_SET);	(void)fprintf(skey.keyfile, "%s\n%s\n%04d\n%s\n%s\n",	    pp->pw_name, skey_get_algorithm(), n, seed, skey.val);	(void)fclose(skey.keyfile);	(void)printf("\nID %s skey is otp-%s %d %s\n", pp->pw_name,		     skey_get_algorithm(), n, seed);	(void)printf("Next login password: %s\n\n",	    hexmode ? put8(buf, key) : btoe(buf, key));	exit(0);}