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

adding authentication, AES alignment issue, MACRO issue

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@59 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2007-02-07 12:22:35 +00:00
parent 9241353c50
commit 30a1970bb2
17 changed files with 401 additions and 263 deletions

12
CHANGELOG Normal file
View File

@ -0,0 +1,12 @@
Changes since 1.0.0
* AES should now work on 16bit processors (there was an alignment problem)
* Various freed objects are cleared before freeing.
* Header files now installed in /usr/local/include/axTLS
* -DCYGWIN replaced with -DCONFIG_PLATFORM_CYGWIN (and the same for solaris)
axhttpd Changes
* Header file issue fixed (in mime_types.c)
* chroot() now used for better security
* Authentication implemented
*

View File

@ -74,10 +74,20 @@ win32_demo:
install: $(PREFIX) all install: $(PREFIX) all
cp --no-dereference $(STAGE)/libax* $(PREFIX)/lib cp --no-dereference $(STAGE)/libax* $(PREFIX)/lib
chmod 755 $(PREFIX)/lib/libax* chmod 755 $(PREFIX)/lib/libax*
-install -m 755 $(STAGE)/ax* $(PREFIX)/bin > /dev/null 2>&1 -install -m 755 $(STAGE)/ax* $(PREFIX)/bin
ifdef CONFIG_PERL_BINDINGS ifdef CONFIG_PERL_BINDINGS
-install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'` > /dev/null 2>&1 -install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'`
endif endif
@mkdir -p -m 755 $(PREFIX)/include/axTLS
-install -m 644 ssl/bigint.h $(PREFIX)/include/axTLS
-install -m 644 ssl/bigint_impl.h $(PREFIX)/include/axTLS
-install -m 644 ssl/crypto.h $(PREFIX)/include/axTLS
-install -m 644 ssl/os_port.h $(PREFIX)/include/axTLS
-install -m 644 ssl/bigint.h $(PREFIX)/include/axTLS
-install -m 644 ssl/ssl.h $(PREFIX)/include/axTLS
-install -m 644 ssl/tls1.h $(PREFIX)/include/axTLS
-install -m 644 ssl/version.h $(PREFIX)/include/axTLS
-install -m 644 config/config.h $(PREFIX)/include/axTLS
installclean: installclean:
-@rm $(PREFIX)/lib/libax* > /dev/null 2>&1 -@rm $(PREFIX)/lib/libax* > /dev/null 2>&1

View File

@ -79,7 +79,7 @@ LD=$(CC)
# Solaris # Solaris
ifdef CONFIG_PLATFORM_SOLARIS ifdef CONFIG_PLATFORM_SOLARIS
CFLAGS += -DSOLARIS CFLAGS += -DCONFIG_PLATFORM_SOLARIS
LDFLAGS += -lsocket -lnsl -lc LDFLAGS += -lsocket -lnsl -lc
LDSHARED = -G LDSHARED = -G
# Linux/Cygwin # Linux/Cygwin
@ -89,7 +89,7 @@ LDSHARED = -shared
ifndef CONFIG_PLATFORM_CYGWIN ifndef CONFIG_PLATFORM_CYGWIN
CFLAGS += -fPIC CFLAGS += -fPIC
else else
CFLAGS += -DCYGWIN CFLAGS += -DCONFIG_PLATFORM_CYGWIN
endif endif
endif endif

View File

@ -13,6 +13,14 @@ config CONFIG_HTTP_STATIC_BUILD
Select y if you want axhttp to be a static build (i.e. don't use the Select y if you want axhttp 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
int "HTTP port"
default 80
help
The port number of the normal HTTP server.
You must be a root user in order to use the default port.
config CONFIG_HTTP_HTTPS_PORT config CONFIG_HTTP_HTTPS_PORT
int "HTTPS port" int "HTTPS port"
default 443 default 443
@ -39,14 +47,6 @@ config CONFIG_HTTP_WEBROOT
The location of the web root in relation to axhttpd. This is The location of the web root in relation to axhttpd. This is
the directory where index.html lives. the directory where index.html lives.
config CONFIG_HTTP_PORT
int "HTTP port"
default 80
help
The port number of the normal HTTP server.
You must be a root user in order to use the default port.
config CONFIG_HTTP_TIMEOUT config CONFIG_HTTP_TIMEOUT
int "Timeout" int "Timeout"
default 5 default 5
@ -79,6 +79,12 @@ config CONFIG_HTTP_PERM_CHECK
Enable permissions checking on the directories before reading the Enable permissions checking on the directories before reading the
files in them. files in them.
config CONFIG_HTTP_HAS_AUTHORIZATION
bool "Enable authorization"
default n
help
Pages/directories can have passwords associated with them.
config CONFIG_HTTP_HAS_IPV6 config CONFIG_HTTP_HAS_IPV6
bool "Enable IPv6" bool "Enable IPv6"
default n default n

View File

@ -54,7 +54,7 @@ else
web_server : $(TARGET) web_server : $(TARGET)
OBJ= \ OBJ= \
main.o \ axhttpd.o \
proc.o \ proc.o \
mime_types.o mime_types.o

View File

@ -77,6 +77,9 @@ struct connstruct
uint8_t is_ssl; uint8_t is_ssl;
uint8_t close_when_done; uint8_t close_when_done;
uint8_t modified_since; uint8_t modified_since;
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
char authorization[MAXREQUESTLENGTH];
#endif
}; };
struct serverstruct struct serverstruct
@ -103,9 +106,6 @@ extern struct connstruct *freeconns;
extern struct cgiextstruct *cgiexts; extern struct cgiextstruct *cgiexts;
#endif #endif
// Conf global prototypes
extern char *webroot;
// conn.c prototypes // conn.c prototypes
void removeconnection(struct connstruct *cn); void removeconnection(struct connstruct *cn);

View File

@ -27,7 +27,6 @@
struct serverstruct *servers; struct serverstruct *servers;
struct connstruct *usedconns; struct connstruct *usedconns;
struct connstruct *freeconns; struct connstruct *freeconns;
char *webroot = CONFIG_HTTP_WEBROOT;
static void addtoservers(int sd); static void addtoservers(int sd);
static int openlistener(int port); static int openlistener(int port);
@ -86,11 +85,12 @@ static void die(int sigtype)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
static char *webroot = CONFIG_HTTP_WEBROOT;
fd_set rfds, wfds; fd_set rfds, wfds;
struct connstruct *tp, *to; struct connstruct *tp, *to;
struct serverstruct *sp; struct serverstruct *sp;
int rnum, wnum, active; int rnum, wnum, active;
int webrootlen, i; int i;
time_t currtime; time_t currtime;
#ifdef WIN32 #ifdef WIN32
@ -98,12 +98,6 @@ int main(int argc, char *argv[])
WSADATA wsaData; WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData); WSAStartup(wVersionRequested,&wsaData);
#else #else
if (getuid() == 0) /* change our uid if we are root */
{
setgid(32767);
setuid(32767);
}
signal(SIGQUIT, die); signal(SIGQUIT, die);
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
@ -122,12 +116,8 @@ int main(int argc, char *argv[])
freeconns->next = tp; freeconns->next = tp;
} }
webrootlen = strlen(webroot); /* change to webroot for better security */
if (chroot(webroot))
if (webroot[webrootlen-1] == '/')
webroot[webrootlen-1] = '\0';
if (isdir(webroot) == 0)
{ {
#ifdef CONFIG_HTTP_VERBOSE #ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "'%s' is not a directory\n", webroot); fprintf(stderr, "'%s' is not a directory\n", webroot);
@ -135,6 +125,11 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
#ifndef WIN32
setgid(32767);
setuid(32767);
#endif
if ((active = openlistener(CONFIG_HTTP_PORT)) == -1) if ((active = openlistener(CONFIG_HTTP_PORT)) == -1)
{ {
#ifdef CONFIG_HTTP_VERBOSE #ifdef CONFIG_HTTP_VERBOSE

View File

@ -20,7 +20,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include "os_port.h" #include "axhttp.h"
static const char mime_default[] = "text/plain"; static const char mime_default[] = "text/plain";

View File

@ -29,8 +29,7 @@
static int special_read(struct connstruct *cn, void *buf, size_t count); static int special_read(struct connstruct *cn, void *buf, size_t count);
static int special_write(struct connstruct *cn, static int special_write(struct connstruct *cn,
const uint8_t *buf, size_t count); const uint8_t *buf, size_t count);
static void send404(struct connstruct *cn); static void send_error(struct connstruct *cn, int err);
static int procindex(struct connstruct *cn, struct stat *stp);
static int hexit(char c); static int hexit(char c);
static void urldecode(char *buf); static void urldecode(char *buf);
static void buildactualfile(struct connstruct *cn); static void buildactualfile(struct connstruct *cn);
@ -47,6 +46,9 @@ static int trycgi_withpathinfo(struct connstruct *cn);
static void split(char *tp, char *sp[], int maxwords, char sc); static void split(char *tp, char *sp[], int maxwords, char sc);
static int iscgi(const char *fn); static int iscgi(const char *fn);
#endif #endif
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
static int auth_check(struct connstruct *cn);
#endif
/* Returns 1 if elems should continue being read, 0 otherwise */ /* Returns 1 if elems should continue being read, 0 otherwise */
static int procheadelem(struct connstruct *cn, char *buf) static int procheadelem(struct connstruct *cn, char *buf)
@ -61,10 +63,11 @@ 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 || if (strcmp(buf, "GET") == 0 ||
strcmp(buf, "HEAD")==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;
@ -79,8 +82,7 @@ static int procheadelem(struct connstruct *cn, char *buf)
if (sanitizefile(value) == 0) if (sanitizefile(value) == 0)
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn);
return 0; return 0;
} }
@ -98,7 +100,6 @@ static int procheadelem(struct connstruct *cn, char *buf)
{ {
if (sanitizehost(value) == 0) if (sanitizehost(value) == 0)
{ {
send404(cn);
removeconnection(cn); removeconnection(cn);
return 0; return 0;
} }
@ -114,6 +115,15 @@ static int procheadelem(struct connstruct *cn, char *buf)
/* TODO: parse this date properly with getdate() or similar */ /* TODO: parse this date properly with getdate() or similar */
cn->modified_since = 1; cn->modified_since = 1;
} }
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
else if (strcmp(buf, "Authorization:") == 0 &&
strncmp(value, "Basic ", 6) == 0)
{
if (base64_decode(&value[6], strlen(&value[6]),
cn->authorization, NULL))
cn->authorization[0] = 0; /* error */
}
#endif
return 1; return 1;
} }
@ -141,15 +151,13 @@ static void procdirlisting(struct connstruct *cn)
if (cn->dirp == INVALID_HANDLE_VALUE) if (cn->dirp == INVALID_HANDLE_VALUE)
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
#else #else
if ((cn->dirp = opendir(actualfile)) == NULL) if ((cn->dirp = opendir(actualfile)) == NULL)
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
@ -205,11 +213,16 @@ void procdodir(struct connstruct *cn)
if (file[0] == '.' && file[1] != '.') if (file[0] == '.' && file[1] != '.')
continue; continue;
/* make sure a '/' is at the end of a directory */
if (cn->filereq[strlen(cn->filereq)-1] != '/')
strcat(cn->filereq, "/");
/* see if the dir + file is another directory */
snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, file); snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, file);
if (isdir(buf)) if (isdir(buf))
strcat(file, "/"); strcat(file, "/");
urlencode(file, encbuf);
urlencode(file, encbuf);
snprintf(buf, sizeof(buf), "<a href=\"%s%s\">%s</a><br />\n", snprintf(buf, sizeof(buf), "<a href=\"%s%s\">%s</a><br />\n",
cn->filereq, encbuf, file); cn->filereq, encbuf, file);
} while (special_write(cn, buf, strlen(buf))); } while (special_write(cn, buf, strlen(buf)));
@ -263,6 +276,10 @@ void procreadhead(struct connstruct *cn)
buf[rv] = '\0'; buf[rv] = '\0';
next = tp = buf; next = tp = buf;
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
cn->authorization[0] = 0;
#endif
/* Split up lines and send to procheadelem() */ /* Split up lines and send to procheadelem() */
while (*next != '\0') while (*next != '\0')
{ {
@ -297,22 +314,22 @@ void procreadhead(struct connstruct *cn)
*/ */
void procsendhead(struct connstruct *cn) void procsendhead(struct connstruct *cn)
{ {
char buf[1024]; char buf[MAXREQUESTLENGTH];
char actualfile[1024];
struct stat stbuf; struct stat stbuf;
time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT; time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
char date[32]; char date[32];
strcpy(date, ctime(&now)); #ifdef CONFIG_HTTP_HAS_AUTHORIZATION
strcpy(actualfile, cn->actualfile); if (auth_check(cn))
{
#ifdef WIN32 removeconnection(cn);
/* stat() under win32 can't deal with trail slash */ return;
if (actualfile[strlen(actualfile)-1] == '\\') }
actualfile[strlen(actualfile)-1] = 0;
#endif #endif
if (stat(actualfile, &stbuf) == -1) strcpy(date, ctime(&now));
if (stat(cn->actualfile, &stbuf) == -1)
{ {
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
if (trycgi_withpathinfo(cn) == 0) if (trycgi_withpathinfo(cn) == 0)
@ -323,8 +340,7 @@ void procsendhead(struct connstruct *cn)
} }
#endif #endif
send404(cn); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
@ -335,8 +351,7 @@ void procsendhead(struct connstruct *cn)
/* Set up CGI script */ /* Set up CGI script */
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
#endif #endif
@ -346,17 +361,20 @@ void procsendhead(struct connstruct *cn)
} }
#endif #endif
/* look for "index.html"? */
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
{ {
/* Check to see if this dir has an index file */ char tbuf[MAXREQUESTLENGTH];
if (procindex(cn, &stbuf) == 0) sprintf(tbuf, "%s%s", cn->actualfile, "index.html");
if (stat(tbuf, &stbuf) != -1)
strcat(cn->actualfile, "index.html");
else
{ {
#if defined(CONFIG_HTTP_DIRECTORIES) #if defined(CONFIG_HTTP_DIRECTORIES)
/* If not, we do a directory listing of it */ /* If not, we do a directory listing of it */
procdirlisting(cn); procdirlisting(cn);
#else #else
send404(cn); send_error(cn, 404);
removeconnection(cn);
#endif #endif
return; return;
} }
@ -368,8 +386,7 @@ void procsendhead(struct connstruct *cn)
/* Set up CGI script */ /* Set up CGI script */
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn);
return; return;
} }
@ -412,14 +429,14 @@ void procsendhead(struct connstruct *cn)
else else
{ {
int flags = O_RDONLY; int flags = O_RDONLY;
#if defined(WIN32) || defined(CYGWIN) #if defined(WIN32) || defined(CONFIG_PLATFORM_CYGWIN)
flags |= O_BINARY; flags |= O_BINARY;
#endif #endif
cn->filedesc = open(cn->actualfile, flags); cn->filedesc = open(cn->actualfile, flags);
if (cn->filedesc == -1) if (cn->filedesc == -1)
{ {
send404(cn); send_error(cn, 404);
removeconnection(cn); removeconnection(cn);
return; return;
} }
@ -515,23 +532,6 @@ static int special_read(struct connstruct *cn, void *buf, size_t count)
return res; return res;
} }
/* Returns 0 if no index was found and doesn't modify cn->actualfile
Returns 1 if an index was found and puts the index in cn->actualfile
and puts its stat info into stp */
static int procindex(struct connstruct *cn, struct stat *stp)
{
char tbuf[MAXREQUESTLENGTH];
sprintf(tbuf, "%s%s", cn->actualfile, "index.html");
if (stat(tbuf, stp) != -1)
{
my_strncpy(cn->actualfile, tbuf, MAXREQUESTLENGTH);
return 1;
}
return 0;
}
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
static void proccgi(struct connstruct *cn, int has_pathinfo) static void proccgi(struct connstruct *cn, int has_pathinfo)
{ {
@ -651,8 +651,8 @@ static int trycgi_withpathinfo(struct connstruct *cn)
while (fr_rs[i] != NULL) while (fr_rs[i] != NULL)
{ {
snprintf(tpfile, sizeof(tpfile), "%s/%s%s", snprintf(tpfile, sizeof(tpfile), "/%s%s",
webroot, cn->virtualhostreq, fr_str); cn->virtualhostreq, fr_str);
if (iscgi(tpfile) && isdir(tpfile) == 0) if (iscgi(tpfile) && isdir(tpfile) == 0)
{ {
@ -782,18 +782,9 @@ static int hexit(char c)
return 0; return 0;
} }
static void send404(struct connstruct *cn)
{
char buf[1024];
strcpy(buf, "HTTP/1.0 404 Not Found\nContent-Type: text/html\n\n"
"<html><body>\n<title>404 Not Found</title><h1>"
"404 Not Found</h1>\n</body></html>\n");
special_write(cn, buf, strlen(buf));
}
static void buildactualfile(struct connstruct *cn) static void buildactualfile(struct connstruct *cn)
{ {
snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s%s", webroot, cn->filereq); snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s", cn->filereq);
/* Add directory slash if not there */ /* Add directory slash if not there */
if (isdir(cn->actualfile) && if (isdir(cn->actualfile) &&
@ -805,9 +796,7 @@ static void buildactualfile(struct connstruct *cn)
{ {
char *t = cn->actualfile; char *t = cn->actualfile;
while ((t = strchr(t, '/'))) while ((t = strchr(t, '/')))
{
*t++ = '\\'; *t++ = '\\';
}
} }
#endif #endif
} }
@ -855,3 +844,146 @@ static int sanitizehost(char *buf)
return 1; return 1;
} }
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
#define AUTH_FILE ".htpasswd"
static void send_authenticate(struct connstruct *cn, const char *realm)
{
char buf[1024];
snprintf(buf, sizeof(buf), "HTTP/1.1 401 Unauthorized\n"
"WWW-Authenticate: Basic\n"
"realm=\"%s\"\n", realm);
special_write(cn, buf, strlen(buf));
}
static int check_digest(char *b64_file_passwd, const char *msg_passwd)
{
uint8_t real_salt[MAXREQUESTLENGTH];
uint8_t real_passwd[MAXREQUESTLENGTH];
int real_passwd_size, real_salt_size;
char *b64_pwd;
uint8_t md5_result[MD5_SIZE];
MD5_CTX ctx;
/* retrieve the salt */
if ((b64_pwd = strchr(b64_file_passwd, '$')) == NULL)
return -1;
*b64_pwd++ = 0;
if (base64_decode(b64_file_passwd, strlen(b64_file_passwd),
real_salt, &real_salt_size))
return -1;
if (base64_decode(b64_pwd, strlen(b64_pwd), real_passwd, &real_passwd_size))
return -1;
/* very simple MD5 crypt algorithm, but then the salt we use is large */
MD5Init(&ctx);
MD5Update(&ctx, real_salt, real_salt_size); /* process the salt */
MD5Update(&ctx, msg_passwd, strlen(msg_passwd)); /* process the password */
MD5Final(&ctx, md5_result);
return memcmp(md5_result, real_passwd, MD5_SIZE);/* 0 = ok */
}
static int auth_check(struct connstruct *cn)
{
char dirname[MAXREQUESTLENGTH];
char authpath[MAXREQUESTLENGTH];
char line[MAXREQUESTLENGTH];
char *cp;
FILE *fp = NULL;
struct stat auth_stat;
strncpy(dirname, cn->actualfile, MAXREQUESTLENGTH);
cp = strrchr(dirname, '/');
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)
{
send_authenticate(cn, dirname);
return -1;
}
/* cn->authorization is in form "username:password" */
if ((cp = strchr(cn->authorization, ':')) == NULL)
goto error;
else
*cp++ = 0; /* cp becomes the password */
fp = fopen(authpath, "r");
while (fgets(line, sizeof(line), fp) != NULL)
{
char *b64_file_passwd;
int l = strlen(line);
/* nuke newline */
if (line[l-1] == '\n')
line[l-1] = 0;
/* line is form "username:salt(b64)$password(b64)" */
if ((b64_file_passwd = strchr(line, ':')) == NULL)
continue;
*b64_file_passwd++ = 0;
if (strcmp(line, cn->authorization)) /* our user? */
continue;
if (check_digest(b64_file_passwd, cp) == 0)
{
fclose(fp);
return 0;
}
}
fclose(fp);
error:
send_authenticate(cn, dirname);
return -1;
}
#endif
static void send_error(struct connstruct *cn, int err)
{
char buf[1024];
char *title;
char *text;
switch (err)
{
case 403:
title = "Forbidden";
text = "File is protected";
break;
case 404:
title = "Not Found";
text = title;
break;
}
sprintf(buf, "HTTP/1.1 %d %s\nContent-Type: text/html\n"
"<html><body>\n<title>%d %s</title>"
"<h1>%d %s</h1>\n</body></html>\n",
err, title, err, title, err, text);
special_write(cn, buf, strlen(buf));
removeconnection(cn);
}

View File

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
WSADATA wsaData; WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2); WORD wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData); WSAStartup(wVersionRequested, &wsaData);
#elif !defined(SOLARIS) #elif !defined(CONFIG_PLATFORM_SOLARIS)
signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */ signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */
#endif #endif

139
ssl/aes.c
View File

@ -62,10 +62,6 @@
(f8)^=rot2(f4), \ (f8)^=rot2(f4), \
(f8)^rot1(f9)) (f8)^rot1(f9))
/* some macros to do endian independent byte extraction */
#define n2l(c,l) l=ntohl(*c); c++
#define l2n(l,c) *c++=htonl(l)
/* /*
* AES S-box * AES S-box
*/ */
@ -249,7 +245,7 @@ void AES_convert_key(AES_CTX *ctx)
k = ctx->ks; k = ctx->ks;
k += 4; k += 4;
for (i=ctx->rounds*4; i>4; i--) for (i= ctx->rounds*4; i > 4; i--)
{ {
w= *k; w= *k;
w = inv_mix_col(w,t1,t2,t3,t4); w = inv_mix_col(w,t1,t2,t3,t4);
@ -262,46 +258,38 @@ void AES_convert_key(AES_CTX *ctx)
*/ */
void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{ {
uint32_t tin0, tin1, tin2, tin3; int i;
uint32_t tout0, tout1, tout2, tout3; uint32_t tin[4], tout[4], iv[4];
uint32_t tin[4];
uint32_t *iv = (uint32_t *)ctx->iv;
uint32_t *msg_32 = (uint32_t *)msg;
uint32_t *out_32 = (uint32_t *)out;
n2l(iv, tout0); memcpy(iv, ctx->iv, AES_IV_SIZE);
n2l(iv, tout1); for (i = 0; i < 4; i++)
n2l(iv, tout2); tout[i] = ntohl(iv[i]);
n2l(iv, tout3);
iv -= 4;
for (length -= 16; length >= 0; length -= 16) for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
{ {
n2l(msg_32, tin0); uint32_t msg_32[4];
n2l(msg_32, tin1); uint32_t out_32[4];
n2l(msg_32, tin2); memcpy(msg_32, msg, AES_BLOCKSIZE);
n2l(msg_32, tin3); msg += AES_BLOCKSIZE;
tin[0] = tin0^tout0;
tin[1] = tin1^tout1; for (i = 0; i < 4; i++)
tin[2] = tin2^tout2; tin[i] = ntohl(msg_32[i])^tout[i];
tin[3] = tin3^tout3;
AES_encrypt(ctx, tin); AES_encrypt(ctx, tin);
tout0 = tin[0]; for (i = 0; i < 4; i++)
l2n(tout0, out_32); {
tout1 = tin[1]; tout[i] = tin[i];
l2n(tout1, out_32); out_32[i] = htonl(tout[i]);
tout2 = tin[2]; }
l2n(tout2, out_32);
tout3 = tin[3]; memcpy(out, out_32, AES_BLOCKSIZE);
l2n(tout3, out_32); out += AES_BLOCKSIZE;
} }
l2n(tout0, iv); for (i = 0; i < 4; i++)
l2n(tout1, iv); iv[i] = htonl(tout[i]);
l2n(tout2, iv); memcpy(ctx->iv, iv, AES_IV_SIZE);
l2n(tout3, iv);
} }
/** /**
@ -309,54 +297,42 @@ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
*/ */
void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
{ {
uint32_t tin0, tin1, tin2, tin3; int i;
uint32_t xor0,xor1,xor2,xor3; uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
uint32_t tout0,tout1,tout2,tout3;
uint32_t data[4];
uint32_t *iv = (uint32_t *)ctx->iv;
uint32_t *msg_32 = (uint32_t *)msg;
uint32_t *out_32 = (uint32_t *)out;
n2l(iv ,xor0); memcpy(iv, ctx->iv, AES_IV_SIZE);
n2l(iv, xor1); for (i = 0; i < 4; i++)
n2l(iv, xor2); xor[i] = ntohl(iv[i]);
n2l(iv, xor3);
iv -= 4;
for (length-=16; length >= 0; length -= 16) for (length -= 16; length >= 0; length -= 16)
{ {
n2l(msg_32, tin0); uint32_t msg_32[4];
n2l(msg_32, tin1); uint32_t out_32[4];
n2l(msg_32, tin2); memcpy(msg_32, msg, AES_BLOCKSIZE);
n2l(msg_32, tin3); msg += AES_BLOCKSIZE;
data[0] = tin0; for (i = 0; i < 4; i++)
data[1] = tin1; {
data[2] = tin2; tin[i] = ntohl(msg_32[i]);
data[3] = tin3; data[i] = tin[i];
}
AES_decrypt(ctx, data); AES_decrypt(ctx, data);
tout0 = data[0]^xor0; for (i = 0; i < 4; i++)
tout1 = data[1]^xor1; {
tout2 = data[2]^xor2; tout[i] = data[i]^xor[i];
tout3 = data[3]^xor3; xor[i] = tin[i];
out_32[i] = htonl(tout[i]);
}
xor0 = tin0; memcpy(out, out_32, AES_BLOCKSIZE);
xor1 = tin1; out += AES_BLOCKSIZE;
xor2 = tin2;
xor3 = tin3;
l2n(tout0, out_32);
l2n(tout1, out_32);
l2n(tout2, out_32);
l2n(tout3, out_32);
} }
l2n(xor0, iv); for (i = 0; i < 4; i++)
l2n(xor1, iv); iv[i] = htonl(xor[i]);
l2n(xor2, iv); memcpy(ctx->iv, iv, AES_IV_SIZE);
l2n(xor3, iv);
} }
/** /**
@ -375,9 +351,7 @@ static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
/* Pre-round key addition */ /* Pre-round key addition */
for (row = 0; row < 4; row++) for (row = 0; row < 4; row++)
{
data[row] ^= *(k++); data[row] ^= *(k++);
}
/* Encrypt one block. */ /* Encrypt one block. */
for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++) for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
@ -395,7 +369,6 @@ static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
{ {
tmp1 = a0 ^ a1 ^ a2 ^ a3; tmp1 = a0 ^ a1 ^ a2 ^ a3;
old_a0 = a0; old_a0 = a0;
a0 ^= tmp1 ^ AES_xtime(a0 ^ a1); a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
a1 ^= tmp1 ^ AES_xtime(a1 ^ a2); a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
a2 ^= tmp1 ^ AES_xtime(a2 ^ a3); a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
@ -408,9 +381,7 @@ static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
/* KeyAddition - note that it is vital that this loop is separate from /* KeyAddition - note that it is vital that this loop is separate from
the MixColumn operation, which must be atomic...*/ the MixColumn operation, which must be atomic...*/
for (row = 0; row < 4; row++) for (row = 0; row < 4; row++)
{
data[row] = tmp[row] ^ *(k++); data[row] = tmp[row] ^ *(k++);
}
} }
} }
@ -424,16 +395,14 @@ static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
uint32_t a0, a1, a2, a3, row; uint32_t a0, a1, a2, a3, row;
int curr_rnd; int curr_rnd;
int rounds = ctx->rounds; int rounds = ctx->rounds;
uint32_t *k = (uint32_t*)ctx->ks + ((rounds+1)*4); const uint32_t *k = ctx->ks + ((rounds+1)*4);
/* pre-round key addition */ /* pre-round key addition */
for (row=4; row > 0;row--) for (row=4; row > 0;row--)
{
data[row-1] ^= *(--k); data[row-1] ^= *(--k);
}
/* Decrypt one block */ /* Decrypt one block */
for (curr_rnd=0; curr_rnd < rounds; curr_rnd++) for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
{ {
/* Perform ByteSub and ShiftRow operations together */ /* Perform ByteSub and ShiftRow operations together */
for (row = 4; row > 0; row--) for (row = 4; row > 0; row--)
@ -468,9 +437,7 @@ static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
} }
for (row = 4; row > 0; row--) for (row = 4; row > 0; row--)
{
data[row-1] = tmp[row-1] ^ *(--k); data[row-1] = tmp[row-1] ^ *(--k);
}
} }
} }

View File

@ -34,13 +34,15 @@ extern "C" {
**************************************************************************/ **************************************************************************/
#define AES_MAXROUNDS 14 #define AES_MAXROUNDS 14
#define AES_BLOCKSIZE 16
#define AES_IV_SIZE 16
typedef struct aes_key_st typedef struct aes_key_st
{ {
uint16_t rounds; uint16_t rounds;
uint16_t key_size; uint16_t key_size;
uint32_t ks[(AES_MAXROUNDS+1)*8]; uint32_t ks[(AES_MAXROUNDS+1)*8];
uint8_t iv[16]; uint8_t iv[AES_IV_SIZE];
} AES_CTX; } AES_CTX;
typedef enum typedef enum
@ -106,9 +108,9 @@ typedef struct
uint8_t buffer[64]; /* input buffer */ uint8_t buffer[64]; /* input buffer */
} MD5_CTX; } MD5_CTX;
void MD5Init(MD5_CTX *); EXP_FUNC void STDCALL MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, const uint8_t *msg, int len); EXP_FUNC void STDCALL MD5Update(MD5_CTX *, const uint8_t *msg, int len);
void MD5Final(MD5_CTX *, uint8_t *digest); EXP_FUNC void STDCALL MD5Final(MD5_CTX *, uint8_t *digest);
/************************************************************************** /**************************************************************************
* HMAC declarations * HMAC declarations
@ -273,6 +275,9 @@ void print_blob(const char *format, const uint8_t *data, int size, ...);
#define print_blob(...) #define print_blob(...)
#endif #endif
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -267,3 +267,78 @@ void print_blob(const char *format,
void print_blob(const char *format, const unsigned char *data, void print_blob(const char *format, const unsigned char *data,
int size, ...) {} int size, ...) {}
#endif #endif
#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
/* base64 to binary lookup table */
static const uint8_t map[128] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255
};
EXP_FUNC int STDCALL base64_decode(const char *in, int len,
uint8_t *out, int *outlen)
{
int g, t, x, y, z;
uint8_t c;
int ret = -1;
g = 3;
for (x = y = z = t = 0; x < len; x++)
{
if ((c = map[in[x]&0x7F]) == 0xff)
continue;
if (c == 254) /* this is the end... */
{
c = 0;
if (--g < 0)
goto error;
}
else if (g != 3) /* only allow = at end */
goto error;
t = (t<<6) | c;
if (++y == 4)
{
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1)
out[z++] = (uint8_t)((t>>8)&255);
if (g > 2)
out[z++] = (uint8_t)(t&255);
y = t = 0;
}
}
if (y != 0)
goto error;
if (outlen)
*outlen = z;
ret = 0;
error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret < 0)
printf("Error: Invalid base64\n"); TTY_FLUSH();
#endif
TTY_FLUSH();
return ret;
}
#endif

View File

@ -169,22 +169,6 @@ void ssl_obj_free(SSLObjLoader *ssl_obj)
#define IS_ENCRYPTED_PRIVATE_KEY 1 #define IS_ENCRYPTED_PRIVATE_KEY 1
#define IS_CERTIFICATE 2 #define IS_CERTIFICATE 2
/* base64 to binary lookup table */
static const uint8_t map[128] =
{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255
};
static const char * const begins[NUM_PEM_TYPES] = static const char * const begins[NUM_PEM_TYPES] =
{ {
"-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN RSA PRIVATE KEY-----",
@ -205,59 +189,6 @@ static const char * const aes_str[2] =
"DEK-Info: AES-256-CBC," "DEK-Info: AES-256-CBC,"
}; };
static int base64_decode(const uint8_t *in, int len,
uint8_t *out, int *outlen)
{
int g, t, x, y, z;
uint8_t c;
int ret = -1;
g = 3;
for (x = y = z = t = 0; x < len; x++)
{
if ((c = map[in[x] & 0x7F]) == 0xff)
continue;
if (c == 254) /* this is the end... */
{
c = 0;
if (--g < 0)
goto error;
}
else if (g != 3) /* only allow = at end */
goto error;
t = (t<<6) | c;
if (++y == 4)
{
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1)
out[z++] = (uint8_t)((t>>8)&255);
if (g > 2)
out[z++] = (uint8_t)(t&255);
y = t = 0;
}
}
if (y != 0)
goto error;
*outlen = z;
ret = 0;
error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret < 0)
printf("Error: Invalid base64 file\n");
#endif
return ret;
}
/** /**
* Take a base64 blob of data and decrypt it (using AES) into its * Take a base64 blob of data and decrypt it (using AES) into its
* proper ASN.1 form. * proper ASN.1 form.
@ -372,7 +303,7 @@ static int new_pem_obj(SSLCTX *ssl_ctx, int is_cacert, uint8_t *where,
strstr((const char *)start, "4,ENCRYPTED")) strstr((const char *)start, "4,ENCRYPTED"))
{ {
/* check for encrypted PEM file */ /* check for encrypted PEM file */
if ((pem_size = pem_decrypt(start, end, password, ssl_obj)) < 0) if (pem_decrypt(start, end, password, ssl_obj) < 0)
goto error; goto error;
} }
else if (base64_decode(start, pem_size, else if (base64_decode(start, pem_size,

View File

@ -90,7 +90,7 @@ static const uint8_t PADDING[64] =
/** /**
* MD5 initialization - begins an MD5 operation, writing a new ctx. * MD5 initialization - begins an MD5 operation, writing a new ctx.
*/ */
void MD5Init(MD5_CTX *ctx) EXP_FUNC void STDCALL MD5Init(MD5_CTX *ctx)
{ {
ctx->count[0] = ctx->count[1] = 0; ctx->count[0] = ctx->count[1] = 0;
@ -105,7 +105,7 @@ void MD5Init(MD5_CTX *ctx)
/** /**
* Accepts an array of octets as the next portion of the message. * Accepts an array of octets as the next portion of the message.
*/ */
void MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len) EXP_FUNC void STDCALL MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
{ {
uint32_t x; uint32_t x;
int i, partLen; int i, partLen;
@ -141,7 +141,7 @@ void MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
/** /**
* Return the 128-bit message digest into the user's array * Return the 128-bit message digest into the user's array
*/ */
void MD5Final(MD5_CTX *ctx, uint8_t *digest) EXP_FUNC void STDCALL MD5Final(MD5_CTX *ctx, uint8_t *digest)
{ {
uint8_t bits[8]; uint8_t bits[8];
uint32_t x, padLen; uint32_t x, padLen;

View File

@ -29,7 +29,7 @@
extern "C" { extern "C" {
#endif #endif
#if defined(WIN32) || defined(CYGWIN) #if defined(WIN32) || defined(CONFIG_PLATFORM_CYGWIN)
#define STDCALL __stdcall #define STDCALL __stdcall
#define EXP_FUNC __declspec(dllexport) #define EXP_FUNC __declspec(dllexport)
#else #else
@ -56,6 +56,7 @@ extern "C" {
#endif /* _WIN32_WCE */ #endif /* _WIN32_WCE */
#include <winsock.h> #include <winsock.h>
#include <direct.h>
#undef getpid #undef getpid
#undef open #undef open
#undef close #undef close
@ -81,6 +82,7 @@ extern "C" {
#define usleep(A) Sleep(A/1000) #define usleep(A) Sleep(A/1000)
#define lseek(A,B,C) _lseek(A,B,C) #define lseek(A,B,C) _lseek(A,B,C)
#define strdup(A) _strdup(A) #define strdup(A) _strdup(A)
#define chroot(A) _chdir(A)
/* This fix gets around a problem where a win32 application on a cygwin xterm /* This fix gets around a problem where a win32 application on a cygwin xterm
doesn't display regular output (until a certain buffer limit) - but it works doesn't display regular output (until a certain buffer limit) - but it works
@ -113,7 +115,7 @@ extern EXP_FUNC int strcasecmp(const char *s1, const char *s2);
#else /* Not Win32 */ #else /* Not Win32 */
#ifdef SOLARIS #ifdef CONFIG_PLATFORM_SOLARIS
#include <inttypes.h> #include <inttypes.h>
#else #else
#include <stdint.h> #include <stdint.h>

View File

@ -1123,6 +1123,7 @@ static void set_key_block(SSL *ssl, int is_write)
/* clean up if possible */ /* clean up if possible */
if (key_block_existed) if (key_block_existed)
{ {
memset(ssl->key_block, 0, ciph_info->key_block_size);
free(ssl->key_block); free(ssl->key_block);
ssl->key_block = NULL; ssl->key_block = NULL;
} }
@ -1454,9 +1455,11 @@ int process_finished(SSL *ssl, int hs_len)
ssl->all_pkts = NULL; ssl->all_pkts = NULL;
ssl->all_pkts_len = 0; ssl->all_pkts_len = 0;
memset(ssl->master_secret, 0, SSL_SECRET_SIZE);
free(ssl->master_secret); free(ssl->master_secret);
ssl->master_secret = NULL; ssl->master_secret = NULL;
memset(ssl->final_finish_mac, 0, SSL_FINISHED_HASH_SIZE);
free(ssl->final_finish_mac); free(ssl->final_finish_mac);
ssl->final_finish_mac = NULL; ssl->final_finish_mac = NULL;