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