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