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