login_skey.c revision 1.5
1/*	$OpenBSD: login_skey.c,v 1.5 2001/12/06 05:37:04 millert Exp $	*/
2
3/*-
4 * Copyright (c) 1995 Berkeley Software Design, Inc. 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: login_skey.c,v 1.3 1996/09/04 05:24:56 prb Exp $
35 */
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/stat.h>
39#include <sys/time.h>
40#include <sys/resource.h>
41
42#include <ctype.h>
43#include <fcntl.h>
44#include <paths.h>
45#include <pwd.h>
46#include <readpassphrase.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <syslog.h>
51#include <unistd.h>
52
53#include <login_cap.h>
54#include <bsd_auth.h>
55#include <sha1.h>
56#include <skey.h>
57
58void timedout __P((int));
59
60int
61main(argc, argv)
62	int argc;
63	char **argv;
64{
65	FILE *back = NULL;
66    	char *class = 0;
67    	char *username = 0;
68	struct skey skey;
69	char skeyprompt[SKEY_MAX_CHALLENGE+17];
70	char passbuf[SKEY_MAX_PW_LEN+1];
71	int c, haskey;
72	int mode = 0;
73
74	skeyprompt[0] = '\0';
75
76	(void)signal(SIGALRM, timedout);
77	(void)setpriority(PRIO_PROCESS, 0, 0);
78
79	openlog(NULL, LOG_ODELAY, LOG_AUTH);
80
81    	while ((c = getopt(argc, argv, "ds:v:")) != -1)
82		switch(c) {
83		case 'd':	/* to remain undocumented */
84			back = stdout;
85			break;
86		case 'v':
87			break;
88		case 's':	/* service */
89			if (strcmp(optarg, "login") == 0)
90				mode = 0;
91			else if (strcmp(optarg, "challenge") == 0)
92				mode = 1;
93			else if (strcmp(optarg, "response") == 0)
94				mode = 2;
95			else {
96				syslog(LOG_ERR, "%s: invalid service", optarg);
97				exit(1);
98			}
99			break;
100		default:
101			syslog(LOG_ERR, "usage error");
102			exit(1);
103		}
104
105	switch(argc - optind) {
106	case 2:
107		class = argv[optind + 1];
108	case 1:
109		username = argv[optind];
110		break;
111	default:
112		syslog(LOG_ERR, "usage error");
113		exit(1);
114	}
115
116
117	if (back == NULL && (back = fdopen(3, "r+")) == NULL)  {
118		syslog(LOG_ERR, "reopening back channel: %m");
119		exit(1);
120	}
121
122	if (mode == 2) {
123		mode = 0;
124		c = -1;
125		/* XXX - redo these loops! */
126		while (++c < sizeof(skeyprompt) &&
127		    read(3, &skeyprompt[c], 1) == 1) {
128			if (skeyprompt[c] == '\0') {
129				mode++;
130				break;
131			}
132		}
133		if (mode == 1) {
134			c = -1;
135			while (++c < sizeof(passbuf) &&
136			    read(3, &passbuf[c], 1) == 1) {
137				if (passbuf[c] == '\0') {
138					mode++;
139					break;
140				}
141			}
142		}
143		if (mode < 2) {
144			syslog(LOG_ERR, "protocol error on back channel");
145			exit(1);
146		}
147		/*
148		 * Sigh.  S/Key really is a stateful protocol.
149		 * We must assume that a user will only try to
150		 * authenticate one at a time and that this call to
151		 * skeychallenge will produce the same results as
152		 * the call to skeychallenge when mode was 1.
153		 *
154		 * Furthermore, RFC2289 requires that an entry be
155		 * locked against a partial guess race which is
156		 * simply not possible if the calling program queries
157		 * the user for the passphrase itself.  Oh well.
158		 */
159		haskey = (skeychallenge(&skey, username, skeyprompt) == 0);
160	} else {
161		/*
162		 * Attempt an S/Key challenge.
163		 * The OpenBSD skeychallenge() will always fill in a
164		 * challenge, even if it has to cons one up.
165		 */
166		haskey = (skeychallenge(&skey, username, skeyprompt) == 0);
167		strcat(skeyprompt, "\nS/Key Password: ");
168		if (mode == 1) {
169			fprintf(back, BI_VALUE " challenge %s\n",
170			    auth_mkvalue(skeyprompt));
171			fprintf(back, BI_CHALLENGE "\n");
172			exit(0);
173		}
174
175		/* Time out getting passphrase after 2 minutes to avoid a DoS */
176		if (haskey)
177			alarm(120);
178		readpassphrase(skeyprompt, passbuf, sizeof(passbuf), 0);
179		if (passbuf[0] == '\0')
180			readpassphrase("S/Key Password [echo on]: ",
181			    passbuf, sizeof(passbuf), RPP_ECHO_ON);
182		alarm(0);
183	}
184
185	if (haskey && skeyverify(&skey, passbuf) == 0) {
186		if (mode == 0) {
187			if (skey.n <= 1)
188				printf("Warning! You MUST change your "
189				    "S/Key password now!\n");
190			else if (skey.n < 5)
191				printf("Warning! Change S/Key password soon\n");
192		}
193		fprintf(back, BI_AUTH "\n");
194		fprintf(back, BI_SECURE "\n");
195		exit(0);
196	}
197	fprintf(back, BI_REJECT "\n");
198	exit(1);
199}
200
201void
202timedout(signo)
203	int signo;
204{
205
206	_exit(1);
207}
208