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