* is_public_client() now caches the IP addresses of all hosts in
authorArt Cancro <ajc@citadel.org>
Fri, 11 Jul 2003 22:19:49 +0000 (22:19 +0000)
committerArt Cancro <ajc@citadel.org>
Fri, 11 Jul 2003 22:19:49 +0000 (22:19 +0000)
  the public_clients file, at server startup and whenever the file is
  modified.  This eliminates the need to make lots of calls to the
  resolver library every time.

citadel/ChangeLog
citadel/citserver.c
citadel/locate_host.c
citadel/locate_host.h
citadel/public_clients
citadel/server.h

index 12b34c5e290b7aa1f799e53e2d7ead74b09ba1aa..816ce65934e17c849d5b9804491fabd97815d556 100644 (file)
@@ -1,4 +1,10 @@
  $Log$
+ Revision 607.17  2003/07/11 22:19:49  ajc
+ * is_public_client() now caches the IP addresses of all hosts in
+   the public_clients file, at server startup and whenever the file is
+   modified.  This eliminates the need to make lots of calls to the
+   resolver library every time.
+
  Revision 607.16  2003/07/10 05:51:46  ajc
  * Added cs_addr field to struct CitContext -- holds a dotted quad string
    of the user's source IP (if applicable).  It's big enough to hold other
@@ -4836,3 +4842,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
+
index 69853a1673ceb9e5233605a1e992fd39c4fd85f1..dc082826301c9443fbc51d38c9ee5886d557f953 100644 (file)
@@ -15,6 +15,9 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
 
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
@@ -371,37 +374,6 @@ void cmd_time(void)
 #endif
 }
 
-/*
- * 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;
-       int retval = 0;
-
-       if (!strcasecmp(realname, testname)) {
-               return(1);
-       }
-
-#ifdef HAVE_NONREENTRANT_NETDB
-       begin_critical_section(S_NETDB);
-#endif
-
-       if ((he = gethostbyname(testname)) != NULL) {
-               if (!strcasecmp(realname, he->h_name)) {
-                       retval = 1;
-               }
-       }
-
-#ifdef HAVE_NONREENTRANT_NETDB
-       end_critical_section(S_NETDB);
-#endif
-
-       return retval;
-}
 
 /*
  * Check originating host against the public_clients file.  This determines
@@ -412,26 +384,68 @@ static int hostnames_match(const char *realname, const char *testname) {
 int is_public_client(void)
 {
        char buf[SIZ];
+       char addrbuf[SIZ];
        FILE *fp;
+       int i;
+       struct stat statbuf;
+       static time_t pc_timestamp = 0;
+       static char public_clients[SIZ];
+
+#define PUBLIC_CLIENTS "./public_clients"
+
+       /*
+        * Check the time stamp on the public_clients file.  If it's been
+        * updated since the last time we were here (or if this is the first
+        * time we've been through the loop), read its contents and learn
+        * the IP addresses of the listed hosts.
+        */
+       if (stat(PUBLIC_CLIENTS, &statbuf) != 0) {
+               /* No public_clients file exists, so bail out */
+               lprintf(5, "Warning: '%s' does not exist\n", PUBLIC_CLIENTS);
+               return(0);
+       }
+
+       if (statbuf.st_mtime > pc_timestamp) {
+               begin_critical_section(S_PUBLIC_CLIENTS);
+               lprintf(7, "Loading %s\n", PUBLIC_CLIENTS);
 
-       lprintf(9, "Checking whether %s is a local client\n",  CC->cs_host);
-       if (hostnames_match(CC->cs_host, "localhost")) return(1);
-       if (hostnames_match(CC->cs_host, config.c_fqdn)) return(1);
+               strcpy(public_clients, "");
+               /* FIXME add localhost */
+               /* FIXME add config.c_fqdn */
 
-       lprintf(9, "Checking whether %s is a public client\n", CC->cs_host);
-       fp = fopen("public_clients", "r");
-       if (fp == NULL) return(0);
+               fp = fopen("public_clients", "r");
+               if (fp != NULL) while (fgets(buf, sizeof buf, fp)!=NULL) {
+                       while (isspace((buf[strlen(buf)-1]))) {
+                               buf[strlen(buf)-1] = 0;
+                       }
+                       if (hostname_to_dotted_quad(addrbuf, buf) == 0) {
+                               if ((strlen(public_clients) +
+                                  strlen(addrbuf) + 2)
+                                  < sizeof(public_clients)) {
+                                       if (strlen(public_clients) != 0) {
+                                               strcat(public_clients, "|");
+                                       }
+                                       strcat(public_clients, addrbuf);
+                               }
+                       }
+               }
+               fclose(fp);
+               pc_timestamp = time(NULL);
+               end_critical_section(S_PUBLIC_CLIENTS);
+       }
 
