From 3a1d6ae332ba8b4f24a1e9b0a7fbd37608581b80 Mon Sep 17 00:00:00 2001 From: Nathan Bryant Date: Thu, 8 Apr 1999 18:19:42 +0000 Subject: [PATCH] * citserver.c: improved is_public_client(), also if a public_client only supplies a numeric address, attempt to resolve it * locate_host.c: verify that the forward DNS matches the reverse --- citadel/ChangeLog | 5 ++++ citadel/citserver.c | 39 ++++++++++++++++++++++++++--- citadel/locate_host.c | 58 +++++++++++++++++++++++++++---------------- 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 70ab9130f..e6f516f0f 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,3 +1,8 @@ +1999-04-08 Nathan Bryant + * citserver.c: improved is_public_client(), also if a public_client only + supplies a numeric address, attempt to resolve it + * locate_host.c: verify that the forward DNS matches the reverse + Wed Apr 7 21:36:16 EDT 1999 Art Cancro * Implemented "access level required to create rooms" (client & server) diff --git a/citadel/citserver.c b/citadel/citserver.c index b27ec14d0..ed45f720b 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -15,6 +15,10 @@ #endif #include #include +#include +#include +#include +#include #include "citadel.h" #include "server.h" #include "sysdep_decls.h" @@ -246,6 +250,26 @@ void cmd_time(void) cprintf("%d %ld\n", OK, tv); } +/* + * Check whether two hostnames match. + * "Realname" should be an actual name of a client that is trying to connect; + * "testname" should be the value we are comparing it with. The idea is that we + * want to compare with both the abbreviated and fully-qualified versions of + * "testname;" some people define "localhost" as "localhost.foo.com," etc. + */ +static int hostnames_match(const char *realname, const char *testname) { + struct hostent *he; + + if (!strcasecmp(realname, testname)) + return 1; + + if ((he = gethostbyname(testname)) != NULL) + if (!strcasecmp(realname, he->h_name)) + return 1; + + return 0; + } + /* * check a hostname against the public_clients file */ @@ -254,8 +278,8 @@ int is_public_client(char *where) char buf[256]; FILE *fp; - if (!strcasecmp(where,"localhost")) return(1); - if (!strcasecmp(where,config.c_fqdn)) return(1); + if (hostnames_match(where,"localhost")) return(1); + if (hostnames_match(where,config.c_fqdn)) return(1); fp = fopen("public_clients","r"); if (fp == NULL) return(0); @@ -263,7 +287,7 @@ int is_public_client(char *where) while (fgets(buf,256,fp)!=NULL) { while (isspace((buf[strlen(buf)-1]))) buf[strlen(buf)-1] = 0; - if (!strcasecmp(buf,where)) { + if (hostnames_match(where,buf)) { fclose(fp); return(1); } @@ -284,6 +308,8 @@ void cmd_iden(char *argbuf) int rev_level; char desc[256]; char from_host[256]; + struct in_addr addr; + struct hostent *he; if (num_parms(argbuf)<4) { cprintf("%d usage error\n",ERROR); @@ -307,7 +333,12 @@ void cmd_iden(char *argbuf) if ((strlen(from_host)>0) && (is_public_client(CC->cs_host))) { - strncpy(CC->cs_host,from_host,24); + if (inet_aton(from_host, &addr) && + (he = gethostbyaddr((char*)&addr, sizeof addr, AF_INET)) != + NULL) + strncpy(CC->cs_host,he->h_name,24); + else + strncpy(CC->cs_host,from_host,24); CC->cs_host[24] = 0; } set_wtmpsupp_to_current_room(); diff --git a/citadel/locate_host.c b/citadel/locate_host.c index 85c4aa510..a18d6e99a 100644 --- a/citadel/locate_host.c +++ b/citadel/locate_host.c @@ -24,38 +24,52 @@ void locate_host(char *tbuf) { - struct sockaddr_in cs; - struct hostent * ch; - int len; + struct sockaddr_in cs; + struct hostent *ch, *ch2; + int len; char *i; - int a1,a2,a3,a4; - - len = sizeof(cs); - if (getpeername(CC->client_socket, (struct sockaddr *)&cs,&len) < 0){ - strcpy(tbuf,config.c_fqdn); - return; - } + int a1, a2, a3, a4; + len = sizeof(cs); + if (getpeername(CC->client_socket, (struct sockaddr *) &cs, &len) < 0) { + strcpy(tbuf, config.c_fqdn); + return; + } #ifdef HAVE_NONREENTRANT_NETDB - begin_critical_section(S_NETDB); + begin_critical_section(S_NETDB); #endif - - if((ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), - AF_INET)) == NULL) { + + if ((ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), + AF_INET)) == NULL) { + bad_dns: i = (char *) &cs.sin_addr; - a1 = ((*i++)&0xff); - a2 = ((*i++)&0xff); - a3 = ((*i++)&0xff); - a4 = ((*i++)&0xff); - sprintf(tbuf,"%d.%d.%d.%d",a1,a2,a3,a4); - return; + a1 = ((*i++) & 0xff); + a2 = ((*i++) & 0xff); + a3 = ((*i++) & 0xff); + a4 = ((*i++) & 0xff); + sprintf(tbuf, "%d.%d.%d.%d", a1, a2, a3, a4); + goto end; /* because we might need to end the critical + section */ + } + /* check if the forward DNS agrees; if not, they're spoofing */ + if ((ch2 = gethostbyname(ch->h_name)) == NULL) + goto bad_dns; + + /* check address for consistency */ + for (; *ch2->h_addr_list; ch2->h_addr_list++) + if (!memcmp(*ch2->h_addr_list, &cs.sin_addr, + sizeof cs.sin_addr)) { + strncpy(tbuf, ch->h_name, 24); + goto end; } + goto bad_dns; /* they were spoofing. report a numeric IP + address. */ - strncpy(tbuf,ch->h_name, 24); + end: #ifdef HAVE_NONREENTRANT_NETDB end_critical_section(S_NETDB); #endif tbuf[24] = 0; - } +} -- 2.39.2