1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

finished authentication, implemented port/dir protection

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@60 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2007-02-10 05:31:17 +00:00
parent 30a1970bb2
commit 36ac01f46a
19 changed files with 351 additions and 255 deletions

View File

@ -8,5 +8,7 @@ Changes since 1.0.0
axhttpd Changes axhttpd Changes
* Header file issue fixed (in mime_types.c) * Header file issue fixed (in mime_types.c)
* chroot() now used for better security * chroot() now used for better security
* Authentication implemented * Basic authentication implemented (with .htpasswd)
* * HTTP Port protection implemented (with .htaccess)
* Directory access protection implemented (with .htaccess)

View File

@ -56,7 +56,7 @@ CONFIG_HTTP_WEBROOT="../www"
CONFIG_HTTP_PORT=80 CONFIG_HTTP_PORT=80
CONFIG_HTTP_TIMEOUT=5 CONFIG_HTTP_TIMEOUT=5
# CONFIG_HTTP_HAS_CGI is not set # CONFIG_HTTP_HAS_CGI is not set
CONFIG_HTTP_CGI_EXTENSION="" CONFIG_HTTP_CGI_EXTENSIONS=""
# CONFIG_HTTP_DIRECTORIES is not set # CONFIG_HTTP_DIRECTORIES is not set
# CONFIG_HTTP_PERM_CHECK is not set # CONFIG_HTTP_PERM_CHECK is not set
# CONFIG_HTTP_HAS_IPV6 is not set # CONFIG_HTTP_HAS_IPV6 is not set

View File

@ -59,7 +59,7 @@ CONFIG_HTTP_WEBROOT="www"
CONFIG_HTTP_PORT=80 CONFIG_HTTP_PORT=80
CONFIG_HTTP_TIMEOUT=5 CONFIG_HTTP_TIMEOUT=5
# CONFIG_HTTP_HAS_CGI is not set # CONFIG_HTTP_HAS_CGI is not set
CONFIG_HTTP_CGI_EXTENSION="" CONFIG_HTTP_CGI_EXTENSIONS=""
CONFIG_HTTP_DIRECTORIES=y CONFIG_HTTP_DIRECTORIES=y
# CONFIG_HTTP_PERM_CHECK is not set # CONFIG_HTTP_PERM_CHECK is not set
# CONFIG_HTTP_HAS_IPV6 is not set # CONFIG_HTTP_HAS_IPV6 is not set

View File

@ -10,7 +10,7 @@ config CONFIG_HTTP_STATIC_BUILD
bool "Static Build" bool "Static Build"
default n default n
help help
Select y if you want axhttp to be a static build (i.e. don't use the Select y if you want axhttpd to be a static build (i.e. don't use the
axtls shared library or dll). axtls shared library or dll).
config CONFIG_HTTP_PORT config CONFIG_HTTP_PORT
@ -59,12 +59,14 @@ config CONFIG_HTTP_HAS_CGI
help help
Enable the CGI capability. Enable the CGI capability.
config CONFIG_HTTP_CGI_EXTENSION config CONFIG_HTTP_CGI_EXTENSIONS
string "CGI File Extension" string "CGI File Extension(s)"
default ".php" default ".php,.sh"
depends on CONFIG_HTTP_HAS_CGI depends on CONFIG_HTTP_HAS_CGI
help help
Tell axhhtp what file extension is used for CGI Tell axhhtpd what file extension(s) are used for CGI.
This is a comma separated list.
config CONFIG_HTTP_DIRECTORIES config CONFIG_HTTP_DIRECTORIES
bool "Enable Directory Listing" bool "Enable Directory Listing"

View File

@ -25,8 +25,10 @@ ifndef CONFIG_PLATFORM_WIN32
ifdef CONFIG_PLATFORM_CYGWIN ifdef CONFIG_PLATFORM_CYGWIN
TARGET=../$(STAGE)/axhttpd.exe TARGET=../$(STAGE)/axhttpd.exe
TARGET2=../$(STAGE)/htpasswd.exe
else else
TARGET=../$(STAGE)/axhttpd TARGET=../$(STAGE)/axhttpd
TARGET2=../$(STAGE)/htpasswd
endif endif
ifdef CONFIG_HTTP_STATIC_BUILD ifdef CONFIG_HTTP_STATIC_BUILD
@ -39,6 +41,7 @@ CFLAGS += -I../ssl
else # win32 build else # win32 build
TARGET=../$(STAGE)/axhttpd.exe TARGET=../$(STAGE)/axhttpd.exe
TARGET2=../$(STAGE)/htpasswd.exe
ifdef CONFIG_HTTP_STATIC_BUILD ifdef CONFIG_HTTP_STATIC_BUILD
LIBS=../$(STAGE)/axtls.static.lib ..\\config\\axtls.res LIBS=../$(STAGE)/axtls.static.lib ..\\config\\axtls.res
@ -51,7 +54,11 @@ ifndef CONFIG_AXHTTPD
web_server: web_server:
else else
web_server : $(TARGET) web_server :: $(TARGET)
ifdef CONFIG_HTTP_HAS_AUTHORIZATION
web_server :: $(TARGET2)
endif
OBJ= \ OBJ= \
axhttpd.o \ axhttpd.o \
@ -69,14 +76,24 @@ ifndef CONFIG_PLATFORM_SOLARIS
strip --remove-section=.comment $(TARGET) strip --remove-section=.comment $(TARGET)
endif endif
endif endif
$(TARGET2): htpasswd.o ../$(STAGE)/libaxtls.a
$(LD) $(LDFLAGS) -o $@ htpasswd.o $(LIBS)
else # Win32 else # Win32
OBJ:=$(OBJ:.o=.obj) OBJ:=$(OBJ:.o=.obj)
%.obj : %.c %.obj : %.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
htpasswd.obj : htpasswd.c
$(CC) $(CFLAGS) $<
$(TARGET): $(OBJ) $(TARGET): $(OBJ)
$(LD) $(LDFLAGS) $(LIBS) /out:$@ $(OBJ) $(LD) $(LDFLAGS) $(LIBS) /out:$@ $(OBJ)
$(TARGET2): htpasswd.obj
$(LD) $(LDFLAGS) $(LIBS) /out:$@ $(OBJ)
endif endif
endif # CONFIG_AXHTTPD endif # CONFIG_AXHTTPD