-       while (fgets(buf, sizeof buf, fp)!=NULL) {
-               while (isspace((buf[strlen(buf)-1]))) 
-                       buf[strlen(buf)-1] = 0;
-               if (hostnames_match(CC->cs_host, buf)) {
-                       fclose(fp);
+       lprintf(9, "Checking whether %s is a local or public client\n",
+               CC->cs_addr);
+       for (i=0; i<num_parms(public_clients); ++i) {
+               extract(addrbuf, public_clients, i);
+               if (!strcasecmp(CC->cs_addr, addrbuf)) {
+                       lprintf(9, "... yes it is.\n");
                        return(1);
                }
        }
 
-       fclose(fp);
+       /* No hits.  This is not a public client. */
+       lprintf(9, "... no it isn't.\n");
        return(0);
 }
 
index 5ef13c8eb6df5f937bf76fef70e03ea0519c484e..31d65c9afdd1f5576f6edd5ddf318bef9fb4fad1 100644 (file)
@@ -145,3 +145,27 @@ int rbl_check(char *message_to_spammer) {
        }
        return(0);
 }
+
+/*
+ * Convert a host name to a dotted quad address. 
+ * Returns zero on success or nonzero on failure.
+ */
+int hostname_to_dotted_quad(char *addr, char *host) {
+       struct hostent *ch;
+       const char *i;
+       int a1, a2, a3, a4;
+
+       ch = gethostbyname(host);
+       if (ch == NULL) {
+               strcpy(addr, "0.0.0.0");
+               return(1);
+       }
+
+       i = (const char *) ch->h_addr_list[0];
+       a1 = ((*i++) & 0xff);
+       a2 = ((*i++) & 0xff);
+       a3 = ((*i++) & 0xff);
+       a4 = ((*i++) & 0xff);
+       sprintf(addr, "%d.%d.%d.%d", a1, a2, a3, a4);
+       return(0);
+}
index 2f74049b02c8455844fd044c067a6834d2319fdb..e2abe7967a08d56bd610bd5933373d8eacdc1363 100644 (file)
@@ -3,3 +3,4 @@ void locate_host(char *tbuf, size_t n,
                char *abuf, size_t na,
                const struct in_addr *addr);
 int rbl_check(char *message_to_spammer);
+int hostname_to_dotted_quad(char *addr, char *host);
index 504890c43d32dd95f4f80f0dcdef87c24fbdc76e..169709ff80f19a971c135435e12aaabfd3b68aed 100644 (file)
@@ -7,3 +7,8 @@
 
 localhost
 127.0.0.1
+uncensored.citadel.org
+web1
+seven
+splorph
+random.xand.com
index e25d5dda3c627561d539247a0d8b1bf29af3f741..cd2502e9d44ce51342b6f16566ec89d0994af8b7 100644 (file)
@@ -201,6 +201,7 @@ enum {
        S_NTTLIST,
        S_DIRECTORY,
        S_NETCONFIGS,
+       S_PUBLIC_CLIENTS,
        MAX_SEMAPHORES
 };