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