* citserver.c: improved is_public_client(), also if a public_client only
authorNathan Bryant <loanshark@uncensored.citadel.org>
Thu, 8 Apr 1999 18:19:42 +0000 (18:19 +0000)
committerNathan Bryant <loanshark@uncensored.citadel.org>
Thu, 8 Apr 1999 18:19:42 +0000 (18:19 +0000)
          supplies a numeric address, attempt to resolve it
        * locate_host.c: verify that the forward DNS matches the reverse

citadel/ChangeLog
citadel/citserver.c
citadel/locate_host.c

index 70ab9130fc698f5e054a826cbcba605b0f1c1f11..e6f516f0fdf5856f2059242f66be70dc25d48d08 100644 (file)
@@ -1,3 +1,8 @@
+1999-04-08 Nathan Bryant <bryant@cs.usm.maine.edu>
+       * 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 <ajc@uncnsrd.mt-kisco.ny.us>
        * Implemented "access level required to create rooms" (client & server)
 
index b27ec14d0ba33c211ba0a5ddcb78ff5d19dc5f16..ed45f720b951e79dd9f204c3eff2cb83aae26ab0 100644 (file)
 #endif
 #include <syslog.h>
 #include <dlfcn.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #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();
index 85c4aa51031587b1deb5a10625e4ac56f4b25eec..a18d6e99a39c406659b194c81b2458120aa04dac 100644 (file)
 
 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;
-       }
+}