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.1 (Berkeley) 06/04/93"; 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 ++ap; 200 } 201 } 202 203 void 204 auth_disable_name(name) 205 char *name; 206 { 207 int x; 208 for (x = 0; x < AUTHTYPE_CNT; ++x) { 209 if (!strcasecmp(name, AUTHTYPE_NAME(x))) { 210 i_wont_support |= typemask(x); 211 break; 212 } 213 } 214 } 215 216 int 217 getauthmask(type, maskp) 218 char *type; 219 int *maskp; 220 { 221 register int x; 222 223 if (strcasecmp(type, AUTHTYPE_NAME(0))) { 224 *maskp = -1; 225 return(1); 226 } 227 228 for (x = 1; x < AUTHTYPE_CNT; ++x) { 229 if (!strcasecmp(type, AUTHTYPE_NAME(x))) { 230 *maskp = typemask(x); 231 return(1); 232 } 233 } 234 return(0); 235 } 236 237 int 238 auth_enable(type) 239 int type; 240 { 241 return(auth_onoff(type, 1)); 242 } 243 244 int 245 auth_disable(type) 246 int type; 247 { 248 return(auth_onoff(type, 0)); 249 } 250 251 int 252 auth_onoff(type, on) 253 char *type; 254 int on; 255 { 256 int mask = -1; 257 Authenticator *ap; 258 259 if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { 260 printf("auth %s 'type'\n", on ? "enable" : "disable"); 261 printf("Where 'type' is one of:\n"); 262 printf("\t%s\n", AUTHTYPE_NAME(0)); 263 for (ap = authenticators; ap->type; ap++) 264 printf("\t%s\n", AUTHTYPE_NAME(ap->type)); 265 return(0); 266 } 267 268 if (!getauthmask(type, &mask)) { 269 printf("%s: invalid authentication type\n", type); 270 return(0); 271 } 272 mask = getauthmask(type, &mask); 273 if (on) 274 i_wont_support &= ~mask; 275 else 276 i_wont_support |= mask; 277 return(1); 278 } 279 280 int 281 auth_togdebug(on) 282 int on; 283 { 284 if (on < 0) 285 auth_debug_mode ^= 1; 286 else 287 auth_debug_mode = on; 288 printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); 289 return(1); 290 } 291 292 int 293 auth_status() 294 { 295 Authenticator *ap; 296 297 if (i_wont_support == -1) 298 printf("Authentication disabled\n"); 299 else 300 printf("Authentication enabled\n"); 301 302 for (ap = authenticators; ap->type; ap++) 303 printf("%s: %s\n", AUTHTYPE_NAME(ap->type), 304 (i_wont_support & typemask(ap->type)) ? 305 "disabled" : "enabled"); 306 return(1); 307 } 308 309 /* 310 * This routine is called by the server to start authentication 311 * negotiation. 312 */ 313 void 314 auth_request() 315 { 316 static unsigned char str_request[64] = { IAC, SB, 317 TELOPT_AUTHENTICATION, 318 TELQUAL_SEND, }; 319 Authenticator *ap = authenticators; 320 unsigned char *e = str_request + 4; 321 322 if (!authenticating) { 323 authenticating = 1; 324 while (ap->type) { 325 if (i_support & ~i_wont_support & typemask(ap->type)) { 326 if (auth_debug_mode) { 327 printf(">>>%s: Sending type %d %d\r\n", 328 Name, ap->type, ap->way); 329 } 330 *e++ = ap->type; 331 *e++ = ap->way; 332 } 333 ++ap; 334 } 335 *e++ = IAC; 336 *e++ = SE; 337 net_write(str_request, e - str_request); 338 printsub('>', &str_request[2], e - str_request - 2); 339 } 340 } 341 342 /* 343 * This is called when an AUTH SEND is received. 344 * It should never arrive on the server side (as only the server can 345 * send an AUTH SEND). 346 * You should probably respond to it if you can... 347 * 348 * If you want to respond to the types out of order (i.e. even 349 * if he sends LOGIN KERBEROS and you support both, you respond 350 * with KERBEROS instead of LOGIN (which is against what the 351 * protocol says)) you will have to hack this code... 352 */ 353 void 354 auth_send(data, cnt) 355 unsigned char *data; 356 int cnt; 357 { 358 Authenticator *ap; 359 static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, 360 TELQUAL_IS, AUTHTYPE_NULL, 0, 361 IAC, SE }; 362 if (Server) { 363 if (auth_debug_mode) { 364 printf(">>>%s: auth_send called!\r\n", Name); 365 } 366 return; 367 } 368 369 if (auth_debug_mode) { 370 printf(">>>%s: auth_send got:", Name); 371 printd(data, cnt); printf("\r\n"); 372 } 373 374 /* 375 * Save the data, if it is new, so that we can continue looking 376 * at it if the authorization we try doesn't work 377 */ 378 if (data < _auth_send_data || 379 data > _auth_send_data + sizeof(_auth_send_data)) { 380 auth_send_cnt = cnt > sizeof(_auth_send_data) 381 ? sizeof(_auth_send_data) 382 : cnt; 383 bcopy((void *)data, (void *)_auth_send_data, auth_send_cnt); 384 auth_send_data = _auth_send_data; 385 } else { 386 /* 387 * This is probably a no-op, but we just make sure 388 */ 389 auth_send_data = data; 390 auth_send_cnt = cnt; 391 } 392 while ((auth_send_cnt -= 2) >= 0) { 393 if (auth_debug_mode) 394 printf(">>>%s: He supports %d\r\n", 395 Name, *auth_send_data); 396 if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { 397 ap = findauthenticator(auth_send_data[0], 398 auth_send_data[1]); 399 if (ap && ap->send) { 400 if (auth_debug_mode) 401 printf(">>>%s: Trying %d %d\r\n", 402 Name, auth_send_data[0], 403 auth_send_data[1]); 404 if ((*ap->send)(ap)) { 405 /* 406 * Okay, we found one we like 407 * and did it. 408 * we can go home now. 409 */ 410 if (auth_debug_mode) 411 printf(">>>%s: Using type %d\r\n", 412 Name, *auth_send_data); 413 auth_send_data += 2; 414 return; 415 } 416 } 417 /* else 418 * just continue on and look for the 419 * next one if we didn't do anything. 420 */ 421 } 422 auth_send_data += 2; 423 } 424 net_write(str_none, sizeof(str_none)); 425 printsub('>', &str_none[2], sizeof(str_none) - 2); 426 if (auth_debug_mode) 427 printf(">>>%s: Sent failure message\r\n", Name); 428 auth_finished(0, AUTH_REJECT); 429 #ifdef KANNAN 430 /* 431 * We requested strong authentication, however no mechanisms worked. 432 * Therefore, exit on client end. 433 */ 434 printf("Unable to securely authenticate user ... exit\n"); 435 exit(0); 436 #endif /* KANNAN */ 437 } 438 439 void 440 auth_send_retry() 441 { 442 /* 443 * if auth_send_cnt <= 0 then auth_send will end up rejecting 444 * the authentication and informing the other side of this. 445 */ 446 auth_send(auth_send_data, auth_send_cnt); 447 } 448 449 void 450 auth_is(data, cnt) 451 unsigned char *data; 452 int cnt; 453 { 454 Authenticator *ap; 455 456 if (cnt < 2) 457 return; 458 459 if (data[0] == AUTHTYPE_NULL) { 460 auth_finished(0, AUTH_REJECT); 461 return; 462 } 463 464 if (ap = findauthenticator(data[0], data[1])) { 465 if (ap->is) 466 (*ap->is)(ap, data+2, cnt-2); 467 } else if (auth_debug_mode) 468 printf(">>>%s: Invalid authentication in IS: %d\r\n", 469 Name, *data); 470 } 471 472 void 473 auth_reply(data, cnt) 474 unsigned char *data; 475 int cnt; 476 { 477 Authenticator *ap; 478 479 if (cnt < 2) 480 return; 481 482 if (ap = findauthenticator(data[0], data[1])) { 483 if (ap->reply) 484 (*ap->reply)(ap, data+2, cnt-2); 485 } else if (auth_debug_mode) 486 printf(">>>%s: Invalid authentication in SEND: %d\r\n", 487 Name, *data); 488 } 489 490 void 491 auth_name(data, cnt) 492 unsigned char *data; 493 int cnt; 494 { 495 Authenticator *ap; 496 unsigned char savename[256]; 497 498 if (cnt < 1) { 499 if (auth_debug_mode) 500 printf(">>>%s: Empty name in NAME\r\n", Name); 501 return; 502 } 503 if (cnt > sizeof(savename) - 1) { 504 if (auth_debug_mode) 505 printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", 506 Name, cnt, sizeof(savename)-1); 507 return; 508 } 509 bcopy((void *)data, (void *)savename, cnt); 510 savename[cnt] = '\0'; /* Null terminate */ 511 if (auth_debug_mode) 512 printf(">>>%s: Got NAME [%s]\r\n", Name, savename); 513 auth_encrypt_user(savename); 514 } 515 516 int 517 auth_sendname(cp, len) 518 unsigned char *cp; 519 int len; 520 { 521 static unsigned char str_request[256+6] 522 = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; 523 register unsigned char *e = str_request + 4; 524 register unsigned char *ee = &str_request[sizeof(str_request)-2]; 525 526 while (--len >= 0) { 527 if ((*e++ = *cp++) == IAC) 528 *e++ = IAC; 529 if (e >= ee) 530 return(0); 531 } 532 *e++ = IAC; 533 *e++ = SE; 534 net_write(str_request, e - str_request); 535 printsub('>', &str_request[2], e - &str_request[2]); 536 return(1); 537 } 538 539 void 540 auth_finished(ap, result) 541 Authenticator *ap; 542 int result; 543 { 544 if (!(authenticated = ap)) 545 authenticated = &NoAuth; 546 validuser = result; 547 } 548 549 /* ARGSUSED */ 550 static void 551 auth_intr(sig) 552 int sig; 553 { 554 auth_finished(0, AUTH_REJECT); 555 } 556 557 int 558 auth_wait(name) 559 char *name; 560 { 561 if (auth_debug_mode) 562 printf(">>>%s: in auth_wait.\r\n", Name); 563 564 if (Server && !authenticating) 565 return(0); 566 567 (void) signal(SIGALRM, auth_intr); 568 alarm(30); 569 while (!authenticated) 570 if (telnet_spin()) 571 break; 572 alarm(0); 573 (void) signal(SIGALRM, SIG_DFL); 574 575 /* 576 * Now check to see if the user is valid or not 577 */ 578 if (!authenticated || authenticated == &NoAuth) 579 return(AUTH_REJECT); 580 581 if (validuser == AUTH_VALID) 582 validuser = AUTH_USER; 583 584 if (authenticated->status) 585 validuser = (*authenticated->status)(authenticated, 586 name, validuser); 587 return(validuser); 588 } 589 590 void 591 auth_debug(mode) 592 int mode; 593 { 594 auth_debug_mode = mode; 595 } 596 597 void 598 auth_printsub(data, cnt, buf, buflen) 599 unsigned char *data, *buf; 600 int cnt, buflen; 601 { 602 Authenticator *ap; 603 604 if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) 605 (*ap->printsub)(data, cnt, buf, buflen); 606 else 607 auth_gen_printsub(data, cnt, buf, buflen); 608 } 609 610 void 611 auth_gen_printsub(data, cnt, buf, buflen) 612 unsigned char *data, *buf; 613 int cnt, buflen; 614 { 615 register unsigned char *cp; 616 unsigned char tbuf[16]; 617 618 cnt -= 3; 619 data += 3; 620 buf[buflen-1] = '\0'; 621 buf[buflen-2] = '*'; 622 buflen -= 2; 623 for (; cnt > 0; cnt--, data++) { 624 sprintf((char *)tbuf, " %d", *data); 625 for (cp = tbuf; *cp && buflen > 0; --buflen) 626 *buf++ = *cp++; 627 if (buflen <= 0) 628 return; 629 } 630 *buf = '\0'; 631 } 632 #endif 633