login_token.c revision 1.6
147060Ssemenu/*	$OpenBSD: login_token.c,v 1.6 2002/06/02 01:27:16 deraadt Exp $	*/
247060Ssemenu
343552Ssemenu/*-
443552Ssemenu * Copyright (c) 1995, 1996 Berkeley Software Design, Inc. All rights reserved.
543552Ssemenu *
643552Ssemenu * Redistribution and use in source and binary forms, with or without
743552Ssemenu * modification, are permitted provided that the following conditions
843552Ssemenu * are met:
943552Ssemenu * 1. Redistributions of source code must retain the above copyright
1043552Ssemenu *    notice, this list of conditions and the following disclaimer.
1143552Ssemenu * 2. Redistributions in binary form must reproduce the above copyright
1243552Ssemenu *    notice, this list of conditions and the following disclaimer in the
1343552Ssemenu *    documentation and/or other materials provided with the distribution.
1443552Ssemenu * 3. All advertising materials mentioning features or use of this software
1543552Ssemenu *    must display the following acknowledgement:
1643552Ssemenu *      This product includes software developed by Berkeley Software Design,
1743552Ssemenu *      Inc.
1843552Ssemenu * 4. The name of Berkeley Software Design, Inc.  may not be used to endorse
1943552Ssemenu *    or promote products derived from this software without specific prior
2043552Ssemenu *    written permission.
2143552Ssemenu *
2243552Ssemenu * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
2343552Ssemenu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2443552Ssemenu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2543552Ssemenu * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
2643552Ssemenu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2743552Ssemenu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2850477Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2943552Ssemenu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3043552Ssemenu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3143552Ssemenu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3243552Ssemenu * SUCH DAMAGE.
3343552Ssemenu *
3443552Ssemenu *	BSDI $From: login_token.c,v 1.2 1996/09/04 05:33:05 prb Exp $
3543552Ssemenu */
3643552Ssemenu
3743552Ssemenu#include <sys/types.h>
3843552Ssemenu#include <sys/param.h>
3943552Ssemenu#include <sys/time.h>
4043552Ssemenu#include <sys/resource.h>
4147060Ssemenu
4243552Ssemenu#include <err.h>
4347060Ssemenu#include <readpassphrase.h>
4443552Ssemenu#include <signal.h>
4543552Ssemenu#include <stdio.h>
4643552Ssemenu#include <syslog.h>
4743552Ssemenu#include <stdlib.h>
4843552Ssemenu#include <string.h>
4943552Ssemenu#include <unistd.h>
5043552Ssemenu#include <login_cap.h>
5143552Ssemenu#include <bsd_auth.h>
5243552Ssemenu
5344142Ssemenu#include "token.h"
5443552Ssemenu
5543552Ssemenuint
5643552Ssemenumain(argc, argv)
5743552Ssemenu	int argc;
5843552Ssemenu	char **argv;
5943552Ssemenu{
6043552Ssemenu	FILE *back = NULL;
6143552Ssemenu	char *class = 0;
6243552Ssemenu	char *username = 0;
6343552Ssemenu	char *instance;
6443552Ssemenu	char challenge[1024];
6543552Ssemenu	char response[1024];
6643552Ssemenu	char *pp = 0;
6743552Ssemenu	int c;
6843552Ssemenu	int mode = 0;
6943552Ssemenu	struct rlimit cds;
7043552Ssemenu	sigset_t blockset;
7143552Ssemenu
7243552Ssemenu	(void)setpriority(PRIO_PROCESS, 0, 0);
7343552Ssemenu
7443552Ssemenu	/* We block keyboard-generated signals during database accesses. */
7543552Ssemenu	sigemptyset(&blockset);
7643552Ssemenu	sigaddset(&blockset, SIGINT);
7743552Ssemenu	sigaddset(&blockset, SIGQUIT);
7843552Ssemenu	sigaddset(&blockset, SIGTSTP);
7943552Ssemenu
8043552Ssemenu	openlog(NULL, LOG_ODELAY, LOG_AUTH);
8143552Ssemenu
8243552Ssemenu	cds.rlim_cur = 0;
8343552Ssemenu	cds.rlim_max = 0;
8443552Ssemenu	if (setrlimit(RLIMIT_CORE, &cds) < 0)
8543552Ssemenu		syslog(LOG_ERR, "couldn't set core dump size to 0: %m");
8643552Ssemenu
8743552Ssemenu	(void)sigprocmask(SIG_BLOCK, &blockset, NULL);
8843552Ssemenu	if (token_init(argv[0]) < 0) {
8943552Ssemenu		syslog(LOG_ERR, "unknown token type");
9043552Ssemenu		errx(1, "unknown token type");
9143552Ssemenu	}
9243552Ssemenu	(void)sigprocmask(SIG_UNBLOCK, &blockset, NULL);
9343552Ssemenu
9443552Ssemenu	while ((c = getopt(argc, argv, "ds:v:")) != -1)
9543552Ssemenu		switch (c) {
9643552Ssemenu		case 'd':		/* to remain undocumented */
9743552Ssemenu			back = stdout;
9843552Ssemenu			break;
9943552Ssemenu		case 'v':
10043552Ssemenu			break;
10143552Ssemenu		case 's':	/* service */
10243552Ssemenu			if (strcmp(optarg, "login") == 0)
10343552Ssemenu				mode = 0;
10443552Ssemenu			else if (strcmp(optarg, "challenge") == 0)
10544142Ssemenu				mode = 1;
10643552Ssemenu			else if (strcmp(optarg, "response") == 0)
10743552Ssemenu				mode = 2;
10843552Ssemenu			else {
10943552Ssemenu				syslog(LOG_ERR, "%s: invalid service", optarg);
11043552Ssemenu				exit(1);
11143552Ssemenu			}
11243552Ssemenu			break;
11343552Ssemenu		default:
11443552Ssemenu			syslog(LOG_ERR, "usage error");
11543552Ssemenu			exit(1);
11643552Ssemenu		}
11743552Ssemenu
11843552Ssemenu	switch (argc - optind) {
119	case 2:
120		class = argv[optind + 1];
121	case 1:
122		username = argv[optind];
123		break;
124	default:
125		syslog(LOG_ERR, "usage error");
126		exit(1);
127	}
128
129
130	if (back == NULL && (back = fdopen(3, "r+")) == NULL)  {
131		syslog(LOG_ERR, "reopening back channel");
132		exit(1);
133	}
134	if (mode == 2) {
135		mode = 0;
136		c = -1;
137		while (++c < sizeof(challenge) &&
138		    read(3, &challenge[c], 1) == 1) {
139			if (challenge[c] == '\0' && ++mode == 2)
140				break;
141			if (challenge[c] == '\0' && mode == 1)
142				pp = challenge + c + 1;
143		}
144		if (mode < 2) {
145			syslog(LOG_ERR, "protocol error on back channel");
146			exit(1);
147		}
148	} else {
149		(void)sigprocmask(SIG_BLOCK, &blockset, NULL);
150		tokenchallenge(username, challenge, sizeof(challenge),
151		    tt->proper);
152		(void)sigprocmask(SIG_UNBLOCK, &blockset, NULL);
153		if (mode == 1) {
154			fprintf(back, BI_VALUE " challenge %s\n",
155			    auth_mkvalue(challenge));
156			fprintf(back, BI_CHALLENGE "\n");
157			exit(0);
158		}
159
160		pp = readpassphrase(challenge, response, sizeof(response), 0);
161		if (!pp || *pp == '\0') {
162			char buf[64];
163			snprintf(buf, sizeof(buf), "%s Response [echo on]: ",
164			    tt->proper);
165			pp = readpassphrase(buf, response, sizeof(response),
166			    RPP_ECHO_ON);
167		}
168	}
169
170	(void)sigprocmask(SIG_BLOCK, &blockset, NULL);
171	if (tokenverify(username, challenge, pp) == 0) {
172		fprintf(back, BI_AUTH "\n");
173
174		if ((instance = strchr(username, '.'))) {
175			*instance++ = 0;
176			if (strcmp(instance, "root") == 0)
177				fprintf(back, BI_ROOTOKAY "\n");
178		}
179		fprintf(back, BI_SECURE "\n");
180		exit(0);
181	}
182
183	fprintf(back, BI_REJECT "\n");
184	exit(1);
185}
186