Sophie

Sophie

distrib > Mandriva > 2009.0 > i586 > by-pkgid > 35bce6cabfcfaec3d3060d600965d3a7 > files > 3

thttpd-2.25b-8mdv2009.0.src.rpm

diff -dru thttpd-2.25b/config.h thttpd-2.25b-access/config.h
--- thttpd-2.25b/config.h	Sun Nov 30 04:40:00 2003
+++ thttpd-2.25b-access/config.h	Wed Jul  7 20:16:24 2004
@@ -138,6 +138,17 @@
 */
 #define AUTH_FILE ".htpasswd"
 
+/* CONFIGURE: The file to use for restricting access on an ip basis. If
+** this is defined then thttpd checks for this file in the local
+** directory before every fetch. If the file exists then thttpd checks
+** whether the client's ip address is allowed to fetch this file, otherwise
+** the fetch is denied.
+**
+** If you undefine this then thttpd will not implement access checks
+** at all and will not check for access files, which saves a bit of CPU time.
+*/
+#define ACCESS_FILE ".htaccess"
+
 /* CONFIGURE: The default character set name to use with text MIME types.
 ** This gets substituted into the MIME types where they have a "%s".
 **
diff -dru thttpd-2.25b/libhttpd.c thttpd-2.25b-access/libhttpd.c
--- thttpd-2.25b/libhttpd.c	Thu Dec 25 20:06:05 2003
+++ thttpd-2.25b-access/libhttpd.c	Wed Jul  7 20:14:44 2004
@@ -136,6 +136,9 @@
 static int auth_check( httpd_conn* hc, char* dirname  );
 static int auth_check2( httpd_conn* hc, char* dirname  );
 #endif /* AUTH_FILE */
+#ifdef ACCESS_FILE
+static int access_check (httpd_conn* hc, char* dirname);
+#endif /* ACCESS_FILE */
 static void send_dirredirect( httpd_conn* hc );
 static int hexit( char c );
 static void strdecode( char* to, char* from );
@@ -876,6 +879,117 @@
     }
 #endif /* ERR_DIR */
 
+#ifdef ACCESS_FILE
+static int err_accessfile (httpd_conn* hc, char* accesspath, char* err, FILE* f)
+{
+  fclose(f);
+
+  syslog(LOG_ERR, "%.80s access file %.80s: invalid line: %s",
+    httpd_ntoa(&hc->client_addr), accesspath, err);
+
+  httpd_send_err(hc, 403, err403title, "", ERROR_FORM(err403form, 
+    "The requested URL '%.80s' is protected by an access file, but the "
+    "access file contains garbage.\n"), hc->encodedurl);
+
+  return -1;
+}
+
+/* Returns -1 == unauthorized, 0 == no access file, 1 = authorized. */
+static int access_check (httpd_conn* hc, char* dirname)
+{
+  static char* accesspath;
+  static size_t maxaccesspath = 0;
+  struct in_addr ipv4_addr, ipv4_mask = { 0xffffffff };
+  FILE* fp;
+  char line[500];
+  struct stat sb;
+  char *addr, *addr1, *addr2, *mask;
+  unsigned long l;
+
+  /* Construct access filename. */
+  httpd_realloc_str(&accesspath, &maxaccesspath, strlen(dirname) + 1 +
+    sizeof(ACCESS_FILE));
+
+  my_snprintf(accesspath, maxaccesspath, "%s/%s", dirname, ACCESS_FILE);
+
+  /* Does this directory have an access file? */
+  if (lstat(accesspath, &sb) < 0)
+    /* Nope, let the request go through. */
+    return 0;
+
+  /* Open the access file. */
+  fp = fopen(accesspath, "r");
+  if (!fp) {
+    /* The file exists but we can't open it? Disallow access. */
+    syslog(LOG_ERR, "%.80s access file %.80s could not be opened - %m",
+      httpd_ntoa(&hc->client_addr), accesspath);
+
+    httpd_send_err(hc, 403, err403title, "", ERROR_FORM(err403form, 
+      "The requested URL '%.80s' is protected by an access file, but "
+      "the access file cannot be opened.\n"), hc->encodedurl);
+
+    return -1;
+  }
+
+  /* Read it. */
+  while (fgets(line, sizeof(line), fp)) {
+    /* Nuke newline. */
+    l = strlen(line);
+    if (line[l - 1] == '\n') line[l - 1] = '\0';
+
+    addr1 = strrchr(line, ' ');
+    addr2 = strrchr(line, '\t');
+    if (addr1 > addr2) addr = addr1;
+    else addr = addr2;
+    if (!addr) return err_accessfile(hc, accesspath, line, fp);
+
+    mask = strchr(++addr, '/');
+    if (mask) {
+      *mask++ = '\0';
+      if (!*mask) return err_accessfile(hc, accesspath, line, fp);
+      if (!strchr(mask, '.')) {
+        l = atol(mask);
+        if ((l < 0) || (l > 32))
+          return err_accessfile(hc, accesspath, line, fp);
+        for (l = 32 - l; l > 0; --l) ipv4_mask.s_addr ^= 1 << (l - 1);
+        ipv4_mask.s_addr = htonl(ipv4_mask.s_addr);
+      }
+      else {
+        if (!inet_aton(mask, &ipv4_mask))
+          return err_accessfile(hc, accesspath, line, fp);
+      }
+    }
+
+    if (!inet_aton(addr, &ipv4_addr))
+      return err_accessfile(hc, accesspath, line, fp);
+
+    /* Does client addr match this rule? */
+    if ((hc->client_addr.sa_in.sin_addr.s_addr & ipv4_mask.s_addr) ==
+      (ipv4_addr.s_addr & ipv4_mask.s_addr)) {
+      /* Yes. */
+      switch (line[0]) {
+        case 'd':
+        case 'D':
+	  break;
+
+        case 'a':
+        case 'A':
+          fclose(fp);
+          return 1;
+
+        default:
+          return err_accessfile(hc, accesspath, line, fp);
+      }
+    }
+  }
+
+  httpd_send_err(hc, 403, err403title, "", ERROR_FORM(err403form, 
+    "The requested URL '%.80s' is protected by an address restriction."),
+    hc->encodedurl);
+  fclose(fp);
+  return -1;
+}
+#endif /* ACCESS_FILE */
 
 #ifdef AUTH_FILE
 
