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