View File

@ -4,3 +4,42 @@ axhttpd is a small embedded web server using the axTLS library.
It is based originally on the web server written by Doug Currie which is at: It is based originally on the web server written by Doug Currie which is at:
http://www.hcsw.org/awhttpd. http://www.hcsw.org/awhttpd.
Basic Authentication
====================
Basic Authentication uses a password file called ".htpasswd", in the
directory to be protected. This file is formatted as the familiar
colon-separated username/encrypted-password pair, records delimited by
newlines. The protection does not carry over to subdirectories. The
utility program htpasswd is included to help manually edit .htpasswd files.
The encryption of this password uses a proprietary algorithm due to the
dependency of many crypt libraries on DES.
An example is in /test_dir/prot (username 'abcd', password is '1234').
Note: This is an mconf configuration option.
HTTP Port Protection
====================
Directories/files can be accessed using the 'http' or 'https' uri prefix. If
normal http access for a directory needs to be disabled, then put
"SSLRequireSSL" into a '.htaccess' file in the directory to be protected.
An example is in /test_dir/prot.
CGI
===
chroot() is now used for added security. However this has the impact of
removing the regular filesystem, so any CGI applications no longer have the
usual access.
So any executables and libraries need to be copied into webroot (under /bin
and /lib).
Failure to do so will result in mystical blank screens (and probably hundreds
of axhttpd instances being created...).

View File