@@ -1030,7 +1144,7 @@
     (void) my_snprintf( authpath, maxauthpath, "%s/%s", dirname, AUTH_FILE );
 
     /* Does this directory have an auth file? */
-    if ( stat( authpath, &sb ) < 0 )
+    if ( lstat( authpath, &sb ) < 0 )
 	/* Nope, let the request go through. */
 	return 0;
 
@@ -3683,6 +3797,11 @@
 		hc->encodedurl );
 	    return -1;
 	    }
+#ifdef ACCESS_FILE
+	/* Check access file for this directory. */
+	if ( access_check( hc, hc->expnfilename ) == -1 )
+	    return -1;
+#endif /* ACCESS_FILE */
 #ifdef AUTH_FILE
 	/* Check authorization for this directory. */
 	if ( auth_check( hc, hc->expnfilename ) == -1 )
@@ -3732,6 +3851,50 @@
 	    return -1;
 	    }
 	}
+
+#ifdef ACCESS_FILE
+    /* Check access for this directory. */
+    httpd_realloc_str( &dirname, &maxdirname, expnlen );
+    (void) strcpy( dirname, hc->expnfilename );
+    cp = strrchr( dirname, '/' );
+    if ( cp == (char*) 0 )
+	(void) strcpy( dirname, "." );
+    else
+	*cp = '\0';
+    if ( access_check( hc, dirname ) == -1 )
+	return -1;
+
+    /* Check if the filename is the ACCESS_FILE itself - that's verboten. */
+    if ( expnlen == sizeof(ACCESS_FILE) - 1 )
+	{
+	if ( strcmp( hc->expnfilename, ACCESS_FILE ) == 0 )
+	    {
+	    syslog(
+		LOG_NOTICE,
+		"%.80s URL \"%.80s\" tried to retrieve an access file",
+		httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+	    httpd_send_err(
+		hc, 403, err403title, "",
+		ERROR_FORM( err403form, "The requested URL '%.80s' is an access file, retrieving it is not permitted.\n" ),
+		hc->encodedurl );
+	    return -1;
+	    }
+	}
+    else if ( expnlen >= sizeof(ACCESS_FILE) &&
+	      strcmp( &(hc->expnfilename[expnlen - sizeof(ACCESS_FILE) + 1]), ACCESS_FILE ) == 0 &&
+	      hc->expnfilename[expnlen - sizeof(ACCESS_FILE)] == '/' )
+	{
+	syslog(
+	    LOG_NOTICE,
+	    "%.80s URL \"%.80s\" tried to retrieve an access file",
+	    httpd_ntoa( &hc->client_addr ), hc->encodedurl );
+	httpd_send_err(
+	    hc, 403, err403title, "",
+	    ERROR_FORM( err403form, "The requested URL '%.80s' is an access file, retrieving it is not permitted.\n" ),
+	    hc->encodedurl );
+	return -1;
+	}
+#endif /* ACCESS_FILE */
 
 #ifdef AUTH_FILE
     /* Check authorization for this directory. */
diff -dru thttpd-2.25b/thttpd.8 thttpd-2.25b-access/thttpd.8
--- thttpd-2.25b/thttpd.8	Sat Nov 15 00:43:51 2003
+++ thttpd-2.25b-access/thttpd.8	Wed Jul  7 20:14:44 2004
@@ -274,6 +274,42 @@
 modify .htpasswd files.
 .PP
 Relevant config.h option: AUTH_FILE
+.SH "ACCESS RESTRICTION"
+.PP
+Access restriction is available as an option at compile time.
+If enabled, it uses an access file in the directory to be protected,
+called .htaccess by default.
+This file consists of a rule and a host address or a network range per
+line.
+Valid rules are:
+.TP
+.B allow from
+The following host address or network range is allowed to access the requested
+directory and its files.
+.TP
+.B deny from
+The following host address or network range is not allowed to access the
+requested directory and its files.
+.PP
+The protection does not carry over to subdirectories.
+There are three ways to specify a valid host address or network range:
+.TP
+.B IPv4 host address
+eg. 10.2.3.4
+.TP
+.B IPv4 network with subnet mask
+eg. 10.0.0.0/255.255.0.0
+.TP
+.B IPv4 network using CIDR notation
+eg. 10.0.0.0/16
+.PP
+Note that rules are processed in the same order as they are listed in the
+access file and that the first rule which matches the client's address is
+applied (there is no order clause).
+So if there is no allow from 0.0.0.0/0 at the end of the file the default
+action is to deny access.
+.PP
+Relevant config.h option: ACCESS_FILE
 .SH "THROTTLING"
 .PP
 The throttle file lets you set maximum byte rates on URLs or URL groups.