1185393efSchristos /*-
2185393efSchristos * Copyright (c) 1991, 1993
3185393efSchristos * Dave Safford. All rights reserved.
4185393efSchristos *
5185393efSchristos * Redistribution and use in source and binary forms, with or without
6185393efSchristos * modification, are permitted provided that the following conditions
7185393efSchristos * are met:
8185393efSchristos * 1. Redistributions of source code must retain the above copyright
9185393efSchristos * notice, this list of conditions and the following disclaimer.
10185393efSchristos * 2. Redistributions in binary form must reproduce the above copyright
11185393efSchristos * notice, this list of conditions and the following disclaimer in the
12185393efSchristos * documentation and/or other materials provided with the distribution.
13185393efSchristos * 3. Neither the name of the University nor the names of its contributors
14185393efSchristos * may be used to endorse or promote products derived from this software
15185393efSchristos * without specific prior written permission.
16185393efSchristos *
17185393efSchristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18185393efSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19185393efSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20185393efSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21185393efSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22185393efSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23185393efSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24185393efSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25185393efSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26185393efSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27185393efSchristos * SUCH DAMAGE.
28185393efSchristos *
29185393efSchristos */
30185393efSchristos
31185393efSchristos #include <sys/cdefs.h>
32185393efSchristos #ifdef notdef
33185393efSchristos __FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/sra.c,v 1.16 2002/05/06 09:48:02 markm Exp $");
34185393efSchristos #else
35*b893c4d5Snia __RCSID("$NetBSD: sra.c,v 1.12 2021/10/30 10:46:57 nia Exp $");
36185393efSchristos #endif
37185393efSchristos
38185393efSchristos #ifdef SRA
39185393efSchristos #ifdef ENCRYPTION
40185393efSchristos #include <sys/types.h>
41185393efSchristos #include <arpa/telnet.h>
4294b84ac8Slukem #include <paths.h>
43185393efSchristos #include <pwd.h>
44185393efSchristos #include <stdio.h>
45185393efSchristos #include <stdlib.h>
46185393efSchristos #include <string.h>
47185393efSchristos #include <syslog.h>
48185393efSchristos #include <ttyent.h>
49185393efSchristos
50185393efSchristos #ifndef NOPAM
51185393efSchristos #include <security/pam_appl.h>
52185393efSchristos #else
53185393efSchristos #include <unistd.h>
54185393efSchristos #endif
55185393efSchristos
56185393efSchristos #include "auth.h"
57185393efSchristos #include "misc.h"
58185393efSchristos #include "encrypt.h"
59185393efSchristos #include "pk.h"
60185393efSchristos
61185393efSchristos char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
62185393efSchristos char *user, *pass, *xuser, *xpass;
6364fe9d91Schristos char *passprompt, *xpassprompt;
64185393efSchristos DesData ck;
65185393efSchristos IdeaData ik;
66185393efSchristos
67185393efSchristos extern int auth_debug_mode;
6894b84ac8Slukem extern char *line; /* see sys_term.c */
69185393efSchristos
70185393efSchristos static int sra_valid = 0;
71185393efSchristos static int passwd_sent = 0;
72185393efSchristos
73185393efSchristos static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
74185393efSchristos AUTHTYPE_SRA, };
75185393efSchristos
76cdf62a44Schristos #define SMALL_LEN 256
77cdf62a44Schristos #define XSMALL_LEN 513
78185393efSchristos #define SRA_KEY 0
79185393efSchristos #define SRA_USER 1
80185393efSchristos #define SRA_CONTINUE 2
81185393efSchristos #define SRA_PASS 3
82185393efSchristos #define SRA_ACCEPT 4
83185393efSchristos #define SRA_REJECT 5
84185393efSchristos
856a6c8f61Schristos static int check_user(char *, const char *);
86185393efSchristos
87185393efSchristos /* support routine to send out authentication message */
88185393efSchristos static int
Data(Authenticator * ap,int type,void * d,int c)89185393efSchristos Data(Authenticator *ap, int type, void *d, int c)
90185393efSchristos {
91185393efSchristos unsigned char *p = str_data + 4;
92cdf62a44Schristos unsigned char *cd = d;
93185393efSchristos
94185393efSchristos if (c == -1)
95cdf62a44Schristos c = strlen(d);
96185393efSchristos
97185393efSchristos if (auth_debug_mode) {
98185393efSchristos printf("%s:%d: [%d] (%d)",
99185393efSchristos str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
100cdf62a44Schristos str_data[3], type, c);
101185393efSchristos printd(d, c);
102185393efSchristos printf("\r\n");
103185393efSchristos }
104185393efSchristos *p++ = ap->type;
105185393efSchristos *p++ = ap->way;
106185393efSchristos *p++ = type;
107185393efSchristos while (c-- > 0) {
108185393efSchristos if ((*p++ = *cd++) == IAC)
109185393efSchristos *p++ = IAC;
110185393efSchristos }
111185393efSchristos *p++ = IAC;
112185393efSchristos *p++ = SE;
113185393efSchristos if (str_data[3] == TELQUAL_IS)
114185393efSchristos printsub('>', &str_data[2], p - (&str_data[2]));
115cdf62a44Schristos return telnet_net_write(str_data, p - str_data);
116185393efSchristos }
117185393efSchristos
118185393efSchristos int
sra_init(Authenticator * ap __unused,int server)119185393efSchristos sra_init(Authenticator *ap __unused, int server)
120185393efSchristos {
121185393efSchristos if (server)
122185393efSchristos str_data[3] = TELQUAL_REPLY;
123185393efSchristos else
124185393efSchristos str_data[3] = TELQUAL_IS;
125185393efSchristos
126cdf62a44Schristos user = malloc(SMALL_LEN);
127cdf62a44Schristos xuser = malloc(XSMALL_LEN);
128cdf62a44Schristos pass = malloc(SMALL_LEN);
129cdf62a44Schristos xpass = malloc(XSMALL_LEN);
130cdf62a44Schristos passprompt = malloc(SMALL_LEN);
131cdf62a44Schristos xpassprompt = malloc(XSMALL_LEN);
132185393efSchristos
133185393efSchristos if (user == NULL || xuser == NULL || pass == NULL || xpass ==
13464fe9d91Schristos NULL || passprompt == NULL || xpassprompt == NULL)
135185393efSchristos return 0; /* malloc failed */
136185393efSchristos
137185393efSchristos passwd_sent = 0;
138185393efSchristos
139185393efSchristos genkeys(pka, ska);
140cdf62a44Schristos return 1;
141185393efSchristos }
142185393efSchristos
143185393efSchristos /* client received a go-ahead for sra */
144185393efSchristos int
sra_send(Authenticator * ap)145185393efSchristos sra_send(Authenticator *ap)
146185393efSchristos {
147185393efSchristos /* send PKA */
148185393efSchristos
149185393efSchristos if (auth_debug_mode)
150185393efSchristos printf("Sent PKA to server.\r\n" );
151185393efSchristos printf("Trying SRA secure login:\r\n");
152185393efSchristos if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
153185393efSchristos if (auth_debug_mode)
154185393efSchristos printf("Not enough room for authentication data\r\n");
155cdf62a44Schristos return 0;
156185393efSchristos }
157185393efSchristos
158cdf62a44Schristos return 1;
159185393efSchristos }
160185393efSchristos
161185393efSchristos /* server received an IS -- could be SRA KEY, USER, or PASS */
162185393efSchristos void
sra_is(Authenticator * ap,unsigned char * data,int cnt)163185393efSchristos sra_is(Authenticator *ap, unsigned char *data, int cnt)
164185393efSchristos {
165185393efSchristos int valid;
166185393efSchristos Session_Key skey;
167185393efSchristos
168185393efSchristos if (cnt-- < 1)
169185393efSchristos goto bad;
170185393efSchristos switch (*data++) {
171185393efSchristos
172185393efSchristos case SRA_KEY:
173185393efSchristos if (cnt < HEXKEYBYTES) {
174185393efSchristos Data(ap, SRA_REJECT, (void *)0, 0);
175185393efSchristos auth_finished(ap, AUTH_USER);
176185393efSchristos if (auth_debug_mode) {
177185393efSchristos printf("SRA user rejected for bad PKB\r\n");
178185393efSchristos }
179185393efSchristos return;
180185393efSchristos }
181185393efSchristos if (auth_debug_mode)
182185393efSchristos printf("Sent pka\r\n");
183185393efSchristos if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
184185393efSchristos if (auth_debug_mode)
185185393efSchristos printf("Not enough room\r\n");
186185393efSchristos return;
187185393efSchristos }
188185393efSchristos memcpy(pkb, data, HEXKEYBYTES);
189185393efSchristos pkb[HEXKEYBYTES] = '\0';
190185393efSchristos common_key(ska, pkb, &ik, &ck);
191185393efSchristos return;
192185393efSchristos
193185393efSchristos case SRA_USER:
194185393efSchristos /* decode KAB(u) */
195cdf62a44Schristos if (cnt > XSMALL_LEN - 1) /* Attempted buffer overflow */
196185393efSchristos break;
197185393efSchristos memcpy(xuser, data, cnt);
198185393efSchristos xuser[cnt] = '\0';
199185393efSchristos pk_decode(xuser, user, &ck);
200185393efSchristos auth_encrypt_user(user);
20164fe9d91Schristos #ifndef NOPAM
20264fe9d91Schristos (void)check_user(user, "*");
20364fe9d91Schristos #endif
20464fe9d91Schristos pk_encode(passprompt, xpassprompt, &ck);
205cdf62a44Schristos Data(ap, SRA_CONTINUE, xpassprompt, XSMALL_LEN - 1);
206185393efSchristos
207185393efSchristos return;
208185393efSchristos
209185393efSchristos case SRA_PASS:
210cdf62a44Schristos if (cnt > XSMALL_LEN - 1) /* Attempted buffer overflow */
211185393efSchristos break;
212185393efSchristos /* decode KAB(P) */
213185393efSchristos memcpy(xpass, data, cnt);
214185393efSchristos xpass[cnt] = '\0';
215185393efSchristos pk_decode(xpass, pass, &ck);
216185393efSchristos
217185393efSchristos /* check user's password */
218185393efSchristos valid = check_user(user, pass);
219185393efSchristos
220185393efSchristos if(valid) {
221f4ee0854Slukem /* PAM (via check_user()) may have changed 'user' */
222f4ee0854Slukem auth_encrypt_user(user);
223185393efSchristos Data(ap, SRA_ACCEPT, (void *)0, 0);
224185393efSchristos skey.data = ck;
225185393efSchristos skey.type = SK_DES;
226185393efSchristos skey.length = 8;
227185393efSchristos encrypt_session_key(&skey, 1);
228185393efSchristos
229185393efSchristos sra_valid = 1;
230185393efSchristos auth_finished(ap, AUTH_VALID);
231185393efSchristos if (auth_debug_mode) {
232185393efSchristos printf("SRA user accepted\r\n");
233185393efSchristos }
234185393efSchristos }
235185393efSchristos else {
23664fe9d91Schristos pk_encode(passprompt, xpassprompt, &ck);
237cdf62a44Schristos Data(ap, SRA_CONTINUE, (void *)xpassprompt,
238cdf62a44Schristos XSMALL_LEN - 1);
239185393efSchristos if (auth_debug_mode) {
240185393efSchristos printf("SRA user failed\r\n");
241185393efSchristos }
242185393efSchristos }
243185393efSchristos return;
244185393efSchristos
245185393efSchristos default:
246185393efSchristos if (auth_debug_mode)
247185393efSchristos printf("Unknown SRA option %d\r\n", data[-1]);
248185393efSchristos }
249185393efSchristos bad:
250185393efSchristos Data(ap, SRA_REJECT, 0, 0);
251185393efSchristos sra_valid = 0;
252185393efSchristos auth_finished(ap, AUTH_REJECT);
253185393efSchristos }
254185393efSchristos
255185393efSchristos /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
256185393efSchristos void
sra_reply(Authenticator * ap,unsigned char * data,int cnt)257185393efSchristos sra_reply(Authenticator *ap, unsigned char *data, int cnt)
258185393efSchristos {
259cdf62a44Schristos char uprompt[SMALL_LEN], tuser[SMALL_LEN];
260185393efSchristos Session_Key skey;
261185393efSchristos size_t i;
262185393efSchristos
263185393efSchristos if (cnt-- < 1)
264185393efSchristos return;
265185393efSchristos switch (*data++) {
266185393efSchristos
267185393efSchristos case SRA_KEY:
268185393efSchristos /* calculate common key */
269185393efSchristos if (cnt < HEXKEYBYTES) {
270185393efSchristos if (auth_debug_mode) {
271185393efSchristos printf("SRA user rejected for bad PKB\r\n");
272185393efSchristos }
273185393efSchristos return;
274185393efSchristos }
275185393efSchristos memcpy(pkb, data, HEXKEYBYTES);
276185393efSchristos pkb[HEXKEYBYTES] = '\0';
277185393efSchristos
278185393efSchristos common_key(ska, pkb, &ik, &ck);
279185393efSchristos
280185393efSchristos enc_user:
281185393efSchristos
282185393efSchristos /* encode user */
283185393efSchristos memset(tuser, 0, sizeof(tuser));
284cdf62a44Schristos snprintf(uprompt, sizeof(uprompt), "User (%s): ",
285cdf62a44Schristos UserNameRequested);
286cdf62a44Schristos if (telnet_gets(uprompt, tuser, SMALL_LEN - 1, 1) == NULL) {
28764fe9d91Schristos printf("\n");
28864fe9d91Schristos exit(1);
28964fe9d91Schristos }
290185393efSchristos if (tuser[0] == '\n' || tuser[0] == '\r' )
291cdf62a44Schristos strlcpy(user, UserNameRequested, SMALL_LEN);
292185393efSchristos else {
293185393efSchristos /* telnet_gets leaves the newline on */
294185393efSchristos for(i = 0; i < sizeof(tuser); i++) {
295185393efSchristos if (tuser[i] == '\n') {
296185393efSchristos tuser[i] = '\0';
297185393efSchristos break;
298185393efSchristos }
299185393efSchristos }
300cdf62a44Schristos strlcpy(user, tuser, SMALL_LEN);
301185393efSchristos }
302185393efSchristos pk_encode(user, xuser, &ck);
303185393efSchristos
304185393efSchristos /* send it off */
305185393efSchristos if (auth_debug_mode)
306185393efSchristos printf("Sent KAB(U)\r\n");
307185393efSchristos if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
308185393efSchristos if (auth_debug_mode)
309185393efSchristos printf("Not enough room\r\n");
310185393efSchristos return;
311185393efSchristos }
312185393efSchristos break;
313185393efSchristos
314185393efSchristos case SRA_CONTINUE:
315185393efSchristos if (passwd_sent) {
316185393efSchristos passwd_sent = 0;
317185393efSchristos printf("[ SRA login failed ]\r\n");
318185393efSchristos goto enc_user;
319185393efSchristos }
320cdf62a44Schristos if (cnt > XSMALL_LEN - 1) {
32164fe9d91Schristos break;
32223dfb0b1Schristos } else if (cnt > 0) {
32323dfb0b1Schristos (void)memcpy(xpassprompt, data, cnt);
32464fe9d91Schristos pk_decode(xpassprompt, passprompt, &ck);
32523dfb0b1Schristos } else {
326cdf62a44Schristos (void)strlcpy(passprompt, "Password: ", SMALL_LEN);
32723dfb0b1Schristos }
328185393efSchristos /* encode password */
329cdf62a44Schristos memset(pass, 0, SMALL_LEN);
330cdf62a44Schristos if (telnet_gets(passprompt, pass, SMALL_LEN - 1, 0) == NULL) {
33164fe9d91Schristos printf("\n");
33264fe9d91Schristos exit(1);
33364fe9d91Schristos }
334185393efSchristos pk_encode(pass, xpass, &ck);
335185393efSchristos /* send it off */
336185393efSchristos if (auth_debug_mode)
337185393efSchristos printf("Sent KAB(P)\r\n");
338185393efSchristos if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
339185393efSchristos if (auth_debug_mode)
340185393efSchristos printf("Not enough room\r\n");
341185393efSchristos return;
342185393efSchristos }
343185393efSchristos passwd_sent = 1;
344185393efSchristos break;
345185393efSchristos
346185393efSchristos case SRA_REJECT:
347185393efSchristos printf("[ SRA refuses authentication ]\r\n");
348185393efSchristos printf("Trying plaintext login:\r\n");
349185393efSchristos auth_finished(0, AUTH_REJECT);
350185393efSchristos return;
351185393efSchristos
352185393efSchristos case SRA_ACCEPT:
353185393efSchristos printf("[ SRA accepts you ]\r\n");
354185393efSchristos skey.data = ck;
355185393efSchristos skey.type = SK_DES;
356185393efSchristos skey.length = 8;
357185393efSchristos encrypt_session_key(&skey, 0);
358185393efSchristos
359185393efSchristos auth_finished(ap, AUTH_VALID);
360185393efSchristos return;
361185393efSchristos default:
362185393efSchristos if (auth_debug_mode)
363185393efSchristos printf("Unknown SRA option %d\r\n", data[-1]);
364185393efSchristos return;
365185393efSchristos }
366185393efSchristos }
367185393efSchristos
368185393efSchristos int
sra_status(Authenticator * ap __unused,char * name,size_t len,int level)369185393efSchristos sra_status(Authenticator *ap __unused, char *name, size_t len, int level)
370185393efSchristos {
371185393efSchristos if (level < AUTH_USER)
372cdf62a44Schristos return level;
373185393efSchristos if (UserNameRequested && sra_valid) {
374185393efSchristos strlcpy(name, UserNameRequested, len);
375cdf62a44Schristos return AUTH_VALID;
376185393efSchristos } else
377cdf62a44Schristos return AUTH_USER;
378185393efSchristos }
379185393efSchristos
380185393efSchristos #define BUMP(buf, len) while (*(buf)) { ++(buf), --(len); }
381185393efSchristos #define ADDC(buf, len, c) if ((len) > 0) { *(buf)++ = (c); --(len); }
382185393efSchristos
383185393efSchristos void
sra_printsub(unsigned char * data,int cnt,unsigned char * ubuf,int buflen)384cdf62a44Schristos sra_printsub(unsigned char *data, int cnt, unsigned char *ubuf, int buflen)
385185393efSchristos {
386cdf62a44Schristos char lbuf[32], *buf = (char *)ubuf;
387185393efSchristos int i;
388185393efSchristos
389185393efSchristos buf[buflen - 1] = '\0'; /* make sure its NULL terminated */
390185393efSchristos buflen -= 1;
391185393efSchristos
392185393efSchristos switch(data[3]) {
393185393efSchristos
394185393efSchristos case SRA_CONTINUE:
395cdf62a44Schristos strncpy(buf, " CONTINUE ", buflen);
396185393efSchristos goto common;
397185393efSchristos
398185393efSchristos case SRA_REJECT: /* Rejected (reason might follow) */
399cdf62a44Schristos strncpy(buf, " REJECT ", buflen);
400185393efSchristos goto common;
401185393efSchristos
402185393efSchristos case SRA_ACCEPT: /* Accepted (name might follow) */
403cdf62a44Schristos strncpy(buf, " ACCEPT ", buflen);
404185393efSchristos
405185393efSchristos common:
406185393efSchristos BUMP(buf, buflen);
407185393efSchristos if (cnt <= 4)
408185393efSchristos break;
409185393efSchristos ADDC(buf, buflen, '"');
410185393efSchristos for (i = 4; i < cnt; i++)
411185393efSchristos ADDC(buf, buflen, data[i]);
412185393efSchristos ADDC(buf, buflen, '"');
413185393efSchristos ADDC(buf, buflen, '\0');
414185393efSchristos break;
415185393efSchristos
416185393efSchristos case SRA_KEY: /* Authentication data follows */
417cdf62a44Schristos strncpy(buf, " KEY ", buflen);
418185393efSchristos goto common2;
419185393efSchristos
420185393efSchristos case SRA_USER:
421cdf62a44Schristos strncpy(buf, " USER ", buflen);
422185393efSchristos goto common2;
423185393efSchristos
424185393efSchristos case SRA_PASS:
425cdf62a44Schristos strncpy(buf, " PASS ", buflen);
426185393efSchristos goto common2;
427185393efSchristos
428185393efSchristos default:
429cdf62a44Schristos snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[3]);
430cdf62a44Schristos strncpy(buf, lbuf, buflen);
431185393efSchristos common2:
432185393efSchristos BUMP(buf, buflen);
433185393efSchristos for (i = 4; i < cnt; i++) {
434cdf62a44Schristos snprintf(lbuf, sizeof(lbuf), " %d", data[i]);
435cdf62a44Schristos strncpy(buf, lbuf, buflen);
436185393efSchristos BUMP(buf, buflen);
437185393efSchristos }
438185393efSchristos break;
439185393efSchristos }
440185393efSchristos }
441185393efSchristos
4420d885c3aSlukem #ifdef NOPAM
443185393efSchristos static int
isroot(const char * usr)444185393efSchristos isroot(const char *usr)
445185393efSchristos {
446382db3edSchristos struct passwd pws, *pwd;
447382db3edSchristos char pwbuf[1024];
448185393efSchristos
449262b0ba9Schristos if (getpwnam_r(usr, &pws, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
450262b0ba9Schristos pwd == NULL)
451185393efSchristos return 0;
452185393efSchristos return (!pwd->pw_uid);
453185393efSchristos }
454185393efSchristos
455185393efSchristos static int
rootterm(const char * ttyname)45694b84ac8Slukem rootterm(const char *ttyname)
457185393efSchristos {
458185393efSchristos struct ttyent *t;
45994b84ac8Slukem const char *ttyn;
46094b84ac8Slukem
46194b84ac8Slukem ttyn = ttyname;
46294b84ac8Slukem if (strncmp(ttyn, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
46394b84ac8Slukem ttyn += sizeof(_PATH_DEV) - 1;
464185393efSchristos
465185393efSchristos return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
466185393efSchristos }
467185393efSchristos
468185393efSchristos static int
check_user(char * name,const char * cred)4696a6c8f61Schristos check_user(char *name, const char *cred)
470185393efSchristos {
4710d885c3aSlukem struct passwd pws, *pw;
4720d885c3aSlukem char pwbuf[1024];
473185393efSchristos char *xpasswd, *salt;
474185393efSchristos
475185393efSchristos if (isroot(name) && !rootterm(line))
476185393efSchristos {
477185393efSchristos crypt("AA", "*"); /* Waste some time to simulate success */
478cdf62a44Schristos return 0;
479185393efSchristos }
480185393efSchristos
4810d885c3aSlukem if (getpwnam_r(name, &pws, pwbuf, sizeof(pwbuf), &pw) == 0 &&
4820d885c3aSlukem pw != NULL) {
483185393efSchristos if (pw->pw_shell == NULL) {
484cdf62a44Schristos return 0;
485185393efSchristos }
486185393efSchristos
487185393efSchristos salt = pw->pw_passwd;
488185393efSchristos xpasswd = crypt(cred, salt);
489185393efSchristos /* The strcmp does not catch null passwords! */
4900d885c3aSlukem if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) {
491cdf62a44Schristos return 0;
492185393efSchristos }
493cdf62a44Schristos return 1;
494185393efSchristos }
495cdf62a44Schristos return 0;
496185393efSchristos }
4970d885c3aSlukem #else /* !NOPAM */
498185393efSchristos
499185393efSchristos /*
500185393efSchristos * The following is stolen from ftpd, which stole it from the imap-uw
501185393efSchristos * PAM module and login.c. It is needed because we can't really
502185393efSchristos * "converse" with the user, having already gone to the trouble of
503185393efSchristos * getting their username and password through an encrypted channel.
504185393efSchristos */
505185393efSchristos
506185393efSchristos #define COPY_STRING(s) (s ? strdup(s) : NULL)
507185393efSchristos
508185393efSchristos struct cred_t {
509185393efSchristos const char *uname;
510185393efSchristos const char *pass;
511185393efSchristos };
512185393efSchristos typedef struct cred_t cred_t;
513185393efSchristos
514185393efSchristos static int
auth_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** resp,void * appdata)515cdf62a44Schristos auth_conv(int num_msg, const struct pam_message **msg,
516cdf62a44Schristos struct pam_response **resp, void *appdata)
517185393efSchristos {
518185393efSchristos int i;
519cdf62a44Schristos cred_t *cred = appdata;
520*b893c4d5Snia struct pam_response *reply = NULL;
521185393efSchristos
522*b893c4d5Snia if (reallocarr(&reply, num_msg, sizeof(*reply)) != 0)
523185393efSchristos return PAM_BUF_ERR;
524185393efSchristos
525185393efSchristos for (i = 0; i < num_msg; i++) {
526185393efSchristos switch (msg[i]->msg_style) {
527185393efSchristos case PAM_PROMPT_ECHO_ON: /* assume want user name */
528185393efSchristos reply[i].resp_retcode = PAM_SUCCESS;
529185393efSchristos reply[i].resp = COPY_STRING(cred->uname);
530185393efSchristos /* PAM frees resp. */
531185393efSchristos break;
532185393efSchristos case PAM_PROMPT_ECHO_OFF: /* assume want password */
533cdf62a44Schristos (void)strlcpy(passprompt, msg[i]->msg, SMALL_LEN);
534185393efSchristos reply[i].resp_retcode = PAM_SUCCESS;
535185393efSchristos reply[i].resp = COPY_STRING(cred->pass);
536185393efSchristos /* PAM frees resp. */
537185393efSchristos break;
538185393efSchristos case PAM_TEXT_INFO:
539185393efSchristos case PAM_ERROR_MSG:
540185393efSchristos reply[i].resp_retcode = PAM_SUCCESS;
541185393efSchristos reply[i].resp = NULL;
542185393efSchristos break;
543185393efSchristos default: /* unknown message style */
544185393efSchristos free(reply);
545185393efSchristos return PAM_CONV_ERR;
546185393efSchristos }
547185393efSchristos }
548185393efSchristos
549185393efSchristos *resp = reply;
550185393efSchristos return PAM_SUCCESS;
551185393efSchristos }
552185393efSchristos
553185393efSchristos /*
554185393efSchristos * The PAM version as a side effect may put a new username in *name.
555185393efSchristos */
556185393efSchristos static int
check_user(char * name,const char * cred)5576a6c8f61Schristos check_user(char *name, const char *cred)
558185393efSchristos {
559185393efSchristos pam_handle_t *pamh = NULL;
560185393efSchristos const void *item;
561185393efSchristos int rval;
562185393efSchristos int e;
563185393efSchristos cred_t auth_cred = { name, cred };
564185393efSchristos struct pam_conv conv = { &auth_conv, &auth_cred };
565185393efSchristos
566185393efSchristos e = pam_start("telnetd", name, &conv, &pamh);
567185393efSchristos if (e != PAM_SUCCESS) {
568185393efSchristos syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
569185393efSchristos return 0;
570185393efSchristos }
571185393efSchristos
572185393efSchristos #if 0 /* Where can we find this value? */
573185393efSchristos e = pam_set_item(pamh, PAM_RHOST, remotehost);
574185393efSchristos if (e != PAM_SUCCESS) {
575185393efSchristos syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
576185393efSchristos pam_strerror(pamh, e));
577185393efSchristos return 0;
578185393efSchristos }
579185393efSchristos #endif
580185393efSchristos
581185393efSchristos e = pam_authenticate(pamh, 0);
582185393efSchristos switch (e) {
583185393efSchristos case PAM_SUCCESS:
584185393efSchristos /*
585185393efSchristos * With PAM we support the concept of a "template"
586185393efSchristos * user. The user enters a login name which is
587185393efSchristos * authenticated by PAM, usually via a remote service
588185393efSchristos * such as RADIUS or TACACS+. If authentication
589185393efSchristos * succeeds, a different but related "template" name
590185393efSchristos * is used for setting the credentials, shell, and
591185393efSchristos * home directory. The name the user enters need only
592185393efSchristos * exist on the remote authentication server, but the
593185393efSchristos * template name must be present in the local password
594185393efSchristos * database.
595185393efSchristos *
596185393efSchristos * This is supported by two various mechanisms in the
597185393efSchristos * individual modules. However, from the application's
598185393efSchristos * point of view, the template user is always passed
599185393efSchristos * back as a changed value of the PAM_USER item.
600185393efSchristos */
601185393efSchristos if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
602185393efSchristos PAM_SUCCESS) {
603cdf62a44Schristos strlcpy(name, item, SMALL_LEN);
604185393efSchristos } else
605185393efSchristos syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
606185393efSchristos pam_strerror(pamh, e));
6070d885c3aSlukem #if 0 /* pam_securetty(8) should be used to enforce this */
608185393efSchristos if (isroot(name) && !rootterm(line))
609185393efSchristos rval = 0;
610185393efSchristos else
6110d885c3aSlukem #endif
612185393efSchristos rval = 1;
613185393efSchristos break;
614185393efSchristos
615185393efSchristos case PAM_AUTH_ERR:
616185393efSchristos case PAM_USER_UNKNOWN:
617185393efSchristos case PAM_MAXTRIES:
618185393efSchristos rval = 0;
619185393efSchristos break;
620185393efSchristos
621185393efSchristos default:
622185393efSchristos syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
623185393efSchristos rval = 0;
624185393efSchristos break;
625185393efSchristos }
626185393efSchristos
627185393efSchristos if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
628185393efSchristos syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
629185393efSchristos rval = 0;
630185393efSchristos }
631185393efSchristos return rval;
632185393efSchristos }
633185393efSchristos
6340d885c3aSlukem #endif /* !NOPAM */
635185393efSchristos
636185393efSchristos #endif /* ENCRYPTION */
637185393efSchristos #endif /* SRA */
638