sra.c revision 1.7 1 1.1 christos /*-
2 1.1 christos * Copyright (c) 1991, 1993
3 1.1 christos * Dave Safford. All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that the following conditions
7 1.1 christos * are met:
8 1.1 christos * 1. Redistributions of source code must retain the above copyright
9 1.1 christos * notice, this list of conditions and the following disclaimer.
10 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 christos * notice, this list of conditions and the following disclaimer in the
12 1.1 christos * documentation and/or other materials provided with the distribution.
13 1.1 christos * 3. Neither the name of the University nor the names of its contributors
14 1.1 christos * may be used to endorse or promote products derived from this software
15 1.1 christos * without specific prior written permission.
16 1.1 christos *
17 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 christos * SUCH DAMAGE.
28 1.1 christos *
29 1.1 christos */
30 1.1 christos
31 1.1 christos #include <sys/cdefs.h>
32 1.1 christos #ifdef notdef
33 1.1 christos __FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/sra.c,v 1.16 2002/05/06 09:48:02 markm Exp $");
34 1.1 christos #else
35 1.7 christos __RCSID("$NetBSD: sra.c,v 1.7 2005/10/25 22:03:34 christos Exp $");
36 1.1 christos #endif
37 1.1 christos
38 1.1 christos #ifdef SRA
39 1.1 christos #ifdef ENCRYPTION
40 1.1 christos #include <sys/types.h>
41 1.1 christos #include <arpa/telnet.h>
42 1.4 lukem #include <paths.h>
43 1.1 christos #include <pwd.h>
44 1.1 christos #include <stdio.h>
45 1.1 christos #include <stdlib.h>
46 1.1 christos #include <string.h>
47 1.1 christos #include <syslog.h>
48 1.1 christos #include <ttyent.h>
49 1.1 christos
50 1.1 christos #ifndef NOPAM
51 1.1 christos #include <security/pam_appl.h>
52 1.1 christos #else
53 1.1 christos #include <unistd.h>
54 1.1 christos #endif
55 1.1 christos
56 1.1 christos #include "auth.h"
57 1.1 christos #include "misc.h"
58 1.1 christos #include "encrypt.h"
59 1.1 christos #include "pk.h"
60 1.1 christos
61 1.1 christos char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
62 1.1 christos char *user, *pass, *xuser, *xpass;
63 1.7 christos char *passprompt, *xpassprompt;
64 1.7 christos size_t passpromptlen;
65 1.1 christos DesData ck;
66 1.1 christos IdeaData ik;
67 1.1 christos
68 1.1 christos extern int auth_debug_mode;
69 1.4 lukem extern char *line; /* see sys_term.c */
70 1.1 christos
71 1.1 christos static int sra_valid = 0;
72 1.1 christos static int passwd_sent = 0;
73 1.1 christos
74 1.1 christos static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
75 1.1 christos AUTHTYPE_SRA, };
76 1.1 christos
77 1.1 christos #define SRA_KEY 0
78 1.1 christos #define SRA_USER 1
79 1.1 christos #define SRA_CONTINUE 2
80 1.1 christos #define SRA_PASS 3
81 1.1 christos #define SRA_ACCEPT 4
82 1.1 christos #define SRA_REJECT 5
83 1.1 christos
84 1.1 christos static int check_user(char *, char *);
85 1.1 christos
86 1.1 christos /* support routine to send out authentication message */
87 1.1 christos static int
88 1.1 christos Data(Authenticator *ap, int type, void *d, int c)
89 1.1 christos {
90 1.1 christos unsigned char *p = str_data + 4;
91 1.1 christos unsigned char *cd = (unsigned char *)d;
92 1.1 christos
93 1.1 christos if (c == -1)
94 1.1 christos c = strlen((char *)cd);
95 1.1 christos
96 1.1 christos if (auth_debug_mode) {
97 1.1 christos printf("%s:%d: [%d] (%d)",
98 1.1 christos str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
99 1.1 christos str_data[3],
100 1.1 christos type, c);
101 1.1 christos printd(d, c);
102 1.1 christos printf("\r\n");
103 1.1 christos }
104 1.1 christos *p++ = ap->type;
105 1.1 christos *p++ = ap->way;
106 1.1 christos *p++ = type;
107 1.1 christos while (c-- > 0) {
108 1.1 christos if ((*p++ = *cd++) == IAC)
109 1.1 christos *p++ = IAC;
110 1.1 christos }
111 1.1 christos *p++ = IAC;
112 1.1 christos *p++ = SE;
113 1.1 christos if (str_data[3] == TELQUAL_IS)
114 1.1 christos printsub('>', &str_data[2], p - (&str_data[2]));
115 1.1 christos return(telnet_net_write(str_data, p - str_data));
116 1.1 christos }
117 1.1 christos
118 1.1 christos int
119 1.1 christos sra_init(Authenticator *ap __unused, int server)
120 1.1 christos {
121 1.1 christos if (server)
122 1.1 christos str_data[3] = TELQUAL_REPLY;
123 1.1 christos else
124 1.1 christos str_data[3] = TELQUAL_IS;
125 1.1 christos
126 1.1 christos user = (char *)malloc(256);
127 1.1 christos xuser = (char *)malloc(513);
128 1.1 christos pass = (char *)malloc(256);
129 1.1 christos xpass = (char *)malloc(513);
130 1.7 christos passprompt = (char *)malloc(256);
131 1.7 christos xpassprompt = (char *)malloc(513);
132 1.1 christos
133 1.1 christos if (user == NULL || xuser == NULL || pass == NULL || xpass ==
134 1.7 christos NULL || passprompt == NULL || xpassprompt == NULL)
135 1.1 christos return 0; /* malloc failed */
136 1.1 christos
137 1.7 christos strcpy(passprompt, "Password: ");
138 1.7 christos passpromptlen = strlen(passprompt);
139 1.1 christos passwd_sent = 0;
140 1.1 christos
141 1.1 christos genkeys(pka,ska);
142 1.1 christos return(1);
143 1.1 christos }
144 1.1 christos
145 1.1 christos /* client received a go-ahead for sra */
146 1.1 christos int
147 1.1 christos sra_send(Authenticator *ap)
148 1.1 christos {
149 1.1 christos /* send PKA */
150 1.1 christos
151 1.1 christos if (auth_debug_mode)
152 1.1 christos printf("Sent PKA to server.\r\n" );
153 1.1 christos printf("Trying SRA secure login:\r\n");
154 1.1 christos if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
155 1.1 christos if (auth_debug_mode)
156 1.1 christos printf("Not enough room for authentication data\r\n");
157 1.1 christos return(0);
158 1.1 christos }
159 1.1 christos
160 1.1 christos return(1);
161 1.1 christos }
162 1.1 christos
163 1.1 christos /* server received an IS -- could be SRA KEY, USER, or PASS */
164 1.1 christos void
165 1.1 christos sra_is(Authenticator *ap, unsigned char *data, int cnt)
166 1.1 christos {
167 1.1 christos int valid;
168 1.1 christos Session_Key skey;
169 1.1 christos
170 1.1 christos if (cnt-- < 1)
171 1.1 christos goto bad;
172 1.1 christos switch (*data++) {
173 1.1 christos
174 1.1 christos case SRA_KEY:
175 1.1 christos if (cnt < HEXKEYBYTES) {
176 1.1 christos Data(ap, SRA_REJECT, (void *)0, 0);
177 1.1 christos auth_finished(ap, AUTH_USER);
178 1.1 christos if (auth_debug_mode) {
179 1.1 christos printf("SRA user rejected for bad PKB\r\n");
180 1.1 christos }
181 1.1 christos return;
182 1.1 christos }
183 1.1 christos if (auth_debug_mode)
184 1.1 christos printf("Sent pka\r\n");
185 1.1 christos if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
186 1.1 christos if (auth_debug_mode)
187 1.1 christos printf("Not enough room\r\n");
188 1.1 christos return;
189 1.1 christos }
190 1.1 christos memcpy(pkb,data,HEXKEYBYTES);
191 1.1 christos pkb[HEXKEYBYTES] = '\0';
192 1.1 christos common_key(ska,pkb,&ik,&ck);
193 1.1 christos return;
194 1.1 christos
195 1.1 christos case SRA_USER:
196 1.1 christos /* decode KAB(u) */
197 1.1 christos if (cnt > 512) /* Attempted buffer overflow */
198 1.1 christos break;
199 1.1 christos memcpy(xuser,data,cnt);
200 1.1 christos xuser[cnt] = '\0';
201 1.1 christos pk_decode(xuser,user,&ck);
202 1.1 christos auth_encrypt_user(user);
203 1.7 christos #ifndef NOPAM
204 1.7 christos (void)check_user(user, "*");
205 1.7 christos #endif
206 1.7 christos pk_encode(passprompt,xpassprompt,&ck);
207 1.7 christos Data(ap, SRA_CONTINUE, (void *)xpassprompt, 512);
208 1.1 christos
209 1.1 christos return;
210 1.1 christos
211 1.1 christos case SRA_PASS:
212 1.1 christos if (cnt > 512) /* Attempted buffer overflow */
213 1.1 christos break;
214 1.1 christos /* decode KAB(P) */
215 1.1 christos memcpy(xpass,data,cnt);
216 1.1 christos xpass[cnt] = '\0';
217 1.1 christos pk_decode(xpass,pass,&ck);
218 1.1 christos
219 1.1 christos /* check user's password */
220 1.1 christos valid = check_user(user,pass);
221 1.1 christos
222 1.1 christos if(valid) {
223 1.5 lukem /* PAM (via check_user()) may have changed 'user' */
224 1.5 lukem auth_encrypt_user(user);
225 1.1 christos Data(ap, SRA_ACCEPT, (void *)0, 0);
226 1.1 christos skey.data = ck;
227 1.1 christos skey.type = SK_DES;
228 1.1 christos skey.length = 8;
229 1.1 christos encrypt_session_key(&skey, 1);
230 1.1 christos
231 1.1 christos sra_valid = 1;
232 1.1 christos auth_finished(ap, AUTH_VALID);
233 1.1 christos if (auth_debug_mode) {
234 1.1 christos printf("SRA user accepted\r\n");
235 1.1 christos }
236 1.1 christos }
237 1.1 christos else {
238 1.7 christos pk_encode(passprompt,xpassprompt,&ck);
239 1.7 christos Data(ap, SRA_CONTINUE, (void *)xpassprompt, 512);
240 1.1 christos /*
241 1.1 christos Data(ap, SRA_REJECT, (void *)0, 0);
242 1.1 christos sra_valid = 0;
243 1.1 christos auth_finished(ap, AUTH_REJECT);
244 1.1 christos */
245 1.1 christos if (auth_debug_mode) {
246 1.1 christos printf("SRA user failed\r\n");
247 1.1 christos }
248 1.1 christos }
249 1.1 christos return;
250 1.1 christos
251 1.1 christos default:
252 1.1 christos if (auth_debug_mode)
253 1.1 christos printf("Unknown SRA option %d\r\n", data[-1]);
254 1.1 christos }
255 1.1 christos bad:
256 1.1 christos Data(ap, SRA_REJECT, 0, 0);
257 1.1 christos sra_valid = 0;
258 1.1 christos auth_finished(ap, AUTH_REJECT);
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
262 1.1 christos void
263 1.1 christos sra_reply(Authenticator *ap, unsigned char *data, int cnt)
264 1.1 christos {
265 1.1 christos char uprompt[256],tuser[256];
266 1.1 christos Session_Key skey;
267 1.1 christos size_t i;
268 1.1 christos
269 1.1 christos if (cnt-- < 1)
270 1.1 christos return;
271 1.1 christos switch (*data++) {
272 1.1 christos
273 1.1 christos case SRA_KEY:
274 1.1 christos /* calculate common key */
275 1.1 christos if (cnt < HEXKEYBYTES) {
276 1.1 christos if (auth_debug_mode) {
277 1.1 christos printf("SRA user rejected for bad PKB\r\n");
278 1.1 christos }
279 1.1 christos return;
280 1.1 christos }
281 1.1 christos memcpy(pkb,data,HEXKEYBYTES);
282 1.1 christos pkb[HEXKEYBYTES] = '\0';
283 1.1 christos
284 1.1 christos common_key(ska,pkb,&ik,&ck);
285 1.1 christos
286 1.1 christos enc_user:
287 1.1 christos
288 1.1 christos /* encode user */
289 1.1 christos memset(tuser,0,sizeof(tuser));
290 1.1 christos sprintf(uprompt,"User (%s): ",UserNameRequested);
291 1.7 christos if (telnet_gets(uprompt,tuser,255,1) == NULL) {
292 1.7 christos printf("\n");
293 1.7 christos exit(1);
294 1.7 christos }
295 1.1 christos if (tuser[0] == '\n' || tuser[0] == '\r' )
296 1.1 christos strcpy(user,UserNameRequested);
297 1.1 christos else {
298 1.1 christos /* telnet_gets leaves the newline on */
299 1.1 christos for(i=0;i<sizeof(tuser);i++) {
300 1.1 christos if (tuser[i] == '\n') {
301 1.1 christos tuser[i] = '\0';
302 1.1 christos break;
303 1.1 christos }
304 1.1 christos }
305 1.1 christos strcpy(user,tuser);
306 1.1 christos }
307 1.1 christos pk_encode(user,xuser,&ck);
308 1.1 christos
309 1.1 christos /* send it off */
310 1.1 christos if (auth_debug_mode)
311 1.1 christos printf("Sent KAB(U)\r\n");
312 1.1 christos if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
313 1.1 christos if (auth_debug_mode)
314 1.1 christos printf("Not enough room\r\n");
315 1.1 christos return;
316 1.1 christos }
317 1.1 christos break;
318 1.1 christos
319 1.1 christos case SRA_CONTINUE:
320 1.1 christos if (passwd_sent) {
321 1.1 christos passwd_sent = 0;
322 1.1 christos printf("[ SRA login failed ]\r\n");
323 1.1 christos goto enc_user;
324 1.1 christos }
325 1.7 christos if (cnt > 512)
326 1.7 christos break;
327 1.7 christos memcpy(xpassprompt,data,cnt);
328 1.7 christos pk_decode(xpassprompt, passprompt, &ck);
329 1.1 christos /* encode password */
330 1.1 christos memset(pass,0,sizeof(pass));
331 1.7 christos if (telnet_gets(passprompt,pass,255,0) == NULL) {
332 1.7 christos printf("\n");
333 1.7 christos exit(1);
334 1.7 christos }
335 1.1 christos pk_encode(pass,xpass,&ck);
336 1.1 christos /* send it off */
337 1.1 christos if (auth_debug_mode)
338 1.1 christos printf("Sent KAB(P)\r\n");
339 1.1 christos if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
340 1.1 christos if (auth_debug_mode)
341 1.1 christos printf("Not enough room\r\n");
342 1.1 christos return;
343 1.1 christos }
344 1.1 christos passwd_sent = 1;
345 1.1 christos break;
346 1.1 christos
347 1.1 christos case SRA_REJECT:
348 1.1 christos printf("[ SRA refuses authentication ]\r\n");
349 1.1 christos printf("Trying plaintext login:\r\n");
350 1.1 christos auth_finished(0,AUTH_REJECT);
351 1.1 christos return;
352 1.1 christos
353 1.1 christos case SRA_ACCEPT:
354 1.1 christos printf("[ SRA accepts you ]\r\n");
355 1.1 christos skey.data = ck;
356 1.1 christos skey.type = SK_DES;
357 1.1 christos skey.length = 8;
358 1.1 christos encrypt_session_key(&skey, 0);
359 1.1 christos
360 1.1 christos auth_finished(ap, AUTH_VALID);
361 1.1 christos return;
362 1.1 christos default:
363 1.1 christos if (auth_debug_mode)
364 1.1 christos printf("Unknown SRA option %d\r\n", data[-1]);
365 1.1 christos return;
366 1.1 christos }
367 1.1 christos }
368 1.1 christos
369 1.1 christos int
370 1.1 christos sra_status(Authenticator *ap __unused, char *name, size_t len, int level)
371 1.1 christos {
372 1.1 christos if (level < AUTH_USER)
373 1.1 christos return(level);
374 1.1 christos if (UserNameRequested && sra_valid) {
375 1.1 christos strlcpy(name, UserNameRequested, len);
376 1.1 christos return(AUTH_VALID);
377 1.1 christos } else
378 1.1 christos return(AUTH_USER);
379 1.1 christos }
380 1.1 christos
381 1.1 christos #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
382 1.1 christos #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
383 1.1 christos
384 1.1 christos void
385 1.1 christos sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
386 1.1 christos {
387 1.1 christos char lbuf[32];
388 1.1 christos int i;
389 1.1 christos
390 1.1 christos buf[buflen-1] = '\0'; /* make sure its NULL terminated */
391 1.1 christos buflen -= 1;
392 1.1 christos
393 1.1 christos switch(data[3]) {
394 1.1 christos
395 1.1 christos case SRA_CONTINUE:
396 1.1 christos strncpy((char *)buf, " CONTINUE ", buflen);
397 1.1 christos goto common;
398 1.1 christos
399 1.1 christos case SRA_REJECT: /* Rejected (reason might follow) */
400 1.1 christos strncpy((char *)buf, " REJECT ", buflen);
401 1.1 christos goto common;
402 1.1 christos
403 1.1 christos case SRA_ACCEPT: /* Accepted (name might follow) */
404 1.1 christos strncpy((char *)buf, " ACCEPT ", buflen);
405 1.1 christos
406 1.1 christos common:
407 1.1 christos BUMP(buf, buflen);
408 1.1 christos if (cnt <= 4)
409 1.1 christos break;
410 1.1 christos ADDC(buf, buflen, '"');
411 1.1 christos for (i = 4; i < cnt; i++)
412 1.1 christos ADDC(buf, buflen, data[i]);
413 1.1 christos ADDC(buf, buflen, '"');
414 1.1 christos ADDC(buf, buflen, '\0');
415 1.1 christos break;
416 1.1 christos
417 1.1 christos case SRA_KEY: /* Authentication data follows */
418 1.1 christos strncpy((char *)buf, " KEY ", buflen);
419 1.1 christos goto common2;
420 1.1 christos
421 1.1 christos case SRA_USER:
422 1.1 christos strncpy((char *)buf, " USER ", buflen);
423 1.1 christos goto common2;
424 1.1 christos
425 1.1 christos case SRA_PASS:
426 1.1 christos strncpy((char *)buf, " PASS ", buflen);
427 1.1 christos goto common2;
428 1.1 christos
429 1.1 christos default:
430 1.1 christos sprintf(lbuf, " %d (unknown)", data[3]);
431 1.1 christos strncpy((char *)buf, lbuf, buflen);
432 1.1 christos common2:
433 1.1 christos BUMP(buf, buflen);
434 1.1 christos for (i = 4; i < cnt; i++) {
435 1.1 christos sprintf(lbuf, " %d", data[i]);
436 1.1 christos strncpy((char *)buf, lbuf, buflen);
437 1.1 christos BUMP(buf, buflen);
438 1.1 christos }
439 1.1 christos break;
440 1.1 christos }
441 1.1 christos }
442 1.1 christos
443 1.6 lukem #ifdef NOPAM
444 1.1 christos static int
445 1.1 christos isroot(const char *usr)
446 1.1 christos {
447 1.2 christos struct passwd pws, *pwd;
448 1.2 christos char pwbuf[1024];
449 1.1 christos
450 1.3 christos if (getpwnam_r(usr, &pws, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
451 1.3 christos pwd == NULL)
452 1.1 christos return 0;
453 1.1 christos return (!pwd->pw_uid);
454 1.1 christos }
455 1.1 christos
456 1.1 christos static int
457 1.4 lukem rootterm(const char *ttyname)
458 1.1 christos {
459 1.1 christos struct ttyent *t;
460 1.4 lukem const char *ttyn;
461 1.4 lukem
462 1.4 lukem ttyn = ttyname;
463 1.4 lukem if (strncmp(ttyn, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0)
464 1.4 lukem ttyn += sizeof(_PATH_DEV) - 1;
465 1.1 christos
466 1.1 christos return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
467 1.1 christos }
468 1.1 christos
469 1.1 christos static int
470 1.1 christos check_user(char *name, char *cred)
471 1.1 christos {
472 1.6 lukem struct passwd pws, *pw;
473 1.6 lukem char pwbuf[1024];
474 1.1 christos char *xpasswd, *salt;
475 1.1 christos
476 1.1 christos if (isroot(name) && !rootterm(line))
477 1.1 christos {
478 1.1 christos crypt("AA","*"); /* Waste some time to simulate success */
479 1.1 christos return(0);
480 1.1 christos }
481 1.1 christos
482 1.6 lukem if (getpwnam_r(name, &pws, pwbuf, sizeof(pwbuf), &pw) == 0 &&
483 1.6 lukem pw != NULL) {
484 1.1 christos if (pw->pw_shell == NULL) {
485 1.1 christos return(0);
486 1.1 christos }
487 1.1 christos
488 1.1 christos salt = pw->pw_passwd;
489 1.1 christos xpasswd = crypt(cred, salt);
490 1.1 christos /* The strcmp does not catch null passwords! */
491 1.6 lukem if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) {
492 1.1 christos return(0);
493 1.1 christos }
494 1.1 christos return(1);
495 1.1 christos }
496 1.1 christos return(0);
497 1.1 christos }
498 1.6 lukem #else /* !NOPAM */
499 1.1 christos
500 1.1 christos /*
501 1.1 christos * The following is stolen from ftpd, which stole it from the imap-uw
502 1.1 christos * PAM module and login.c. It is needed because we can't really
503 1.1 christos * "converse" with the user, having already gone to the trouble of
504 1.1 christos * getting their username and password through an encrypted channel.
505 1.1 christos */
506 1.1 christos
507 1.1 christos #define COPY_STRING(s) (s ? strdup(s):NULL)
508 1.1 christos
509 1.1 christos struct cred_t {
510 1.1 christos const char *uname;
511 1.1 christos const char *pass;
512 1.1 christos };
513 1.1 christos typedef struct cred_t cred_t;
514 1.1 christos
515 1.1 christos static int
516 1.1 christos auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
517 1.1 christos {
518 1.1 christos int i;
519 1.1 christos cred_t *cred = (cred_t *) appdata;
520 1.1 christos struct pam_response *reply =
521 1.1 christos malloc(sizeof(struct pam_response) * num_msg);
522 1.1 christos
523 1.1 christos if (reply == NULL)
524 1.1 christos return PAM_BUF_ERR;
525 1.1 christos
526 1.1 christos for (i = 0; i < num_msg; i++) {
527 1.1 christos switch (msg[i]->msg_style) {
528 1.1 christos case PAM_PROMPT_ECHO_ON: /* assume want user name */
529 1.1 christos reply[i].resp_retcode = PAM_SUCCESS;
530 1.1 christos reply[i].resp = COPY_STRING(cred->uname);
531 1.1 christos /* PAM frees resp. */
532 1.1 christos break;
533 1.1 christos case PAM_PROMPT_ECHO_OFF: /* assume want password */
534 1.7 christos (void)strlcpy(passprompt, msg[i]->msg, 256);
535 1.7 christos reply[i].resp_retcode = PAM_SUCCESS;
536 1.7 christos reply[i].resp = COPY_STRING(cred->pass);
537 1.7 christos /* PAM frees resp. */
538 1.7 christos break;
539 1.1 christos case PAM_TEXT_INFO:
540 1.1 christos case PAM_ERROR_MSG:
541 1.1 christos reply[i].resp_retcode = PAM_SUCCESS;
542 1.1 christos reply[i].resp = NULL;
543 1.1 christos break;
544 1.1 christos default: /* unknown message style */
545 1.1 christos free(reply);
546 1.1 christos return PAM_CONV_ERR;
547 1.1 christos }
548 1.1 christos }
549 1.1 christos
550 1.1 christos *resp = reply;
551 1.1 christos return PAM_SUCCESS;
552 1.1 christos }
553 1.1 christos
554 1.1 christos /*
555 1.1 christos * The PAM version as a side effect may put a new username in *name.
556 1.1 christos */
557 1.1 christos static int
558 1.1 christos check_user(char *name, char *cred)
559 1.1 christos {
560 1.1 christos pam_handle_t *pamh = NULL;
561 1.1 christos const void *item;
562 1.1 christos int rval;
563 1.1 christos int e;
564 1.1 christos cred_t auth_cred = { name, cred };
565 1.1 christos struct pam_conv conv = { &auth_conv, &auth_cred };
566 1.1 christos
567 1.1 christos e = pam_start("telnetd", name, &conv, &pamh);
568 1.1 christos if (e != PAM_SUCCESS) {
569 1.1 christos syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
570 1.1 christos return 0;
571 1.1 christos }
572 1.1 christos
573 1.1 christos #if 0 /* Where can we find this value? */
574 1.1 christos e = pam_set_item(pamh, PAM_RHOST, remotehost);
575 1.1 christos if (e != PAM_SUCCESS) {
576 1.1 christos syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
577 1.1 christos pam_strerror(pamh, e));
578 1.1 christos return 0;
579 1.1 christos }
580 1.1 christos #endif
581 1.1 christos
582 1.1 christos e = pam_authenticate(pamh, 0);
583 1.1 christos switch (e) {
584 1.1 christos case PAM_SUCCESS:
585 1.1 christos /*
586 1.1 christos * With PAM we support the concept of a "template"
587 1.1 christos * user. The user enters a login name which is
588 1.1 christos * authenticated by PAM, usually via a remote service
589 1.1 christos * such as RADIUS or TACACS+. If authentication
590 1.1 christos * succeeds, a different but related "template" name
591 1.1 christos * is used for setting the credentials, shell, and
592 1.1 christos * home directory. The name the user enters need only
593 1.1 christos * exist on the remote authentication server, but the
594 1.1 christos * template name must be present in the local password
595 1.1 christos * database.
596 1.1 christos *
597 1.1 christos * This is supported by two various mechanisms in the
598 1.1 christos * individual modules. However, from the application's
599 1.1 christos * point of view, the template user is always passed
600 1.1 christos * back as a changed value of the PAM_USER item.
601 1.1 christos */
602 1.1 christos if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
603 1.1 christos PAM_SUCCESS) {
604 1.1 christos strcpy(name, item);
605 1.1 christos } else
606 1.1 christos syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
607 1.1 christos pam_strerror(pamh, e));
608 1.6 lukem #if 0 /* pam_securetty(8) should be used to enforce this */
609 1.1 christos if (isroot(name) && !rootterm(line))
610 1.1 christos rval = 0;
611 1.1 christos else
612 1.6 lukem #endif
613 1.1 christos rval = 1;
614 1.1 christos break;
615 1.1 christos
616 1.1 christos case PAM_AUTH_ERR:
617 1.1 christos case PAM_USER_UNKNOWN:
618 1.1 christos case PAM_MAXTRIES:
619 1.1 christos rval = 0;
620 1.1 christos break;
621 1.1 christos
622 1.1 christos default:
623 1.1 christos syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
624 1.1 christos rval = 0;
625 1.1 christos break;
626 1.1 christos }
627 1.1 christos
628 1.1 christos if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
629 1.1 christos syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
630 1.1 christos rval = 0;
631 1.1 christos }
632 1.1 christos return rval;
633 1.1 christos }
634 1.1 christos
635 1.6 lukem #endif /* !NOPAM */
636 1.1 christos
637 1.1 christos #endif /* ENCRYPTION */
638 1.1 christos #endif /* SRA */
639