A BSD authentication module for duress passwords
1/* $OpenBSD$ */
2/*-
3 * Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software Design,
16 * Inc.
17 * 4. The name of Berkeley Software Design, Inc. may not be used to endorse
18 * or promote products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * BSDI $From: login_passwd.c,v 1.11 1997/08/08 18:58:24 prb Exp $
34 */
35
36#include "common.h"
37
38FILE *back = NULL;
39
40int
41main(int argc, char **argv)
42{
43 int opt, mode = 0, ret, lastchance = 0;
44 char *username, *password = NULL;
45 char pbuf[1024];
46 char response[1024];
47 char *wheel = NULL, *class = NULL;
48 struct passwd *pwd;
49
50 setpriority(PRIO_PROCESS, 0, 0);
51
52 openlog(NULL, LOG_ODELAY, LOG_AUTH);
53
54 while ((opt = getopt(argc, argv, "ds:v:")) != -1) {
55 switch (opt) {
56 case 'd':
57 back = stdout;
58 break;
59 case 's': /* service */
60 if (strcmp(optarg, "login") == 0)
61 mode = MODE_LOGIN;
62 else if (strcmp(optarg, "challenge") == 0)
63 mode = MODE_CHALLENGE;
64 else if (strcmp(optarg, "response") == 0)
65 mode = MODE_RESPONSE;
66 else {
67 syslog(LOG_ERR, "%s: invalid service", optarg);
68 exit(1);
69 }
70 break;
71 case 'v':
72 if (strncmp(optarg, "wheel=", 6) == 0)
73 wheel = optarg + 6;
74 else if (strncmp(optarg, "lastchance=", 11) == 0)
75 lastchance = (strcmp(optarg + 11, "yes") == 0);
76 /* Silently ignore unsupported variables */
77 break;
78 default:
79 syslog(LOG_ERR, "usage error1");
80 exit(1);
81 }
82 }
83
84 switch (argc - optind) {
85 case 2:
86 class = argv[optind + 1];
87 /*FALLTHROUGH*/
88 case 1:
89 username = argv[optind];
90 break;
91 default:
92 syslog(LOG_ERR, "usage error2");
93 exit(1);
94 }
95
96 /* get the password hash before pledge(2) or it will return '*' */
97 pwd = getpwnam_shadow(username);
98
99 if (pledge("stdio rpath tty id proc exec", NULL) == -1) {
100 syslog(LOG_ERR, "pledge: %m");
101 exit(1);
102 }
103
104 if (back == NULL && (back = fdopen(3, "r+")) == NULL) {
105 syslog(LOG_ERR, "reopening back channel: %m");
106 exit(1);
107 }
108
109 /*
110 * Read password, either as from the terminal or if the
111 * response mode is active from the caller program.
112 *
113 * XXX This is completely ungrokkable, and should be rewritten.
114 */
115 switch (mode) {
116 case MODE_RESPONSE: {
117 int count;
118 mode = 0;
119 count = -1;
120 while (++count < sizeof(response) &&
121 read(3, &response[count], 1) == 1) {
122 if (response[count] == '\0' && ++mode == 2)
123 break;
124 if (response[count] == '\0' && mode == 1) {
125 password = response + count + 1;
126 }
127 }
128 if (mode < 2) {
129 syslog(LOG_ERR, "protocol error on back channel");
130 exit(1);
131 }
132 break;
133 }
134
135 case MODE_LOGIN:
136 password = readpassphrase("Password:", pbuf, sizeof(pbuf), RPP_ECHO_OFF);
137 break;
138 case MODE_CHALLENGE:
139 fprintf(back, BI_AUTH "\n");
140 exit(0);
141 break;
142 default:
143 syslog(LOG_ERR, "%d: unknown mode", mode);
144 exit(1);
145 break;
146 }
147
148 ret = pwd_login(username, password, wheel, lastchance, class, pwd);
149
150 if (password != NULL)
151 explicit_bzero(password, strlen(password));
152 if (ret != AUTH_OK)
153 fprintf(back, BI_REJECT "\n");
154
155 closelog();
156
157 exit(0);
158}