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