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