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