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