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