146800Sdab /*- 246800Sdab * Copyright (c) 1991 The Regents of the University of California. 346800Sdab * All rights reserved. 446800Sdab * 546800Sdab * %sccs.include.redist.c% 646800Sdab */ 746800Sdab 846800Sdab #ifndef lint 9*47612Sdab static char sccsid[] = "@(#)auth.c 5.2 (Berkeley) 03/22/91"; 1046800Sdab #endif /* not lint */ 1146800Sdab 1246800Sdab /* 1346800Sdab * Copyright (C) 1990 by the Massachusetts Institute of Technology 1446800Sdab * 1546800Sdab * Export of this software from the United States of America is assumed 1646800Sdab * to require a specific license from the United States Government. 1746800Sdab * It is the responsibility of any person or organization contemplating 1846800Sdab * export to obtain such a license before exporting. 1946800Sdab * 2046800Sdab * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 2146800Sdab * distribute this software and its documentation for any purpose and 2246800Sdab * without fee is hereby granted, provided that the above copyright 2346800Sdab * notice appear in all copies and that both that copyright notice and 2446800Sdab * this permission notice appear in supporting documentation, and that 2546800Sdab * the name of M.I.T. not be used in advertising or publicity pertaining 2646800Sdab * to distribution of the software without specific, written prior 2746800Sdab * permission. M.I.T. makes no representations about the suitability of 2846800Sdab * this software for any purpose. It is provided "as is" without express 2946800Sdab * or implied warranty. 3046800Sdab */ 3146800Sdab 3246800Sdab 3346800Sdab #if defined(AUTHENTICATE) 3446800Sdab #include <stdio.h> 3546800Sdab #include <sys/types.h> 3646800Sdab #include <signal.h> 3746800Sdab #define AUTH_NAMES 3846800Sdab #include <arpa/telnet.h> 3946800Sdab #ifdef __STDC__ 4046800Sdab #include <stdlib.h> 4146800Sdab #endif 4246800Sdab #ifdef NO_STRING_H 4346800Sdab #include <strings.h> 4446800Sdab #else 4546800Sdab #include <string.h> 4646800Sdab #endif 4746800Sdab 4846800Sdab #include "encrypt.h" 4946800Sdab #include "auth.h" 5046800Sdab #include "misc-proto.h" 5146800Sdab #include "auth-proto.h" 5246800Sdab 5346800Sdab #define typemask(x) (1<<((x)-1)) 5446800Sdab 5546800Sdab int auth_debug_mode = 0; 5646800Sdab static char *Name = "Noname"; 5746800Sdab static int Server = 0; 5846800Sdab static Authenticator *authenticated = 0; 5946800Sdab static int authenticating = 0; 6046800Sdab static int validuser = 0; 6146800Sdab static unsigned char _auth_send_data[256]; 6246800Sdab static unsigned char *auth_send_data; 6346800Sdab static int auth_send_cnt = 0; 6446800Sdab 6546800Sdab /* 6646800Sdab * Authentication types supported. Plese note that these are stored 6746800Sdab * in priority order, i.e. try the first one first. 6846800Sdab */ 6946800Sdab Authenticator authenticators[] = { 7046800Sdab #ifdef KRB5 71*47612Sdab { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 72*47612Sdab kerberos5_init, 73*47612Sdab kerberos5_send, 74*47612Sdab kerberos5_is, 75*47612Sdab kerberos5_reply, 76*47612Sdab kerberos5_status, 77*47612Sdab kerberos5_printsub }, 7846800Sdab { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 7946800Sdab kerberos5_init, 8046800Sdab kerberos5_send, 8146800Sdab kerberos5_is, 8246800Sdab kerberos5_reply, 8346800Sdab kerberos5_status, 8446800Sdab kerberos5_printsub }, 8546800Sdab #endif 8646800Sdab #ifdef KRB4 87*47612Sdab { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, 88*47612Sdab kerberos4_init, 89*47612Sdab kerberos4_send, 90*47612Sdab kerberos4_is, 91*47612Sdab kerberos4_reply, 92*47612Sdab kerberos4_status, 93*47612Sdab kerberos4_printsub }, 9446800Sdab { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, 9546800Sdab kerberos4_init, 9646800Sdab kerberos4_send, 9746800Sdab kerberos4_is, 9846800Sdab kerberos4_reply, 9946800Sdab kerberos4_status, 10046800Sdab kerberos4_printsub }, 10146800Sdab #endif 10246800Sdab { 0, }, 10346800Sdab }; 10446800Sdab 10546800Sdab static Authenticator NoAuth = { 0 }; 10646800Sdab 10746800Sdab static int i_support = 0; 10846800Sdab static int i_wont_support = 0; 10946800Sdab 11046800Sdab Authenticator * 11146800Sdab findauthenticator(type, way) 11246800Sdab int type; 11346800Sdab int way; 11446800Sdab { 11546800Sdab Authenticator *ap = authenticators; 11646800Sdab 11746800Sdab while (ap->type && (ap->type != type || ap->way != way)) 11846800Sdab ++ap; 11946800Sdab return(ap->type ? ap : 0); 12046800Sdab } 12146800Sdab 12246800Sdab void 12346800Sdab auth_init(name, server) 12446800Sdab char *name; 12546800Sdab int server; 12646800Sdab { 12746800Sdab Authenticator *ap = authenticators; 12846800Sdab 12946800Sdab Server = server; 13046800Sdab Name = name; 13146800Sdab 13246800Sdab i_support = 0; 13346800Sdab authenticated = 0; 13446800Sdab authenticating = 0; 13546800Sdab while (ap->type) { 13646800Sdab if (!ap->init || (*ap->init)(ap, server)) { 13746800Sdab i_support |= typemask(ap->type); 13846800Sdab if (auth_debug_mode) 139*47612Sdab printf(">>>%s: I support auth type %d %d\r\n", 14046800Sdab Name, 141*47612Sdab ap->type, ap->way); 14246800Sdab } 14346800Sdab ++ap; 14446800Sdab } 14546800Sdab } 14646800Sdab 14746800Sdab void 14846800Sdab auth_disable_name(name) 14946800Sdab char *name; 15046800Sdab { 15146800Sdab int x; 15246800Sdab for (x = 0; x < AUTHTYPE_CNT; ++x) { 15346800Sdab if (!strcasecmp(name, AUTHTYPE_NAME(x))) { 15446800Sdab i_wont_support |= typemask(x); 15546800Sdab break; 15646800Sdab } 15746800Sdab } 15846800Sdab } 15946800Sdab 16046800Sdab int 16146800Sdab getauthmask(type, maskp) 16246800Sdab char *type; 16346800Sdab int *maskp; 16446800Sdab { 16546800Sdab register int x; 16646800Sdab 16746800Sdab if (strcasecmp(type, AUTHTYPE_NAME(0))) { 16846800Sdab *maskp = -1; 16946800Sdab return(1); 17046800Sdab } 17146800Sdab 17246800Sdab for (x = 1; x < AUTHTYPE_CNT; ++x) { 17346800Sdab if (!strcasecmp(type, AUTHTYPE_NAME(x))) { 17446800Sdab *maskp = typemask(x); 17546800Sdab return(1); 17646800Sdab } 17746800Sdab } 17846800Sdab return(0); 17946800Sdab } 18046800Sdab 18146800Sdab int 18246800Sdab auth_enable(type) 18346800Sdab int type; 18446800Sdab { 18546800Sdab return(auth_onoff(type, 1)); 18646800Sdab } 18746800Sdab 18846800Sdab int 18946800Sdab auth_disable(type) 19046800Sdab int type; 19146800Sdab { 19246800Sdab return(auth_onoff(type, 0)); 19346800Sdab } 19446800Sdab 19546800Sdab int 19646800Sdab auth_onoff(type, on) 19746800Sdab char *type; 19846800Sdab int on; 19946800Sdab { 20046800Sdab int mask = -1; 20146800Sdab Authenticator *ap; 20246800Sdab 20346800Sdab if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { 20446800Sdab printf("auth %s 'type'\n", on ? "enable" : "disable"); 20546800Sdab printf("Where 'type' is one of:\n"); 20646800Sdab printf("\t%s\n", AUTHTYPE_NAME(0)); 20746800Sdab for (ap = authenticators; ap->type; ap++) 20846800Sdab printf("\t%s\n", AUTHTYPE_NAME(ap->type)); 20946800Sdab return(0); 21046800Sdab } 21146800Sdab 21246800Sdab if (!getauthmask(type, &mask)) { 21346800Sdab printf("%s: invalid authentication type\n", type); 21446800Sdab return(0); 21546800Sdab } 21646800Sdab mask = getauthmask(type, &mask); 21746800Sdab if (on) 21846800Sdab i_wont_support &= ~mask; 21946800Sdab else 22046800Sdab i_wont_support |= mask; 22146800Sdab return(1); 22246800Sdab } 22346800Sdab 22446800Sdab int 225*47612Sdab auth_togdebug(on) 226*47612Sdab int on; 22746800Sdab { 228*47612Sdab if (on < 0) 229*47612Sdab auth_debug_mode ^= 1; 230*47612Sdab else 231*47612Sdab auth_debug_mode = on; 23246800Sdab printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); 23346800Sdab return(1); 23446800Sdab } 23546800Sdab 23646800Sdab int 23746800Sdab auth_status() 23846800Sdab { 23946800Sdab Authenticator *ap; 24046800Sdab 24146800Sdab if (i_wont_support == -1) 24246800Sdab printf("Authentication disabled\n"); 24346800Sdab else 24446800Sdab printf("Authentication enabled\n"); 24546800Sdab 24646800Sdab for (ap = authenticators; ap->type; ap++) 24746800Sdab printf("%s: %s\n", AUTHTYPE_NAME(ap->type), 24846800Sdab (i_wont_support & typemask(ap->type)) ? 24946800Sdab "disabled" : "enabled"); 25046800Sdab return(1); 25146800Sdab } 25246800Sdab 25346800Sdab /* 25446800Sdab * This routine is called by the server to start authentication 25546800Sdab * negotiation. 25646800Sdab */ 25746800Sdab void 25846800Sdab auth_request() 25946800Sdab { 26046800Sdab static unsigned char str_request[64] = { IAC, SB, 26146800Sdab TELOPT_AUTHENTICATION, 26246800Sdab TELQUAL_SEND, }; 26346800Sdab Authenticator *ap = authenticators; 26446800Sdab unsigned char *e = str_request + 4; 26546800Sdab 26646800Sdab if (!authenticating) { 26746800Sdab authenticating = 1; 26846800Sdab while (ap->type) { 26946800Sdab if (i_support & ~i_wont_support & typemask(ap->type)) { 27046800Sdab if (auth_debug_mode) { 271*47612Sdab printf(">>>%s: Sending type %d %d\r\n", 272*47612Sdab Name, ap->type, ap->way); 27346800Sdab } 27446800Sdab *e++ = ap->type; 27546800Sdab *e++ = ap->way; 27646800Sdab } 27746800Sdab ++ap; 27846800Sdab } 27946800Sdab *e++ = IAC; 28046800Sdab *e++ = SE; 28146800Sdab net_write(str_request, e - str_request); 28246800Sdab printsub('>', &str_request[2], e - str_request - 2); 28346800Sdab } 28446800Sdab } 28546800Sdab 28646800Sdab /* 28746800Sdab * This is called when an AUTH SEND is received. 28846800Sdab * It should never arrive on the server side (as only the server can 28946800Sdab * send an AUTH SEND). 29046800Sdab * You should probably respond to it if you can... 29146800Sdab * 29246800Sdab * If you want to respond to the types out of order (i.e. even 29346800Sdab * if he sends LOGIN KERBEROS and you support both, you respond 29446800Sdab * with KERBEROS instead of LOGIN (which is against what the 29546800Sdab * protocol says)) you will have to hack this code... 29646800Sdab */ 29746800Sdab void 29846800Sdab auth_send(data, cnt) 29946800Sdab unsigned char *data; 30046800Sdab int cnt; 30146800Sdab { 30246800Sdab Authenticator *ap; 30346800Sdab static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, 30446800Sdab TELQUAL_IS, AUTHTYPE_NULL, 0, 30546800Sdab IAC, SE }; 30646800Sdab if (Server) { 30746800Sdab if (auth_debug_mode) { 30846800Sdab printf(">>>%s: auth_send called!\r\n", Name); 30946800Sdab } 31046800Sdab return; 31146800Sdab } 31246800Sdab 31346800Sdab if (auth_debug_mode) { 31446800Sdab printf(">>>%s: auth_send got:", Name); 31546800Sdab printd(data, cnt); printf("\r\n"); 31646800Sdab } 31746800Sdab 31846800Sdab /* 31946800Sdab * Save the data, if it is new, so that we can continue looking 32046800Sdab * at it if the authorization we try doesn't work 32146800Sdab */ 32246800Sdab if (data < _auth_send_data || 32346800Sdab data > _auth_send_data + sizeof(_auth_send_data)) { 32446800Sdab auth_send_cnt = cnt > sizeof(_auth_send_data) 32546800Sdab ? sizeof(_auth_send_data) 32646800Sdab : cnt; 32746800Sdab bcopy((void *)data, (void *)_auth_send_data, auth_send_cnt); 32846800Sdab auth_send_data = _auth_send_data; 32946800Sdab } else { 33046800Sdab /* 33146800Sdab * This is probably a no-op, but we just make sure 33246800Sdab */ 33346800Sdab auth_send_data = data; 33446800Sdab auth_send_cnt = cnt; 33546800Sdab } 33646800Sdab while ((auth_send_cnt -= 2) >= 0) { 33746800Sdab if (auth_debug_mode) 33846800Sdab printf(">>>%s: He supports %d\r\n", 33946800Sdab Name, *auth_send_data); 34046800Sdab if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { 34146800Sdab ap = findauthenticator(auth_send_data[0], 34246800Sdab auth_send_data[1]); 34346800Sdab if (!ap) { 34446800Sdab printf("Internal state error: cannot find authentication type %d a second time\r\n", *auth_send_data); 34546800Sdab } else if (ap->send) { 34646800Sdab if (auth_debug_mode) 347*47612Sdab printf(">>>%s: Trying %d %d\r\n", 348*47612Sdab Name, auth_send_data[0], 349*47612Sdab auth_send_data[1]); 35046800Sdab if ((*ap->send)(ap)) { 35146800Sdab /* 35246800Sdab * Okay, we found one we like 35346800Sdab * and did it. 35446800Sdab * we can go home now. 35546800Sdab */ 35646800Sdab if (auth_debug_mode) 35746800Sdab printf(">>>%s: Using type %d\r\n", 35846800Sdab Name, *auth_send_data); 35946800Sdab auth_send_data += 2; 36046800Sdab return; 36146800Sdab } 36246800Sdab } 36346800Sdab /* else 36446800Sdab * just continue on and look for the 36546800Sdab * next one if we didn't do anything. 36646800Sdab */ 36746800Sdab } 36846800Sdab auth_send_data += 2; 36946800Sdab } 37046800Sdab net_write(str_none, sizeof(str_none)); 37146800Sdab printsub('>', &str_none[2], sizeof(str_none) - 2); 37246800Sdab if (auth_debug_mode) 37346800Sdab printf(">>>%s: Sent failure message\r\n", Name); 37446800Sdab auth_finished(0, AUTH_REJECT); 37546800Sdab } 37646800Sdab 37746800Sdab void 37846800Sdab auth_send_retry() 37946800Sdab { 38046800Sdab /* 38146800Sdab * if auth_send_cnt <= 0 then auth_send will end up rejecting 38246800Sdab * the authentication and informing the other side of this. 38346800Sdab */ 38446800Sdab auth_send(auth_send_data, auth_send_cnt); 38546800Sdab } 38646800Sdab 38746800Sdab void 38846800Sdab auth_is(data, cnt) 38946800Sdab unsigned char *data; 39046800Sdab int cnt; 39146800Sdab { 39246800Sdab Authenticator *ap; 39346800Sdab 39446800Sdab if (cnt < 2) 39546800Sdab return; 39646800Sdab 39746800Sdab if (data[0] == AUTHTYPE_NULL) { 39846800Sdab auth_finished(0, AUTH_REJECT); 39946800Sdab return; 40046800Sdab } 40146800Sdab 40246800Sdab if (ap = findauthenticator(data[0], data[1])) { 40346800Sdab if (ap->is) 40446800Sdab (*ap->is)(ap, data+2, cnt-2); 40546800Sdab } else if (auth_debug_mode) 40646800Sdab printf(">>>%s: Invalid authentication in IS: %d\r\n", 40746800Sdab Name, *data); 40846800Sdab } 40946800Sdab 41046800Sdab void 41146800Sdab auth_reply(data, cnt) 41246800Sdab unsigned char *data; 41346800Sdab int cnt; 41446800Sdab { 41546800Sdab Authenticator *ap; 41646800Sdab 41746800Sdab if (cnt < 2) 41846800Sdab return; 41946800Sdab 42046800Sdab if (ap = findauthenticator(data[0], data[1])) { 42146800Sdab if (ap->reply) 42246800Sdab (*ap->reply)(ap, data+2, cnt-2); 42346800Sdab } else if (auth_debug_mode) 42446800Sdab printf(">>>%s: Invalid authentication in SEND: %d\r\n", 42546800Sdab Name, *data); 42646800Sdab } 42746800Sdab 42846800Sdab void 429*47612Sdab auth_name(data, cnt) 430*47612Sdab unsigned char *data; 431*47612Sdab int cnt; 432*47612Sdab { 433*47612Sdab Authenticator *ap; 434*47612Sdab unsigned char savename[256]; 435*47612Sdab 436*47612Sdab if (cnt < 1) { 437*47612Sdab if (auth_debug_mode) 438*47612Sdab printf(">>>%s: Empty name in NAME\r\n", Name); 439*47612Sdab return; 440*47612Sdab } 441*47612Sdab if (cnt > sizeof(savename) - 1) { 442*47612Sdab if (auth_debug_mode) 443*47612Sdab printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", 444*47612Sdab Name, cnt, sizeof(savename)-1); 445*47612Sdab return; 446*47612Sdab } 447*47612Sdab bcopy((void *)data, (void *)savename, cnt); 448*47612Sdab savename[cnt] = '\0'; /* Null terminate */ 449*47612Sdab if (auth_debug_mode) 450*47612Sdab printf(">>>%s: Got NAME [%s]\r\n", Name, savename); 451*47612Sdab auth_encrypt_user(savename); 452*47612Sdab } 453*47612Sdab 454*47612Sdab int 455*47612Sdab auth_sendname(cp, len) 456*47612Sdab unsigned char *cp; 457*47612Sdab int len; 458*47612Sdab { 459*47612Sdab static unsigned char str_request[256+6] 460*47612Sdab = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; 461*47612Sdab register unsigned char *e = str_request + 4; 462*47612Sdab register unsigned char *ee = &str_request[sizeof(str_request)-2]; 463*47612Sdab 464*47612Sdab while (--len >= 0) { 465*47612Sdab if ((*e++ = *cp++) == IAC) 466*47612Sdab *e++ = IAC; 467*47612Sdab if (e >= ee) 468*47612Sdab return(0); 469*47612Sdab } 470*47612Sdab *e++ = IAC; 471*47612Sdab *e++ = SE; 472*47612Sdab net_write(str_request, e - str_request); 473*47612Sdab printsub('>', &str_request[2], e - &str_request[2]); 474*47612Sdab return(1); 475*47612Sdab } 476*47612Sdab 477*47612Sdab void 47846800Sdab auth_finished(ap, result) 47946800Sdab Authenticator *ap; 48046800Sdab int result; 48146800Sdab { 48246800Sdab if (!(authenticated = ap)) 48346800Sdab authenticated = &NoAuth; 48446800Sdab validuser = result; 48546800Sdab } 48646800Sdab 48746800Sdab /* ARGSUSED */ 48846800Sdab static void 48946800Sdab auth_intr(sig) 49046800Sdab int sig; 49146800Sdab { 49246800Sdab auth_finished(0, AUTH_REJECT); 49346800Sdab } 49446800Sdab 49546800Sdab int 49646800Sdab auth_wait(name) 49746800Sdab char *name; 49846800Sdab { 49946800Sdab if (auth_debug_mode) 50046800Sdab printf(">>>%s: in auth_wait.\r\n", Name); 50146800Sdab 50246800Sdab if (Server && !authenticating) 50346800Sdab return(0); 50446800Sdab 50546800Sdab (void) signal(SIGALRM, auth_intr); 50646800Sdab alarm(30); 50746800Sdab while (!authenticated) 50846800Sdab if (telnet_spin()) 50946800Sdab break; 51046800Sdab alarm(0); 51146800Sdab (void) signal(SIGALRM, SIG_DFL); 51246800Sdab 51346800Sdab /* 51446800Sdab * Now check to see if the user is valid or not 51546800Sdab */ 51646800Sdab if (!authenticated || authenticated == &NoAuth) 51746800Sdab return(AUTH_REJECT); 51846800Sdab 51946800Sdab if (validuser == AUTH_VALID) 52046800Sdab validuser = AUTH_USER; 52146800Sdab 52246800Sdab if (authenticated->status) 52346800Sdab validuser = (*authenticated->status)(authenticated, 52446800Sdab name, validuser); 52546800Sdab return(validuser); 52646800Sdab } 52746800Sdab 52846800Sdab void 52946800Sdab auth_debug(mode) 53046800Sdab int mode; 53146800Sdab { 53246800Sdab auth_debug_mode = mode; 53346800Sdab } 53446800Sdab 53546800Sdab void 53646800Sdab auth_printsub(data, cnt, buf, buflen) 53746800Sdab unsigned char *data, *buf; 53846800Sdab int cnt, buflen; 53946800Sdab { 54046800Sdab Authenticator *ap; 54146800Sdab 54246800Sdab if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) 54346800Sdab (*ap->printsub)(data, cnt, buf, buflen); 54446800Sdab else 54546800Sdab auth_gen_printsub(data, cnt, buf, buflen); 54646800Sdab } 54746800Sdab 54846800Sdab void 54946800Sdab auth_gen_printsub(data, cnt, buf, buflen) 55046800Sdab unsigned char *data, *buf; 55146800Sdab int cnt, buflen; 55246800Sdab { 55346800Sdab register unsigned char *cp; 55446800Sdab unsigned char tbuf[16]; 55546800Sdab 55646800Sdab cnt -= 3; 55746800Sdab data += 3; 55846800Sdab buf[buflen-1] = '\0'; 55946800Sdab buf[buflen-2] = '*'; 56046800Sdab buflen -= 2; 56146800Sdab for (; cnt > 0; cnt--, data++) { 56246800Sdab sprintf((char *)tbuf, " %d", *data); 56346800Sdab for (cp = tbuf; *cp && buflen > 0; --buflen) 56446800Sdab *buf++ = *cp++; 56546800Sdab if (buflen <= 0) 56646800Sdab return; 56746800Sdab } 56846800Sdab *buf = '\0'; 56946800Sdab } 57046800Sdab #endif 571