@ -25,9 +25,7 @@
#define HAVE_IPV6 #define HAVE_IPV6
#endif #endif
#define MAXFILEPATH 1024 #define MAXREQUESTLENGTH 256
#define MAXIPLEN 45
#define MAXREQUESTLENGTH 1024
#define MAXCGIARGS 100 #define MAXCGIARGS 100
#define BLOCKSIZE 4096 #define BLOCKSIZE 4096
@ -40,9 +38,12 @@
#define STATE_WANT_TO_SEND_FILE 4 #define STATE_WANT_TO_SEND_FILE 4
#define STATE_DOING_DIR 5 #define STATE_DOING_DIR 5
#define TYPE_GET 0 enum
#define TYPE_HEAD 1 {
#define TYPE_POST 2 TYPE_GET,
TYPE_HEAD,
TYPE_POST
};
struct connstruct struct connstruct
{ {
@ -62,21 +63,21 @@ struct connstruct
#endif #endif
time_t timeout; time_t timeout;
char ip[MAXIPLEN];
char actualfile[MAXREQUESTLENGTH]; char actualfile[MAXREQUESTLENGTH];
char filereq[MAXREQUESTLENGTH]; char filereq[MAXREQUESTLENGTH];
char dirname[MAXREQUESTLENGTH];
char virtualhostreq[MAXREQUESTLENGTH];
int numbytes;
char databuf[BLOCKSIZE];
uint8_t is_ssl;
uint8_t close_when_done;
uint8_t modified_since;
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
char cgiargs[MAXREQUESTLENGTH]; char cgiargs[MAXREQUESTLENGTH];
char cgiscriptinfo[MAXREQUESTLENGTH]; char cgiscriptinfo[MAXREQUESTLENGTH];
char cgipathinfo[MAXREQUESTLENGTH]; char cgipathinfo[MAXREQUESTLENGTH];
#endif #endif
char virtualhostreq[MAXREQUESTLENGTH];
int numbytes;
char databuf[BLOCKSIZE];
uint8_t is_ssl;
uint8_t close_when_done;
uint8_t modified_since;
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION) #if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
char authorization[MAXREQUESTLENGTH]; char authorization[MAXREQUESTLENGTH];
#endif #endif

View File

@ -38,7 +38,7 @@ static void procpermcheck(const char *pathtocheck);
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
struct cgiextstruct *cgiexts; struct cgiextstruct *cgiexts;
static void addcgiext(char *tp); static void addcgiext(const char *tp);
#if !defined(WIN32) #if !defined(WIN32)
static void reaper(int sigtype) static void reaper(int sigtype)
@ -55,6 +55,7 @@ static void sigint_cleanup(int sig)
struct connstruct *tp; struct connstruct *tp;
int i; int i;
while (servers != NULL) while (servers != NULL)
{ {
if (servers->is_ssl) if (servers->is_ssl)
@ -75,6 +76,17 @@ static void sigint_cleanup(int sig)
freeconns = tp; freeconns = tp;
} }
#if defined(CONFIG_HTTP_HAS_CGI)
while (cgiexts)
{
struct cgiextstruct *cp = cgiexts->next;
if (cp == NULL) /* last entry */
free(cgiexts->ext);
free(cgiexts);
cgiexts = cp;
}
#endif
exit(0); exit(0);
} }
@ -159,7 +171,7 @@ int main(int argc, char *argv[])
procpermcheck(webroot); procpermcheck(webroot);
#endif #endif
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
addcgiext(CONFIG_HTTP_CGI_EXTENSION); addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
#endif #endif
#if defined(CONFIG_HTTP_VERBOSE) #if defined(CONFIG_HTTP_VERBOSE)
printf("axhttpd (%s): listening on ports %d (http) and %d (https)\n", printf("axhttpd (%s): listening on ports %d (http) and %d (https)\n",
@ -413,13 +425,21 @@ static void procpermcheck(const char *pathtocheck)
#endif /* CONFIG_HTTP_PERM_CHECK */ #endif /* CONFIG_HTTP_PERM_CHECK */
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
static void addcgiext(char *tp) static void addcgiext(const char *cgi_exts)
{ {
struct cgiextstruct *ex = (struct cgiextstruct *) char *cp = strdup(cgi_exts);
malloc(sizeof(struct cgiextstruct));
ex->ext = strdup(tp); /* extenstions are comma separated */
ex->next = cgiexts; do
cgiexts = ex; {
struct cgiextstruct *ex = (struct cgiextstruct *)
malloc(sizeof(struct cgiextstruct));
ex->ext = cp;
ex->next = cgiexts;
cgiexts = ex;
if ((cp = strchr(cp, ',')) != NULL)
*cp++ = 0;
} while (cp != NULL);
} }
#endif #endif
@ -557,10 +577,8 @@ static void addconnection(int sd, char *ip, int is_ssl)
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
*(tp->cgiargs) = '\0'; *(tp->cgiargs) = '\0';
#endif #endif
*(tp->virtualhostreq) = '\0';
tp->state = STATE_WANT_TO_READ_HEAD; tp->state = STATE_WANT_TO_READ_HEAD;
tp->reqtype = TYPE_GET; tp->reqtype = TYPE_GET;
my_strncpy(tp->ip, ip, MAXIPLEN);
tp->close_when_done = 0; tp->close_when_done = 0;
tp->modified_since = 0; tp->modified_since = 0;
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT; tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;

View File

@ -1,117 +0,0 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "axhttp.h"
void addconnection(int sd, char *ip, int is_ssl)
{
struct connstruct *tp;
// Get ourselves a connstruct
if (freeconns == NULL)
tp = (struct connstruct *)malloc(sizeof(struct connstruct));
else
{
tp = freeconns;
freeconns = tp->next;
}
// Attach it to the used list
tp->next = usedconns;
usedconns = tp;
tp->networkdesc = sd;
if (is_ssl)
ssl_server_new(servers->ssl_ctx, sd);
tp->is_ssl = is_ssl;
tp->filedesc = -1;
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
tp->dirp = NULL;
#endif
*(tp->actualfile) = '\0';
*(tp->filereq) = '\0';
#if defined(CONFIG_HTTP_HAS_CGI)
*(tp->cgiargs) = '\0';
#endif
*(tp->virtualhostreq) = '\0';
tp->state = STATE_WANT_TO_READ_HEAD;
tp->reqtype = TYPE_GET;
my_strncpy(tp->ip, ip, MAXIPLEN);
tp->close_when_done = 0;
tp->modified_since = 0;
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
}
void removeconnection(struct connstruct *cn)
{
struct connstruct *tp;
int shouldret = 0;
tp = usedconns;
if (tp == NULL || cn == NULL)
shouldret = 1;
else if (tp == cn)
usedconns = tp->next;
else
{
while (tp != NULL)
{
if (tp->next == cn)
{
tp->next = (tp->next)->next;
shouldret = 0;
break;
}
tp = tp->next;
shouldret = 1;
}
}
if (shouldret)
return;
// If we did, add it to the free list
cn->next = freeconns;
freeconns = cn;
// Close it all down
if (cn->networkdesc != -1)
{
if (cn->is_ssl)
ssl_free(ssl_find(servers->ssl_ctx, cn->networkdesc));
SOCKET_CLOSE(cn->networkdesc);
}
if (cn->filedesc != -1)
close(cn->filedesc);
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
if (cn->dirp != NULL)
#ifdef WIN32
FindClose(cn->dirp);
#else
closedir(cn->dirp);
#endif
#endif
}

98
httpd/htpasswd.c Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright(C) 2007 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ssl.h"
int tfd;
void base64_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen)
{
static const char b64str[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (inlen && outlen)
{
*out++ = b64str[(in[0] >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64str[((in[0] << 4)
+ (--inlen ? in[1] >> 4 : 0)) & 0x3f];
if (!--outlen)
break;
*out++ = (inlen
? b64str[((in[1] << 2)
+ (--inlen ? in[2] >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64str[in[2] & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
if (outlen)
*out = '\0';
}
static void usage(void)
{
fprintf(stderr,"Usage: htpasswd username\n");
exit(1);
}
int main(int argc, char *argv[])
{
char* pw;
uint8_t md5_salt[MD5_SIZE], md5_pass[MD5_SIZE];
char b64_salt[MD5_SIZE+10], b64_pass[MD5_SIZE+10];
MD5_CTX ctx;
if (argc != 2)
usage();
pw = strdup(getpass("New password:"));
if (strcmp(pw, getpass("Re-type new password:")) != 0)
{
fprintf(stderr, "They don't match, sorry.\n" );
exit(1);
}
RNG_initialize(pw, sizeof(pw));
get_random(MD5_SIZE, md5_salt);
RNG_terminate();
base64_encode(md5_salt, MD5_SIZE, b64_salt, sizeof(b64_salt));
MD5Init(&ctx);
MD5Update(&ctx, md5_salt, MD5_SIZE);
MD5Update(&ctx, pw, strlen(pw));
MD5Final(&ctx, md5_pass);
base64_encode(md5_pass, MD5_SIZE, b64_pass, sizeof(b64_pass));
printf("Add the following to your '.htpasswd' file\n");
printf("%s:%s$%s\n", argv[1], b64_salt, b64_pass);
return 0;
}

View File

@ -35,6 +35,7 @@ static void urldecode(char *buf);
static void buildactualfile(struct connstruct *cn); static void buildactualfile(struct connstruct *cn);
static int sanitizefile(const char *buf); static int sanitizefile(const char *buf);
static int sanitizehost(char *buf); static int sanitizehost(char *buf);
static int htaccess_check(struct connstruct *cn);
#if defined(CONFIG_HTTP_DIRECTORIES) #if defined(CONFIG_HTTP_DIRECTORIES)
static void urlencode(const uint8_t *s, uint8_t *t); static void urlencode(const uint8_t *s, uint8_t *t);
@ -63,11 +64,10 @@ static int procheadelem(struct connstruct *cn, char *buf)
*delim = 0; *delim = 0;
value = delim+1; value = delim+1;
printf("BUF %s - value %s\n", buf, value);
if (strcmp(buf, "GET") == 0 || /* printf("name: %s, value: %s\n", buf, value); */
strcmp(buf, "HEAD") == 0 || if (strcmp(buf, "GET") == 0 || strcmp(buf, "HEAD") == 0 ||
strcmp(buf, "POST") == 0) strcmp(buf, "POST") == 0)
{ {
if (buf[0] == 'H') if (buf[0] == 'H')
cn->reqtype = TYPE_HEAD; cn->reqtype = TYPE_HEAD;
@ -76,13 +76,13 @@ static int procheadelem(struct connstruct *cn, char *buf)
if ((delim = strchr(value, ' ')) == NULL) /* expect HTTP type */ if ((delim = strchr(value, ' ')) == NULL) /* expect HTTP type */
return 0; return 0;
*delim = 0;
*delim = 0;
urldecode(value); urldecode(value);
if (sanitizefile(value) == 0) if (sanitizefile(value) == 0)
{ {
send_error(cn, 404); send_error(cn, 403);
return 0; return 0;
} }
@ -94,7 +94,6 @@ static int procheadelem(struct connstruct *cn, char *buf)
my_strncpy(cn->cgiargs, value+1, MAXREQUESTLENGTH); my_strncpy(cn->cgiargs, value+1, MAXREQUESTLENGTH);
} }
#endif #endif
} }
else if (strcmp(buf, "Host:") == 0) else if (strcmp(buf, "Host:") == 0)
{ {
@ -117,11 +116,14 @@ static int procheadelem(struct connstruct *cn, char *buf)
} }
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION #ifdef CONFIG_HTTP_HAS_AUTHORIZATION
else if (strcmp(buf, "Authorization:") == 0 && else if (strcmp(buf, "Authorization:") == 0 &&
strncmp(value, "Basic ", 6) == 0) strncmp(value, "Basic ", 6) == 0)
{ {
int size;
if (base64_decode(&value[6], strlen(&value[6]), if (base64_decode(&value[6], strlen(&value[6]),
cn->authorization, NULL)) cn->authorization, &size))
cn->authorization[0] = 0; /* error */ cn->authorization[0] = 0; /* error */
else
cn->authorization[size] = 0;
} }
#endif #endif
@ -319,36 +321,42 @@ void procsendhead(struct connstruct *cn)
time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT; time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
char date[32]; char date[32];
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION /* are we trying to access a file over the HTTP connection instead of a
if (auth_check(cn)) * HTTPS connection? Or is this directory disabled? */
if (htaccess_check(cn))
{ {
send_error(cn, 403);
return;
}
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
if (auth_check(cn)) /* see if there is a '.htpasswd' file */
{
#ifdef CONFIG_HTTP_VERBOSE
printf("axhttpd: access to %s denied\n", cn->actualfile); TTY_FLUSH();
#endif
removeconnection(cn); removeconnection(cn);
return; return;
} }
#endif #endif
strcpy(date, ctime(&now)); if (stat(cn->actualfile, &stbuf) == -1)
if (stat(cn->actualfile, &stbuf) == -1)
{ {
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
if (trycgi_withpathinfo(cn) == 0) if (stat(cn->actualfile, &stbuf) == -1 && trycgi_withpathinfo(cn) == 0)
{ {
/* We Try To Find A CGI */ /* We Try To Find A CGI */
proccgi(cn, 1); proccgi(cn, 1);
return; return;
} }
#endif #endif
send_error(cn, 404);
return;
} }
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
if (iscgi(cn->actualfile)) if (iscgi(cn->actualfile))
{ {
#ifndef WIN32 #ifndef WIN32
/* Set up CGI script */ /* An executable file? */
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{ {
send_error(cn, 404); send_error(cn, 404);
@ -396,6 +404,8 @@ void procsendhead(struct connstruct *cn)
#endif #endif
} }
strcpy(date, ctime(&now));
if (cn->modified_since) if (cn->modified_since)
{ {
/* file has already been read before */ /* file has already been read before */
@ -407,20 +417,6 @@ void procsendhead(struct connstruct *cn)
return; return;
} }
#ifdef CONFIG_HTTP_VERBOSE
printf("axhttpd: %s send %s\n",
cn->is_ssl ? "https" : "http", cn->actualfile);
TTY_FLUSH();
#endif
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\n"
"Content-Type: %s\nContent-Length: %ld\n"
"Date: %sLast-Modified: %s\n", VERSION,
getmimetype(cn->actualfile), (long) stbuf.st_size,
date, ctime(&(stbuf.st_mtime))); /* ctime() has a \n on the end */
special_write(cn, buf, strlen(buf));
if (cn->reqtype == TYPE_HEAD) if (cn->reqtype == TYPE_HEAD)
{ {
removeconnection(cn); removeconnection(cn);
@ -437,10 +433,23 @@ void procsendhead(struct connstruct *cn)
if (cn->filedesc == -1) if (cn->filedesc == -1)
{ {
send_error(cn, 404); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\n"
"Content-Type: %s\nContent-Length: %ld\n"
"Date: %sLast-Modified: %s\n", VERSION,
getmimetype(cn->actualfile), (long) stbuf.st_size,
date, ctime(&(stbuf.st_mtime))); /* ctime() has a \n on the end */
special_write(cn, buf, strlen(buf));
#ifdef CONFIG_HTTP_VERBOSE
printf("axhttpd: %s send %s\n",
cn->is_ssl ? "https" : "http", cn->actualfile);
TTY_FLUSH();
#endif
#ifdef WIN32 #ifdef WIN32
for (;;) for (;;)
{ {
@ -659,10 +668,8 @@ static int trycgi_withpathinfo(struct connstruct *cn)
/* We've found our CGI file! */ /* We've found our CGI file! */
my_strncpy(cn->actualfile, tpfile, MAXREQUESTLENGTH); my_strncpy(cn->actualfile, tpfile, MAXREQUESTLENGTH);
my_strncpy(cn->cgiscriptinfo, fr_str, MAXREQUESTLENGTH); my_strncpy(cn->cgiscriptinfo, fr_str, MAXREQUESTLENGTH);
offset = (fr_rs[i] + strlen(fr_rs[i])) - fr_str; offset = (fr_rs[i] + strlen(fr_rs[i])) - fr_str;
my_strncpy(cn->cgipathinfo, cn->filereq+offset, MAXREQUESTLENGTH); my_strncpy(cn->cgipathinfo, cn->filereq+offset, MAXREQUESTLENGTH);
return 0; return 0;
} }
@ -678,11 +685,10 @@ static int trycgi_withpathinfo(struct connstruct *cn)
static int iscgi(const char *fn) static int iscgi(const char *fn)
{ {
struct cgiextstruct *tp; struct cgiextstruct *tp = cgiexts;
int fnlen, extlen; int fnlen, extlen;
fnlen = strlen(fn); fnlen = strlen(fn);
tp = cgiexts;
while (tp != NULL) while (tp != NULL)
{ {
@ -784,6 +790,7 @@ static int hexit(char c)
static void buildactualfile(struct connstruct *cn) static void buildactualfile(struct connstruct *cn)
{ {
char *cp;
snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s", cn->filereq); snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s", cn->filereq);
/* Add directory slash if not there */ /* Add directory slash if not there */
@ -791,12 +798,23 @@ static void buildactualfile(struct connstruct *cn)
cn->actualfile[strlen(cn->actualfile)-1] != '/') cn->actualfile[strlen(cn->actualfile)-1] != '/')
strcat(cn->actualfile, "/"); strcat(cn->actualfile, "/");
/* work out the directory name */
strncpy(cn->dirname, cn->actualfile, MAXREQUESTLENGTH);
if ((cp = strrchr(cn->dirname, '/')) == NULL)
cn->dirname[0] = 0;
else
*cp = 0;
#ifdef WIN32 #ifdef WIN32
/* convert all the forward slashes to back slashes */ /* convert all the forward slashes to back slashes */
{ {
char *t = cn->actualfile; char *t = cn->actualfile;
while ((t = strchr(t, '/'))) while ((t = strchr(t, '/')))
*t++ = '\\'; *t++ = '\\';
t = cn->dirname;
while ((t = strchr(t, '/')))
*t++ = '\\';
} }
#endif #endif
} }
@ -844,9 +862,14 @@ static int sanitizehost(char *buf)
return 1; return 1;
} }
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION static FILE * exist_check(struct connstruct *cn, const char *check_file)
#define AUTH_FILE ".htpasswd" {
char pathname[MAXREQUESTLENGTH];
snprintf(pathname, MAXREQUESTLENGTH, "%s/%s", cn->dirname, check_file);
return fopen(pathname, "r");
}
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
static void send_authenticate(struct connstruct *cn, const char *realm) static void send_authenticate(struct connstruct *cn, const char *realm)
{ {
char buf[1024]; char buf[1024];
@ -857,30 +880,29 @@ static void send_authenticate(struct connstruct *cn, const char *realm)
special_write(cn, buf, strlen(buf)); special_write(cn, buf, strlen(buf));
} }
static int check_digest(char *b64_file_passwd, const char *msg_passwd) static int check_digest(char *salt, const char *msg_passwd)
{ {
uint8_t real_salt[MAXREQUESTLENGTH]; uint8_t b256_salt[MAXREQUESTLENGTH];
uint8_t real_passwd[MAXREQUESTLENGTH]; uint8_t real_passwd[MD5_SIZE];
int real_passwd_size, real_salt_size; int salt_size;
char *b64_pwd; char *b64_passwd;
uint8_t md5_result[MD5_SIZE]; uint8_t md5_result[MD5_SIZE];
MD5_CTX ctx; MD5_CTX ctx;
/* retrieve the salt */ /* retrieve the salt */
if ((b64_pwd = strchr(b64_file_passwd, '$')) == NULL) if ((b64_passwd = strchr(salt, '$')) == NULL)
return -1; return -1;
*b64_pwd++ = 0; *b64_passwd++ = 0;
if (base64_decode(b64_file_passwd, strlen(b64_file_passwd), if (base64_decode(salt, strlen(salt), b256_salt, &salt_size))
real_salt, &real_salt_size))
return -1; return -1;
if (base64_decode(b64_pwd, strlen(b64_pwd), real_passwd, &real_passwd_size)) if (base64_decode(b64_passwd, strlen(b64_passwd), real_passwd, NULL))
return -1; return -1;
/* very simple MD5 crypt algorithm, but then the salt we use is large */ /* very simple MD5 crypt algorithm, but then the salt we use is large */
MD5Init(&ctx); MD5Init(&ctx);
MD5Update(&ctx, real_salt, real_salt_size); /* process the salt */ MD5Update(&ctx, b256_salt, salt_size); /* process the salt */
MD5Update(&ctx, msg_passwd, strlen(msg_passwd)); /* process the password */ MD5Update(&ctx, msg_passwd, strlen(msg_passwd)); /* process the password */
MD5Final(&ctx, md5_result); MD5Final(&ctx, md5_result);
return memcmp(md5_result, real_passwd, MD5_SIZE);/* 0 = ok */ return memcmp(md5_result, real_passwd, MD5_SIZE);/* 0 = ok */
@ -888,36 +910,15 @@ static int check_digest(char *b64_file_passwd, const char *msg_passwd)
static int auth_check(struct connstruct *cn) static int auth_check(struct connstruct *cn)
{ {
char dirname[MAXREQUESTLENGTH];
char authpath[MAXREQUESTLENGTH];
char line[MAXREQUESTLENGTH]; char line[MAXREQUESTLENGTH];
FILE *fp;
char *cp; char *cp;
FILE *fp = NULL;
struct stat auth_stat;
strncpy(dirname, cn->actualfile, MAXREQUESTLENGTH); if ((fp = exist_check(cn, ".htpasswd")) == NULL)
cp = strrchr(dirname, '/'); return 0; /* no .htpasswd file, so let though */
if (cp == NULL)
dirname[0] = 0;
else
*cp = 0;
/* check that the file is not the AUTH_FILE itself */
if (strcmp(cn->actualfile, AUTH_FILE) == 0)
{
send_error(cn, 403);
goto error;
}
snprintf(authpath, MAXREQUESTLENGTH, "%s/%s", dirname, AUTH_FILE);
if (stat(authpath, &auth_stat) < 0) /* no auth file, so let though */
return 0;
if (cn->authorization[0] == 0) if (cn->authorization[0] == 0)
{ goto error;
send_authenticate(cn, dirname);
return -1;
}
/* cn->authorization is in form "username:password" */ /* cn->authorization is in form "username:password" */
if ((cp = strchr(cn->authorization, ':')) == NULL) if ((cp = strchr(cn->authorization, ':')) == NULL)
@ -925,8 +926,6 @@ static int auth_check(struct connstruct *cn)
else else
*cp++ = 0; /* cp becomes the password */ *cp++ = 0; /* cp becomes the password */
fp = fopen(authpath, "r");
while (fgets(line, sizeof(line), fp) != NULL) while (fgets(line, sizeof(line), fp) != NULL)
{ {
char *b64_file_passwd; char *b64_file_passwd;
@ -952,14 +951,41 @@ static int auth_check(struct connstruct *cn)
} }
} }
fclose(fp);
error: error:
send_authenticate(cn, dirname); fclose(fp);
send_authenticate(cn, cn->virtualhostreq);
return -1; return -1;
} }
#endif #endif
static int htaccess_check(struct connstruct *cn)
{
char line[MAXREQUESTLENGTH];
FILE *fp;
int ret = 0;
if ((fp = exist_check(cn, ".htaccess")) == NULL)
return 0; /* no .htaccess file, so let though */
while (fgets(line, sizeof(line), fp) != NULL)
{
if (!cn->is_ssl && strstr(line, "SSLRequireSSL"))
{
ret = -1; /* SSL port access required */
break;
}
if (strstr(line, "Deny all"))
{
ret = -1; /* access to this dir denied */
break;
}
}
fclose(fp);
return ret;
}
static void send_error(struct connstruct *cn, int err) static void send_error(struct connstruct *cn, int err)
{ {
char buf[1024]; char buf[1024];
@ -971,6 +997,10 @@ static void send_error(struct connstruct *cn, int err)
case 403: case 403:
title = "Forbidden"; title = "Forbidden";
text = "File is protected"; text = "File is protected";
#ifdef CONFIG_HTTP_VERBOSE
printf("axhttpd: access to %s:/%s denied\n",
cn->is_ssl ? "https" : "http", cn->actualfile); TTY_FLUSH();
#endif
break; break;
case 404: case 404:
@ -979,9 +1009,12 @@ static void send_error(struct connstruct *cn, int err)
break; break;
} }
sprintf(buf, "HTTP/1.1 %d %s\nContent-Type: text/html\n" sprintf(buf, "HTTP/1.1 %d %s\n"
"<html><body>\n<title>%d %s</title>" "Content-Type: text/html\n"
"<h1>%d %s</h1>\n</body></html>\n", "Cache-Control: no-cache,no-store\n"
"Connection: close\n\n"
"<html>\n<head>\n<title>%d %s</title></head>\n"
"<body><h1>%d %s</h1>\n</body></html>\n",
err, title, err, title, err, text); err, title, err, title, err, text);
special_write(cn, buf, strlen(buf)); special_write(cn, buf, strlen(buf));
removeconnection(cn); removeconnection(cn);

View File

@ -99,5 +99,5 @@ endif
clean:: clean::
$(MAKE) -C test clean $(MAKE) -C test clean
-@rm -f ../$(STAGE)/*.pch ../$(STAGE)/*.so* ../$(STAGE)/*.a ../$(STAGE)/*.dll ../$(STAGE)/*.lib ../$(STAGE)/*.exp ../$(STAGE)/*.pdb ../$(STAGE)/*.ilk -@rm -f ../$(STAGE)/* *.a *.lib

View File

@ -123,9 +123,9 @@ void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
/************************************************************************** /**************************************************************************
* RNG declarations * RNG declarations
**************************************************************************/ **************************************************************************/
void RNG_initialize(const uint8_t *seed_buf, int size); EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
void RNG_terminate(void); EXP_FUNC void STDCALL RNG_terminate(void);
void get_random(int num_rand_bytes, uint8_t *rand_data); EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
/************************************************************************** /**************************************************************************
@ -270,7 +270,7 @@ typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key,
int get_file(const char *filename, uint8_t **buf); int get_file(const char *filename, uint8_t **buf);
#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG) #if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)
void print_blob(const char *format, const uint8_t *data, int size, ...); EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
#else #else
#define print_blob(...) #define print_blob(...)
#endif #endif

View File

@ -82,7 +82,7 @@ int get_file(const char *filename, uint8_t **buf)
* - On Linux use /dev/urandom * - On Linux use /dev/urandom
* - If none of these work then use a custom RNG. * - If none of these work then use a custom RNG.
*/ */
void RNG_initialize(const uint8_t *seed_buf, int size) EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size)
{ {
if (rng_ref_count == 0) if (rng_ref_count == 0)
{ {
@ -106,9 +106,7 @@ void RNG_initialize(const uint8_t *seed_buf, int size)
int i; int i;
for (i = 0; i < size/(int)sizeof(uint64_t); i++) for (i = 0; i < size/(int)sizeof(uint64_t); i++)
{
rng_num ^= *((uint64_t *)&seed_buf[i*sizeof(uint64_t)]); rng_num ^= *((uint64_t *)&seed_buf[i*sizeof(uint64_t)]);
}
srand((long)seed_buf); /* use the stack ptr as another rnd seed */ srand((long)seed_buf); /* use the stack ptr as another rnd seed */
#endif #endif
@ -120,7 +118,7 @@ void RNG_initialize(const uint8_t *seed_buf, int size)
/** /**
* Terminate the RNG engine. * Terminate the RNG engine.
*/ */
void RNG_terminate(void) EXP_FUNC void STDCALL RNG_terminate(void)
{ {
if (--rng_ref_count == 0) if (--rng_ref_count == 0)
{ {
@ -135,7 +133,7 @@ void RNG_terminate(void)
/** /**
* Set a series of bytes with a random number. Individual bytes can be 0 * Set a series of bytes with a random number. Individual bytes can be 0
*/ */
void get_random(int num_rand_bytes, uint8_t *rand_data) EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
{ {
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM) #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
/* use the Linux default */ /* use the Linux default */
@ -160,9 +158,7 @@ void get_random(int num_rand_bytes, uint8_t *rand_data)
memcpy(rand_data, &big_num1, sizeof(uint64_t)); memcpy(rand_data, &big_num1, sizeof(uint64_t));
if (num_rand_bytes > sizeof(uint64_t)) if (num_rand_bytes > sizeof(uint64_t))
{
memcpy(&rand_data[8], &big_num2, sizeof(uint64_t)); memcpy(&rand_data[8], &big_num2, sizeof(uint64_t));
}
if (num_rand_bytes > 16) if (num_rand_bytes > 16)
{ {
@ -189,9 +185,7 @@ void get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
for (i = 0; i < num_rand_bytes; i++) for (i = 0; i < num_rand_bytes; i++)
{ {
while (rand_data[i] == 0) /* can't be 0 */ while (rand_data[i] == 0) /* can't be 0 */
{
rand_data[i] = (uint8_t)(rand()); rand_data[i] = (uint8_t)(rand());
}
} }
} }
@ -243,7 +237,7 @@ static void print_hex(uint8_t hex)
* @param data [in] The start of data to use * @param data [in] The start of data to use
* @param ... [in] Any additional arguments * @param ... [in] Any additional arguments
*/ */
void print_blob(const char *format, EXP_FUNC void STDCALL print_blob(const char *format,
const uint8_t *data, int size, ...) const uint8_t *data, int size, ...)
{ {
int i; int i;
@ -264,7 +258,7 @@ void print_blob(const char *format,
} }
#elif defined(WIN32) #elif defined(WIN32)
/* VC6.0 doesn't handle variadic macros */ /* VC6.0 doesn't handle variadic macros */
void print_blob(const char *format, const unsigned char *data, EXP_FUNC void STDCALL print_blob(const char *format, const unsigned char *data,
int size, ...) {} int size, ...) {}
#endif #endif

View File

@ -3,10 +3,10 @@
echo "Content-Type: text/html" echo "Content-Type: text/html"
echo echo
echo "<html><title>System Health</title><body>" echo "<html><title>System Health</title><body>"
echo "<h1>System Health for '`hostname`'</h1>" echo "<h1>System Health for '`/bin/hostname`'</h1>"
echo "<h2>Processes</h2><table border=\"2\">" echo "<h2>Processes</h2><table border=\"2\">"
ps -ef | sed -e "s/\(.*\)/<tr><td>\1<\/td><\/tr>/" /bin/ps -ef | /bin/sed -e "s/\(.*\)/<tr><td>\1<\/td><\/tr>/"
echo "</table><h2>Free FileSystem Space</h2>" echo "</table><h2>Free FileSystem Space</h2>"
echo "<table border=\"2\">" echo "<table border=\"2\">"
df -h . | sed -e "s/\(.*\)/<tr><td>\1<\/td><\/tr>/" /bin/df -h / | /bin/sed -e "s/\(.*\)/<tr><td>\1<\/td><\/tr>/"
echo "</table></body></html>" echo "</table></body></html>"

View File

@ -0,0 +1,2 @@
SSLRequireSSL

View File

@ -0,0 +1 @@
abcd:CQhgDPyy0rvEU8OMxnQIvg==$YdJfIKZimFLYxPf/rbnhtQ==

View File

@ -0,0 +1,6 @@
<html>
<head><title>axhttpd is running</title></head>
<body>
Looks like you got to this directory.
</body>
</htm>

View File

@ -1,4 +1,4 @@
#!/usr/bin/php #!/bin/php
<? <?
phpinfo(); phpinfo();