1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)auth.c 8.2 (Berkeley) 02/16/95"; 10 #endif /* not lint */ 11 12 /* 13 * Copyright (C) 1990 by the Massachusetts Institute of Technology 14 * 15 * Export of this software from the United States of America is assumed 16 * to require a specific license from the United States Government. 17 * It is the responsibility of any person or organization contemplating 18 * export to obtain such a license before exporting. 19 * 20 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 21 * distribute this software and its documentation for any purpose and 22 * without fee is hereby granted, provided that the above copyright 23 * notice appear in all copies and that both that copyright notice and 24 * this permission notice appear in supporting documentation, and that 25 * the name of M.I.T. not be used in advertising or publicity pertaining 26 * to distribution of the software without specific, written prior 27 * permission. M.I.T. makes no representations about the suitability of 28 * this software for any purpose. It is provided "as is" without express 29 * or implied warranty. 30 */ 31 32 33 #if defined(AUTHENTICATION) 34 #include <stdio.h> 35 #include <sys/types.h> 36 #include <signal.h> 37 #define AUTH_NAMES 38 #include <arpa/telnet.h> 39 #ifdef __STDC__ 40 #include <stdlib.h> 41 #endif 42 #ifdef NO_STRING_H 43 #include <strings.h> 44 #else 45 #include <string.h> 46 #endif 47 48 #include "encrypt.h" 49 #include "auth.h" 50 #include "misc-proto.h" 51 #include "auth-proto.h" 52 53 #define typemask(x) (1<<((x)-1)) 54 55 #ifdef KRB4_ENCPWD 56 extern krb4encpwd_init(); 57 extern krb4encpwd_send(); 58 extern krb4encpwd_is(); 59 extern krb4encpwd_reply(); 60 extern krb4encpwd_status(); 61 extern krb4encpwd_printsub(); 62 #endif 63 64 #ifdef RSA_ENCPWD 65 extern rsaencpwd_init(); 66 extern rsaencpwd_send(); 67 extern rsaencpwd_is(); 68 extern rsaencpwd_reply(); 69 extern rsaencpwd_status(); 70 extern rsaencpwd_printsub(); 71 #endif 72 73 int auth_debug_mode = 0; 74 static char *Name = "Noname"; 75 static int Server = 0; 76 static Authenticator *authenticated = 0; 77 static int authenticating = 0; 78 static int validuser = 0; 79 static unsigned char _auth_send_data[256]; 80 static unsigned char *auth_send_data; 81 static int auth_send_cnt = 0; 82 83 /* 84 * Authentication types supported. Plese note that these are stored 85 * in priority order, i.e. try the first one first. 86 */ 87 Authenticator authenticators[] = { 88 #ifdef SPX 89 { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 90 spx_init, 91 spx_send, 92 spx_is, 93 spx_reply, 94 spx_status, 95 spx_printsub }, 96 { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 97 spx_init, 98 spx_send, 99 spx_is, 100 spx_reply, 101 spx_status, 102 spx_printsub }, 103 #endif 104 #ifdef KRB5 105 # ifdef ENCRYPTION 106 { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 107 kerberos5_init, 108 kerberos5_send, 109 kerberos5_is, 110 kerberos5_reply, 111 kerberos5_status, 112 kerberos5_printsub }, 113 # endif /* ENCRYPTION */ 114 { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 115 kerberos5_init, 116 kerberos5_send, 117 kerberos5_is, 118 kerberos5_reply, 119 kerberos5_status, 120 kerberos5_printsub }, 121 #endif 122 #ifdef KRB4 123 # ifdef ENCRYPTION 124 { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 125 kerberos4_init, 126 kerberos4_send, 127 kerberos4_is, 128 kerberos4_reply, 129 kerberos4_status, 130 kerberos4_printsub }, 131 # endif /* ENCRYPTION */ 132 { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 133 kerberos4_init, 134 kerberos4_send, 135 kerberos4_is, 136 kerberos4_reply, 137 kerberos4_status, 138 kerberos4_printsub }, 139 #endif 140 #ifdef KRB4_ENCPWD 141 { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 142 krb4encpwd_init, 143 krb4encpwd_send, 144 krb4encpwd_is, 145 krb4encpwd_reply, 146 krb4encpwd_status, 147 krb4encpwd_printsub }, 148 #endif 149 #ifdef RSA_ENCPWD 150 { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 151 rsaencpwd_init, 152 rsaencpwd_send, 153 rsaencpwd_is, 154 rsaencpwd_reply, 155 rsaencpwd_status, 156 rsaencpwd_printsub }, 157 #endif 158 { 0, }, 159 }; 160 161 static Authenticator NoAuth = { 0 }; 162 163 static int i_support = 0; 164 static int i_wont_support = 0; 165 166 Authenticator * 167 findauthenticator(type, way) 168 int type; 169 int way; 170 { 171 Authenticator *ap = authenticators; 172 173 while (ap->type && (ap->type != type || ap->way != way)) 174 ++ap; 175 return(ap->type ? ap : 0); 176 } 177 178 void 179 auth_init(name, server) 180 char *name; 181 int server; 182 { 183 Authenticator *ap = authenticators; 184 185 Server = server; 186 Name = name; 187 188 i_support = 0; 189 authenticated = 0; 190 authenticating = 0; 191 while (ap->type) { 192 if (!ap->init || (*ap->init)(ap, server)) { 193 i_support |= typemask(ap->type); 194 if (auth_debug_mode) 195 printf(">>>%s: I support auth type %d %d\r\n", 196 Name, 197 ap->type, ap->way); 198 } 199 else if (auth_debug_mode) 200 printf(">>>%s: Init failed: auth type %d %d\r\n", 201 Name, ap->type, ap->way); 202 ++ap; 203 } 204 } 205 206 void 207 auth_disable_name(name) 208 char *name; 209 { 210 int x; 211 for (x = 0; x < AUTHTYPE_CNT; ++x) { 212 if (!strcasecmp(name, AUTHTYPE_NAME(x))) { 213 i_wont_support |= typemask(x); 214 break; 215 } 216 } 217 } 218 219 int 220 getauthmask(type, maskp) 221 char *type; 222 int *maskp; 223 { 224 register int x; 225 226 if (!strcasecmp(type, AUTHTYPE_NAME(0))) { 227 *maskp = -1; 228 return(1); 229 } 230 231 for (x = 1; x < AUTHTYPE_CNT; ++x) { 232 if (!strcasecmp(type, AUTHTYPE_NAME(x))) { 233 *maskp = typemask(x); 234 return(1); 235 } 236 } 237 return(0); 238 } 239 240 int 241 auth_enable(type) 242 char *type; 243 { 244 return(auth_onoff(type, 1)); 245 } 246 247 int 248 auth_disable(type) 249 char *type; 250 { 251 return(auth_onoff(type, 0)); 252 } 253 254 int 255 auth_onoff(type, on) 256 char *type; 257 int on; 258 { 259 int i, mask = -1; 260 Authenticator *ap; 261 262 if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { 263 printf("auth %s 'type'\n", on ? "enable" : "disable"); 264 printf("Where 'type' is one of:\n"); 265 printf("\t%s\n", AUTHTYPE_NAME(0)); 266 mask = 0; 267 for (ap = authenticators; ap->type; ap++) { 268 if ((mask & (i = typemask(ap->type))) != 0) 269 continue; 270 mask |= i; 271 printf("\t%s\n", AUTHTYPE_NAME(ap->type)); 272 } 273 return(0); 274 } 275 276 if (!getauthmask(type, &mask)) { 277 printf("%s: invalid authentication type\n", type); 278 return(0); 279 } 280 if (on) 281 i_wont_support &= ~mask; 282 else 283 i_wont_support |= mask; 284 return(1); 285 } 286 287 int 288 auth_togdebug(on) 289 int on; 290 { 291 if (on < 0) 292 auth_debug_mode ^= 1; 293 else 294 auth_debug_mode = on; 295 printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); 296 return(1); 297 } 298 299 int 300 auth_status() 301 { 302 Authenticator *ap; 303 int i, mask; 304 305 if (i_wont_support == -1) 306 printf("Authentication disabled\n"); 307 else 308 printf("Authentication enabled\n"); 309 310 mask = 0; 311 for (ap = authenticators; ap->type; ap++) { 312 if ((mask & (i = typemask(ap->type))) != 0) 313 continue; 314 mask |= i; 315 printf("%s: %s\n", AUTHTYPE_NAME(ap->type), 316 (i_wont_support & typemask(ap->type)) ? 317 "disabled" : "enabled"); 318 } 319 return(1); 320 } 321 322 /* 323 * This routine is called by the server to start authentication 324 * negotiation. 325 */ 326 void 327 auth_request() 328 { 329 static unsigned char str_request[64] = { IAC, SB, 330 TELOPT_AUTHENTICATION, 331 TELQUAL_SEND, }; 332 Authenticator *ap = authenticators; 333 unsigned char *e = str_request + 4; 334 335 if (!authenticating) { 336 authenticating = 1; 337 while (ap->type) { 338 if (i_support & ~i_wont_support & typemask(ap->type)) { 339 if (auth_debug_mode) { 340 printf(">>>%s: Sending type %d %d\r\n", 341 Name, ap->type, ap->way); 342 } 343 *e++ = ap->type; 344 *e++ = ap->way; 345 } 346 ++ap; 347 } 348 *e++ = IAC; 349 *e++ = SE; 350 net_write(str_request, e - str_request); 351 printsub('>', &str_request[2], e - str_request - 2); 352 } 353 } 354 355 /* 356 * This is called when an AUTH SEND is received. 357 * It should never arrive on the server side (as only the server can 358 * send an AUTH SEND). 359 * You should probably respond to it if you can... 360 * 361 * If you want to respond to the types out of order (i.e. even 362 * if he sends LOGIN KERBEROS and you support both, you respond 363 * with KERBEROS instead of LOGIN (which is against what the 364 * protocol says)) you will have to hack this code... 365 */ 366 void 367 auth_send(data, cnt) 368 unsigned char *data; 369 int cnt; 370 { 371 Authenticator *ap; 372 static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, 373 TELQUAL_IS, AUTHTYPE_NULL, 0, 374 IAC, SE }; 375 if (Server) { 376 if (auth_debug_mode) { 377 printf(">>>%s: auth_send called!\r\n", Name); 378 } 379 return; 380 } 381 382 if (auth_debug_mode) { 383 printf(">>>%s: auth_send got:", Name); 384 printd(data, cnt); printf("\r\n"); 385 } 386 387 /* 388 * Save the data, if it is new, so that we can continue looking 389 * at it if the authorization we try doesn't work 390 */ 391 if (data < _auth_send_data || 392 data > _auth_send_data + sizeof(_auth_send_data)) { 393 auth_send_cnt = cnt > sizeof(_auth_send_data) 394 ? sizeof(_auth_send_data) 395 : cnt; 396 bcopy((void *)data, (void *)_auth_send_data, auth_send_cnt); 397 auth_send_data = _auth_send_data; 398 } else { 399 /* 400 * This is probably a no-op, but we just make sure 401 */ 402 auth_send_data = data; 403 auth_send_cnt = cnt; 404 } 405 while ((auth_send_cnt -= 2) >= 0) { 406 if (auth_debug_mode) 407 printf(">>>%s: He supports %d\r\n", 408 Name, *auth_send_data); 409 if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { 410 ap = findauthenticator(auth_send_data[0], 411 auth_send_data[1]); 412 if (ap && ap->send) { 413 if (auth_debug_mode) 414 printf(">>>%s: Trying %d %d\r\n", 415 Name, auth_send_data[0], 416 auth_send_data[1]); 417 if ((*ap->send)(ap)) { 418 /* 419 * Okay, we found one we like 420 * and did it. 421 * we can go home now. 422 */ 423 if (auth_debug_mode) 424 printf(">>>%s: Using type %d\r\n", 425 Name, *auth_send_data); 426 auth_send_data += 2; 427 return; 428 } 429 } 430 /* else 431 * just continue on and look for the 432 * next one if we didn't do anything. 433 */ 434 } 435 auth_send_data += 2; 436 } 437 net_write(str_none, sizeof(str_none)); 438 printsub('>', &str_none[2], sizeof(str_none) - 2); 439 if (auth_debug_mode) 440 printf(">>>%s: Sent failure message\r\n", Name); 441 auth_finished(0, AUTH_REJECT); 442 #ifdef KANNAN 443 /* 444 * We requested strong authentication, however no mechanisms worked. 445 * Therefore, exit on client end. 446 */ 447 printf("Unable to securely authenticate user ... exit\n"); 448 exit(0); 449 #endif /* KANNAN */ 450 } 451 452 void 453 auth_send_retry() 454 { 455 /* 456 * if auth_send_cnt <= 0 then auth_send will end up rejecting 457 * the authentication and informing the other side of this. 458 */ 459 auth_send(auth_send_data, auth_send_cnt); 460 } 461 462 void 463 auth_is(data, cnt) 464 unsigned char *data; 465 int cnt; 466 { 467 Authenticator *ap; 468 469 if (cnt < 2) 470 return; 471 472 if (data[0] == AUTHTYPE_NULL) { 473 auth_finished(0, AUTH_REJECT); 474 return; 475 } 476 477 if (ap = findauthenticator(data[0], data[1])) { 478 if (ap->is) 479 (*ap->is)(ap, data+2, cnt-2); 480 } else if (auth_debug_mode) 481 printf(">>>%s: Invalid authentication in IS: %d\r\n", 482 Name, *data); 483 } 484 485 void 486 auth_reply(data, cnt) 487 unsigned char *data; 488 int cnt; 489 { 490 Authenticator *ap; 491 492 if (cnt < 2) 493 return; 494 495 if (ap = findauthenticator(data[0], data[1])) { 496 if (ap->reply) 497 (*ap->reply)(ap, data+2, cnt-2); 498 } else if (auth_debug_mode) 499 printf(">>>%s: Invalid authentication in SEND: %d\r\n", 500 Name, *data); 501 } 502 503 void 504 auth_name(data, cnt) 505 unsigned char *data; 506 int cnt; 507 { 508 Authenticator *ap; 509 unsigned char savename[256]; 510 511 if (cnt < 1) { 512 if (auth_debug_mode) 513 printf(">>>%s: Empty name in NAME\r\n", Name); 514 return; 515 } 516 if (cnt > sizeof(savename) - 1) { 517 if (auth_debug_mode) 518 printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", 519 Name, cnt, sizeof(savename)-1); 520 return; 521 } 522 bcopy((void *)data, (void *)savename, cnt); 523 savename[cnt] = '\0'; /* Null terminate */ 524 if (auth_debug_mode) 525 printf(">>>%s: Got NAME [%s]\r\n", Name, savename); 526 auth_encrypt_user(savename); 527 } 528 529 int 530 auth_sendname(cp, len) 531 unsigned char *cp; 532 int len; 533 { 534 static unsigned char str_request[256+6] 535 = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; 536 register unsigned char *e = str_request + 4; 537 register unsigned char *ee = &str_request[sizeof(str_request)-2]; 538 539 while (--len >= 0) { 540 if ((*e++ = *cp++) == IAC) 541 *e++ = IAC; 542 if (e >= ee) 543 return(0); 544 } 545 *e++ = IAC; 546 *e++ = SE; 547 net_write(str_request, e - str_request); 548 printsub('>', &str_request[2], e - &str_request[2]); 549 return(1); 550 } 551 552 void 553 auth_finished(ap, result) 554 Authenticator *ap; 555 int result; 556 { 557 if (!(authenticated = ap)) 558 authenticated = &NoAuth; 559 validuser = result; 560 } 561 562 /* ARGSUSED */ 563 static void 564 auth_intr(sig) 565 int sig; 566 { 567 auth_finished(0, AUTH_REJECT); 568 } 569 570 int 571 auth_wait(name) 572 char *name; 573 { 574 if (auth_debug_mode) 575 printf(">>>%s: in auth_wait.\r\n", Name); 576 577 if (Server && !authenticating) 578 return(0); 579 580 (void) signal(SIGALRM, auth_intr); 581 alarm(30); 582 while (!authenticated) 583 if (telnet_spin()) 584 break; 585 alarm(0); 586 (void) signal(SIGALRM, SIG_DFL); 587 588 /* 589 * Now check to see if the user is valid or not 590 */ 591 if (!authenticated || authenticated == &NoAuth) 592 return(AUTH_REJECT); 593 594 if (validuser == AUTH_VALID) 595 validuser = AUTH_USER; 596 597 if (authenticated->status) 598 validuser = (*authenticated->status)(authenticated, 599 name, validuser); 600 return(validuser); 601 } 602 603 void 604 auth_debug(mode) 605 int mode; 606 { 607 auth_debug_mode = mode; 608 } 609 610 void 611 auth_printsub(data, cnt, buf, buflen) 612 unsigned char *data, *buf; 613 int cnt, buflen; 614 { 615 Authenticator *ap; 616 617 if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) 618 (*ap->printsub)(data, cnt, buf, buflen); 619 else 620 auth_gen_printsub(data, cnt, buf, buflen); 621 } 622 623 void 624 auth_gen_printsub(data, cnt, buf, buflen) 625 unsigned char *data, *buf; 626 int cnt, buflen; 627 { 628 register unsigned char *cp; 629 unsigned char tbuf[16]; 630 631 cnt -= 3; 632 data += 3; 633 buf[buflen-1] = '\0'; 634 buf[buflen-2] = '*'; 635 buflen -= 2; 636 for (; cnt > 0; cnt--, data++) { 637 sprintf((char *)tbuf, " %d", *data); 638 for (cp = tbuf; *cp && buflen > 0; --buflen) 639 *buf++ = *cp++; 640 if (buflen <= 0) 641 return; 642 } 643 *buf = '\0'; 644 } 645 #endif 646