2 * Copyright (c) 1991, 1993
3 * Dave Safford. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
35 #include <sys/types.h>
36 #include <arpa/telnet.h>
48 #include <security/pam_appl.h>
62 char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
63 char *user,*pass,*xuser,*xpass;
67 extern int auth_debug_mode;
70 static int sra_valid = 0;
71 static int passwd_sent = 0;
73 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
78 #define SRA_CONTINUE 2
83 static int check_user(const char *, const char *);
85 /* support routine to send out authentication message */
87 Data(Authenticator *ap, int type, void *d, int c)
89 unsigned char *p = str_data + 4;
90 unsigned char *cd = (unsigned char *)d;
93 c = strlen((char *)cd);
95 if (auth_debug_mode) {
96 printf("%s:%d: [%d] (%d)",
97 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
107 if ((*p++ = *cd++) == IAC)
112 if (str_data[3] == TELQUAL_IS)
113 printsub('>', &str_data[2], p - (&str_data[2]));
114 return(net_write(str_data, p - str_data));
118 sra_init(Authenticator *ap, int server)
121 str_data[3] = TELQUAL_REPLY;
123 str_data[3] = TELQUAL_IS;
125 user = (char *)malloc(256);
126 xuser = (char *)malloc(513);
127 pass = (char *)malloc(256);
128 xpass = (char *)malloc(513);
130 if (user == NULL || xuser == NULL || pass == NULL || xpass ==
132 return 0; /* malloc failed */
140 /* client received a go-ahead for sra */
142 sra_send(Authenticator *ap)
147 printf("Sent PKA to server.\r\n" );
148 printf("Trying SRA secure login:\r\n");
149 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
151 printf("Not enough room for authentication data\r\n");
158 /* server received an IS -- could be SRA KEY, USER, or PASS */
160 sra_is(Authenticator *ap, unsigned char *data, int cnt)
170 if (cnt < HEXKEYBYTES) {
171 Data(ap, SRA_REJECT, (void *)0, 0);
172 auth_finished(ap, AUTH_USER);
173 if (auth_debug_mode) {
174 printf("SRA user rejected for bad PKB\r\n");
179 printf("Sent pka\r\n");
180 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
182 printf("Not enough room\r\n");
185 memcpy(pkb,data,HEXKEYBYTES);
186 pkb[HEXKEYBYTES] = '\0';
187 common_key(ska,pkb,&ik,&ck);
192 if (cnt > 512) /* Attempted buffer overflow */
194 memcpy(xuser,data,cnt);
196 pk_decode(xuser,user,&ck);
197 auth_encrypt_user(user);
198 Data(ap, SRA_CONTINUE, (void *)0, 0);
203 if (cnt > 512) /* Attempted buffer overflow */
206 memcpy(xpass,data,cnt);
208 pk_decode(xpass,pass,&ck);
210 /* check user's password */
211 valid = check_user(user,pass);
214 Data(ap, SRA_ACCEPT, (void *)0, 0);
215 #ifdef DES_ENCRYPTION
219 encrypt_session_key(&skey, 1);
223 auth_finished(ap, AUTH_VALID);
224 if (auth_debug_mode) {
225 printf("SRA user accepted\r\n");
229 Data(ap, SRA_CONTINUE, (void *)0, 0);
231 Data(ap, SRA_REJECT, (void *)0, 0);
233 auth_finished(ap, AUTH_REJECT);
235 if (auth_debug_mode) {
236 printf("SRA user failed\r\n");
243 printf("Unknown SRA option %d\r\n", data[-1]);
246 Data(ap, SRA_REJECT, 0, 0);
248 auth_finished(ap, AUTH_REJECT);
251 /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
253 sra_reply(Authenticator *ap, unsigned char *data, int cnt)
255 extern char *telnet_gets();
256 char uprompt[256],tuser[256];
265 /* calculate common key */
266 if (cnt < HEXKEYBYTES) {
267 if (auth_debug_mode) {
268 printf("SRA user rejected for bad PKB\r\n");
272 memcpy(pkb,data,HEXKEYBYTES);
273 pkb[HEXKEYBYTES] = '\0';
275 common_key(ska,pkb,&ik,&ck);
280 memset(tuser,0,sizeof(tuser));
281 sprintf(uprompt,"User (%s): ",UserNameRequested);
282 telnet_gets(uprompt,tuser,255,1);
283 if (tuser[0] == '\n' || tuser[0] == '\r' )
284 strcpy(user,UserNameRequested);
286 /* telnet_gets leaves the newline on */
287 for(i=0;i<sizeof(tuser);i++) {
288 if (tuser[i] == '\n') {
295 pk_encode(user,xuser,&ck);
299 printf("Sent KAB(U)\r\n");
300 if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
302 printf("Not enough room\r\n");
310 printf("[ SRA login failed ]\r\n");
313 /* encode password */
314 memset(pass,0,sizeof(pass));
315 telnet_gets("Password: ",pass,255,0);
316 pk_encode(pass,xpass,&ck);
319 printf("Sent KAB(P)\r\n");
320 if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
322 printf("Not enough room\r\n");
329 printf("[ SRA refuses authentication ]\r\n");
330 printf("Trying plaintext login:\r\n");
331 auth_finished(0,AUTH_REJECT);
335 printf("[ SRA accepts you ]\r\n");
336 #ifdef DES_ENCRYPTION
340 encrypt_session_key(&skey, 0);
343 auth_finished(ap, AUTH_VALID);
347 printf("Unknown SRA option %d\r\n", data[-1]);
353 sra_status(Authenticator *ap, char *name, int level)
355 if (level < AUTH_USER)
357 if (UserNameRequested && sra_valid) {
358 strcpy(name, UserNameRequested);
364 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
365 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
368 sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
373 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
379 strncpy((char *)buf, " CONTINUE ", buflen);
382 case SRA_REJECT: /* Rejected (reason might follow) */
383 strncpy((char *)buf, " REJECT ", buflen);
386 case SRA_ACCEPT: /* Accepted (name might follow) */
387 strncpy((char *)buf, " ACCEPT ", buflen);
393 ADDC(buf, buflen, '"');
394 for (i = 4; i < cnt; i++)
395 ADDC(buf, buflen, data[i]);
396 ADDC(buf, buflen, '"');
397 ADDC(buf, buflen, '\0');
400 case SRA_KEY: /* Authentication data follows */
401 strncpy((char *)buf, " KEY ", buflen);
405 strncpy((char *)buf, " USER ", buflen);
409 strncpy((char *)buf, " PASS ", buflen);
413 sprintf(lbuf, " %d (unknown)", data[3]);
414 strncpy((char *)buf, lbuf, buflen);
417 for (i = 4; i < cnt; i++) {
418 sprintf(lbuf, " %d", data[i]);
419 strncpy((char *)buf, lbuf, buflen);
429 * Helper function for sgetpwnam().
434 char *new = malloc((unsigned) strlen(s) + 1);
439 (void) strcpy(new, s);
444 sgetpwnam(char *name)
446 static struct passwd save;
447 register struct passwd *p;
450 if ((p = getpwnam(name)) == NULL)
454 free(save.pw_passwd);
460 save.pw_name = sgetsave(p->pw_name);
461 save.pw_passwd = sgetsave(p->pw_passwd);
462 save.pw_gecos = sgetsave(p->pw_gecos);
463 save.pw_dir = sgetsave(p->pw_dir);
464 save.pw_shell = sgetsave(p->pw_shell);
466 syslog(LOG_WARNING,"%s\n",save.pw_name);
467 syslog(LOG_WARNING,"%s\n",save.pw_passwd);
468 syslog(LOG_WARNING,"%s\n",save.pw_gecos);
469 syslog(LOG_WARNING,"%s\n",save.pw_dir);
475 free(save.pw_passwd);
476 save.pw_passwd = sgetsave(sp->sp_pwdp);
483 isroot(const char *user)
487 if ((pw=getpwnam(user))==NULL)
489 return (!pw->pw_uid);
497 return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
502 check_user(const char *name, const char *pass)
505 char *xpasswd, *salt;
507 if (isroot(name) && !rootterm(line))
509 crypt("AA","*"); /* Waste some time to simulate success */
513 if (pw = sgetpwnam(name)) {
514 if (pw->pw_shell == NULL) {
515 pw = (struct passwd *) NULL;
519 salt = pw->pw_passwd;
520 xpasswd = crypt(pass, salt);
521 /* The strcmp does not catch null passwords! */
522 if (pw == NULL || *pw->pw_passwd == '\0' ||
523 strcmp(xpasswd, pw->pw_passwd)) {
524 pw = (struct passwd *) NULL;
534 * The following is stolen from ftpd, which stole it from the imap-uw
535 * PAM module and login.c. It is needed because we can't really
536 * "converse" with the user, having already gone to the trouble of
537 * getting their username and password through an encrypted channel.
540 #define COPY_STRING(s) (s ? strdup(s):NULL)
546 typedef struct cred_t cred_t;
549 auth_conv(int num_msg, const struct pam_message **msg,
550 struct pam_response **resp, void *appdata)
553 cred_t *cred = (cred_t *) appdata;
554 struct pam_response *reply =
555 malloc(sizeof(struct pam_response) * num_msg);
560 for (i = 0; i < num_msg; i++) {
561 switch (msg[i]->msg_style) {
562 case PAM_PROMPT_ECHO_ON: /* assume want user name */
563 reply[i].resp_retcode = PAM_SUCCESS;
564 reply[i].resp = COPY_STRING(cred->uname);
565 /* PAM frees resp. */
567 case PAM_PROMPT_ECHO_OFF: /* assume want password */
568 reply[i].resp_retcode = PAM_SUCCESS;
569 reply[i].resp = COPY_STRING(cred->pass);
570 /* PAM frees resp. */
574 reply[i].resp_retcode = PAM_SUCCESS;
575 reply[i].resp = NULL;
577 default: /* unknown message style */
588 * The PAM version as a side effect may put a new username in *name.
591 check_user(const char *name, const char *pass)
593 pam_handle_t *pamh = NULL;
597 cred_t auth_cred = { name, pass };
598 struct pam_conv conv = { &auth_conv, &auth_cred };
600 e = pam_start("telnetd", name, &conv, &pamh);
601 if (e != PAM_SUCCESS) {
602 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
606 #if 0 /* Where can we find this value? */
607 e = pam_set_item(pamh, PAM_RHOST, remotehost);
608 if (e != PAM_SUCCESS) {
609 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
610 pam_strerror(pamh, e));
615 e = pam_authenticate(pamh, 0);
619 * With PAM we support the concept of a "template"
620 * user. The user enters a login name which is
621 * authenticated by PAM, usually via a remote service
622 * such as RADIUS or TACACS+. If authentication
623 * succeeds, a different but related "template" name
624 * is used for setting the credentials, shell, and
625 * home directory. The name the user enters need only
626 * exist on the remote authentication server, but the
627 * template name must be present in the local password
630 * This is supported by two various mechanisms in the
631 * individual modules. However, from the application's
632 * point of view, the template user is always passed
633 * back as a changed value of the PAM_USER item.
635 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
637 strcpy((char *) name, (const char *) item);
639 syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
640 pam_strerror(pamh, e));
641 if (isroot(name) && !rootterm(line))
648 case PAM_USER_UNKNOWN:
654 syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
659 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
660 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));