login_skey.c revision 1.1
1/*	$OpenBSD: login_skey.c,v 1.1 2000/12/12 02:35:18 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
58int
59main(argc, argv)
60	int argc;
61	char **argv;
62{
63	FILE *back = NULL;
64    	char *class = 0;
65    	char *username = 0;
66	struct skey skey;
67	char skeyprompt[SKEY_MAX_CHALLENGE+17];
68	char passbuf[SKEY_MAX_PW_LEN+1];
69	int c, haskey;
70	int mode = 0;
71	char *instance;
72
73	skeyprompt[0] = '\0';
74
75	(void)signal(SIGQUIT, SIG_IGN);
76	(void)signal(SIGINT, SIG_IGN);
77	(void)setpriority(PRIO_PROCESS, 0, 0);
78
79	openlog(NULL, LOG_ODELAY, LOG_AUTH);
80
81    	while ((c = getopt(argc, argv, "ds:v:")) != EOF)
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		haskey = (skeychallenge(&skey, username, skeyprompt) == 0);
155	} else {
156		/*
157		 * Attempt an S/Key challenge.
158		 * The OpenBSD skeychallenge() will always fill in a
159		 * challenge, even if it has to cons one up.
160		 */
161		haskey = (skeychallenge(&skey, username, skeyprompt) == 0);
162		strcat(skeyprompt, "\nS/Key Password: ");
163		if (mode == 1) {
164			fprintf(back, BI_VALUE " challenge %s\n",
165			    auth_mkvalue(skeyprompt));
166			fprintf(back, BI_CHALLENGE "\n");
167			exit(0);
168		}
169
170		readpassphrase(skeyprompt, passbuf, sizeof(passbuf), 0);
171		if (passbuf[0] == '\0') {
172			readpassphrase("S/Key Password [echo on]: ",
173			    passbuf, sizeof(passbuf), RPP_ECHO_ON);
174		}
175	}
176
177	if ((instance = strchr(username, '.')))
178		*instance++ = '\0';
179
180	if (haskey && skeyverify(&skey, passbuf) == 0) {
181		if (mode == 0) {
182			if (skey.n <= 1)
183				printf("Warning! You MUST change your S/Key password now!\n");
184			else if (skey.n < 5)
185				printf("Warning! Change S/Key password soon\n");
186		}
187		fprintf(back, BI_AUTH "\n");
188		if (instance && strcmp(instance, "root") == 0)
189			fprintf(back, BI_ROOTOKAY "\n");
190		fprintf(back, BI_SECURE "\n");
191		exit(0);
192	}
193	fprintf(back, BI_REJECT "\n");
194	exit(1);
195}
196