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