diff options
author | goodale <goodale@1faa4e14-9dd3-4be0-9f0e-ffe519881164> | 2000-09-15 12:45:27 +0000 |
---|---|---|
committer | goodale <goodale@1faa4e14-9dd3-4be0-9f0e-ffe519881164> | 2000-09-15 12:45:27 +0000 |
commit | 9ca8518895939d3ae82c937bed7f2b545a9f9e39 (patch) | |
tree | 6a4f12a4f4c472bffac1dbffb2b5a877bf2c0beb | |
parent | 3c4f4b1e6a1de4d6e16a70af4d11fc11ddb11da9 (diff) |
Made parallel aware.
Added stuff for parameter steering. See doc/Steering.txt.
Added stuff for HTTP Basic authentication. See doc/Auth.txt.
Tom
git-svn-id: http://svn.cactuscode.org/arrangements/CactusConnect/HTTPD/trunk@9 1faa4e14-9dd3-4be0-9f0e-ffe519881164
-rw-r--r-- | README | 19 | ||||
-rw-r--r-- | doc/Auth.txt | 104 | ||||
-rw-r--r-- | doc/Steering.txt | 30 | ||||
-rw-r--r-- | src/Authorisation.c | 356 | ||||
-rw-r--r-- | src/Content.c | 67 | ||||
-rw-r--r-- | src/Startup.c | 18 | ||||
-rw-r--r-- | src/Steer.c | 370 | ||||
-rw-r--r-- | src/base64.c | 330 | ||||
-rw-r--r-- | src/base64.h | 29 | ||||
-rw-r--r-- | src/http_Auth.h | 31 | ||||
-rw-r--r-- | src/http_Steer.h | 27 | ||||
-rw-r--r-- | src/make.code.defn | 13 |
12 files changed, 1385 insertions, 9 deletions
@@ -18,7 +18,9 @@ The current interface for this webserver is contained in http_Request.h (Note that this will change once we have an agreed common protocol for -other thorns to talk to web-serving thorns.) +other thorns to talk to web-serving thorns.) There are also utility +interface for parameter steering and HTTP authentication, which are +described in the files in the doc directory. The primary mechanism is to @@ -105,7 +107,8 @@ file. Structure of the thorn: ---------------------- -The thorn is split into two parts - web serving and content provision. +The thorn is split into three parts - basic web serving, utilities, +and content provision Web serving: ----------- @@ -124,6 +127,17 @@ The above files should not need to be touched apart from debugging purposes, to add more HTTP methods, or otherwise to enhance the interaction with the network and protocols. +Utilities: +_________ + +The web server provided utilities to help content provision - + +Steer.c - parameter steering interface + - see doc/Steering.txt + +Authorisation.c - HTTP authentication + - see doc/Auth.txt + Content Provision: ----------------- @@ -136,3 +150,4 @@ provide content. In principle this could be in another thorn, but that should wait until we have an agreed set of interfaces to allow web-server thorns to be interchangeable, at least at compile time, but hopefully at run-time. + diff --git a/doc/Auth.txt b/doc/Auth.txt new file mode 100644 index 0000000..9587b4f --- /dev/null +++ b/doc/Auth.txt @@ -0,0 +1,104 @@ + /*@@ + @file Auth.txt + @date Fri Sep 15 14:05:49 2000 + @author Tom Goodale + @desc + Description of http authentication interface interface. + @enddesc + @version $Header$ + @@*/ + +There is an HTTP authentication interface, which is accessed by +including http_Auth.h. + +This provides two functions: + +int HTTP_AuthAddUser(const char *database, + const char *name, + const char *password, + const char *encryption_scheme); + +which allows databases of users and passwords to be created. + +The encryption scheme says how the password which is being passed in +is encrypted. Currently supported schemes are 'none' for plaintext, +or 'crypt' for a password encrypted using crypt(3), such as is produced +by the unix passwd command, plus many other tools. The use of +crypt(3) relies on Cactus determining that the function exists. Other +encryption systems are easily added. + +This allows the password stored in parameter files or displayed on a +web page to be encrypted. + +The other function is + +int HTTP_AuthenticateBasic(httpRequest *request, + const char *database); + +which takes an HTTP request, and a password database, and sees if the +'Authorization' header field declares a user and password which are in +the database. This function supports the 'Basic' authentication +scheme supplied by HTTP/1.0. + +This function has three possible return codes. + ++1 - the Authorization header was missing. +0 - header there. User and password match. +-1 - header there. User and password don't match. + +Usage: +------ + +Create a set of users and password in a database, e.g. + + HTTP_AuthAddUser("developers","goodale","foo","none"); + +which declares a database called 'developers' and adds a user +'goodale; with password 'foo' which is plaintext. An equivalent +declaration would have been + +HTTP_AuthAddUser("developers","goodale","fSzQC4Ssz0ab.","crypt"); + +if the configuration supports crypt(3) passwords. + +Then when a page comes in, one does + + notauthorised = HTTP_AuthenticateBasic(request, "users"); + + if(!notauthorised) + { + /* Access allowed */ + strcpy(message,"HTTP/1.0 200 Ok\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"WWW-Authenticate: Basic realm=\"foo\"\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"Content-Type: text/html\r\n\r\n"); + + write(request->filedes, message, strlen(message)); + + ... + } + else + { + /* Access not allowed. */ + strcpy(message,"HTTP/1.0 401 Unauthorized\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"WWW-Authenticate: Basic realm=\"foo\"\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"Content-Type: text/html\r\n\r\n"); + + write(request->filedes, message, strlen(message)); + + ... + } + + Additionally you could check whether 'notauthorised' = +1 or -1 and +in the latter case log some message about a failed access request. diff --git a/doc/Steering.txt b/doc/Steering.txt new file mode 100644 index 0000000..26053ec --- /dev/null +++ b/doc/Steering.txt @@ -0,0 +1,30 @@ + /*@@ + @file Steering.txt + @date Fri Sep 15 14:05:49 2000 + @author Tom Goodale + @desc + Description of parameter steering interface. + @enddesc + @version $Header$ + @@*/ + +There is a parameter steering interface, which is accessed by +including http_Steer.h. + +This defines two functions: + + +int HTTP_SteerQueue(const char *thorn, + const char *parameter, + const char *value); + +which schedules a parameter to be steered, and + +int HTTP_SteerDispatch(void); + +which broadcasts the data to other processors and then +steers all the parameters which were queued. + +This is to allow steering requests to be queued up over several +iterations, and then broadcast at once, which should reduce the +number of barriers called by the code. diff --git a/src/Authorisation.c b/src/Authorisation.c new file mode 100644 index 0000000..3be4c3b --- /dev/null +++ b/src/Authorisation.c @@ -0,0 +1,356 @@ + /*@@ + @file Authorisation.c + @date Fri Sep 15 12:34:59 2000 + @author Tom Goodale + @desc + Authorisation stuff for webserver + @enddesc + @version $Header + @@*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "cctk.h" + +#include "util_Hash.h" +#include "util_String.h" + +#include "http_Request.h" +#include "http_Auth.h" + +#include "base64.h" + +static char *rcsid = "$Header$"; + +CCTK_FILEVERSION(DevThorns_httpd_Authorisation_c) + +/******************************************************************** + ********************* Local Data Types *********************** + ********************************************************************/ + +struct httpUserData +{ + char *password; + char *encryption_scheme; +}; + +/******************************************************************** + ********************* Local Routine Prototypes ********************* + ********************************************************************/ + +static int AddUser(uHash *database, + const char *name, + const char *password, + const char *encryption_scheme); + +static int VerifyPassword(const char *database, + const char *user, + const char *password); + +/******************************************************************** + ********************* Other Routine Prototypes ********************* + ********************************************************************/ + +/******************************************************************** + ********************* Local Data ***************************** + ********************************************************************/ + +static uHash *AuthDatabase = NULL; + +#define INITIAL_SIZE 32 +#define DECODED_SIZE 100 + +/******************************************************************** + ********************* External Routines ********************** + ********************************************************************/ + + /*@@ + @routine HTTP_AuthAddUser + @date Fri Sep 15 12:52:09 2000 + @author Tom Goodale + @desc + Adds a user to a http authentication database. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int HTTP_AuthAddUser(const char *database, + const char *name, + const char *password, + const char *encryption_scheme) +{ + int retcode; + uHash *this_database; + + /* Create the master database if necessary */ + if(!AuthDatabase) + { + AuthDatabase = Util_HashCreate(INITIAL_SIZE); + } + + if(AuthDatabase) + { + /* Does this database exist ? */ + this_database = (uHash *)Util_HashData(AuthDatabase, strlen(database), database, 0); + + if(!this_database) + { + this_database = Util_HashCreate(INITIAL_SIZE); + + if(this_database) + { + Util_HashStore(AuthDatabase, strlen(database), database, 0, (void *)this_database); + } + else + { + retcode = -2; + } + } + } + else + { + retcode = -1; + } + + /* Now add the user to the database */ + if(this_database) + { + retcode = AddUser(this_database, name, password, encryption_scheme); + } + + return retcode; +} + + + /*@@ + @routine HTTP_AuthenticateBasic + @date Fri Sep 15 13:12:43 2000 + @author Tom Goodale + @desc + Authenticates an HTTP request against + a particular database. + @enddesc + @calls + @calledby + @history + + @endhistory + + @returntype int + @returndesc + The authorisation status. + +1 means that there was no Authorization header. + 0 succesful authentication + -1 failed authentication + @endreturndesc + +@@*/ +int HTTP_AuthenticateBasic(httpRequest *request, + const char *database) +{ + int retval; + char message[1024]; + + const char *value; + char *auth_string; + char *token; + + int decoded_size; + unsigned char decoded[DECODED_SIZE+1]; + + unsigned char *password; + + int authorised; + + value = HTTP_HeaderValue(request, "Authorization"); + + auth_string = NULL; + + authorised = 0; + + /* Ok, there's an authentication string here. */ + if(value) + { + auth_string = Util_Strdup(value); + + token = strtok(auth_string, " "); + + if(token) + { + if(CCTK_Equals(token, "Basic")) + { + token = strtok(NULL, " ,\t"); + decoded_size = HTTP_b64_pton(token, decoded, DECODED_SIZE); + + /* Null terminate string */ + decoded[decoded_size] = 0; + + password = strchr(decoded, ':'); + + if(password) + { + *password = 0; + password++; + + authorised = VerifyPassword(database, decoded, password); + } + } + } + + if(auth_string) + { + free(auth_string); + } + + if(authorised) + { + retval = 0; + } + else + { + retval = -1; + } + } + else + { + /* There's no authentication string here */ + + retval = 1; + + } + + return retval; +} + +/******************************************************************** + ********************* Local Routines ************************* + ********************************************************************/ + + /*@@ + @routine AddUser + @date Fri Sep 15 12:52:37 2000 + @author Tom Goodale + @desc + Adds a user to a particular database. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static int AddUser(uHash *database, + const char *name, + const char *password, + const char *encryption_scheme) +{ + int retcode; + struct httpUserData *this_user; + + /* Does this user already exist ? */ + this_user = (struct httpUserData *)Util_HashData(database, strlen(name), name, 0); + + if(!this_user) + { + /* New user */ + + this_user = (struct httpUserData *)malloc(sizeof(struct httpUserData *)); + + if(this_user) + { + this_user->password = Util_Strdup(password); + this_user->encryption_scheme = Util_Strdup(encryption_scheme); + + retcode = Util_HashStore(database, strlen(name), name, 0, (void *)this_user); + } + else + { + retcode = -1; + } + } + else + { + /* Replace user's current data */ + free(this_user->password); + free(this_user->encryption_scheme); + + this_user->password = Util_Strdup(password); + this_user->encryption_scheme = Util_Strdup(encryption_scheme); + + retcode = 0; + } + + return retcode; +} + + /*@@ + @routine VerifyPassword + @date Fri Sep 15 13:28:50 2000 + @author Tom Goodale + @desc + Verifies a user and password against a database. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static int VerifyPassword(const char *database, + const char *user, + const char *password) +{ + int retcode; + uHash *this_database; + struct httpUserData *data; + + retcode = 0; + + if(AuthDatabase) + { + /* Does this database exist ? */ + this_database = (uHash *)Util_HashData(AuthDatabase, strlen(database), database, 0); + + if(this_database) + { + data = (struct httpUserData *) Util_HashData(this_database, strlen(user), user, 0); + + if(data) + { + /* Ok, now verify the password. */ + if(CCTK_Equals(data->encryption_scheme, "none")) + { + if(!strcmp(data->password, password)) + { + retcode = 1; + } + } + else if(CCTK_Equals(data->encryption_scheme, "crypt")) + { +#ifdef HAVE_CRYPT + if(!strcmp(data->password, crypt(password, data->password))) + { + retcode = 1; + } +#else + fprintf(stderr, "Sorry, crypt(3) not supported in this configuration.\n"); +#endif + } + else + { + fprintf(stderr, "Unknown encryption algorithm '%s'\n", data->encryption_scheme); + } + } + } + } + + return retcode; +} diff --git a/src/Content.c b/src/Content.c index 3e95e74..b1f6c34 100644 --- a/src/Content.c +++ b/src/Content.c @@ -12,6 +12,7 @@ @@*/ #include <stdio.h> +#include <string.h> #include "cctk.h" @@ -19,6 +20,8 @@ #include "http_Request.h" +#include "http_Auth.h" + static char *rcsid = "$Header$"; CCTK_FILEVERSION(DevThorns_httpd_Content_c) @@ -47,6 +50,8 @@ static int ShowStaticPage(cGH *cctkGH, httpRequest *request, void *data); static int TestPage(cGH *cctkGH, httpRequest *request, void *data); +static int AuthPage(cGH *cctkGH, httpRequest *request, void *data); + static int CompareStrings(const void *string1, const void *string2); /******************************************************************** @@ -91,6 +96,10 @@ int HTTP_RegisterPages(void) /* Register a test page */ HTTP_RegisterPage("/test_page", TestPage, NULL); + HTTP_RegisterPage("/auth_page", AuthPage, NULL); + + HTTP_AuthAddUser("user","goodale","foo","none"); + /* Registrer images */ RegisterImages(); } @@ -696,9 +705,9 @@ static int TestPage(cGH *cctkGH, httpRequest *request, void *data) write(request->filedes, message, strlen(message)); - value = HTTP_ArgumentValue(request, "cmd"); + value = HTTP_ArgumentValue(request, "text"); - sprintf(message, "cmd = %s<hr>\n", value); + sprintf(message, "text = %s<hr>\n", value); write(request->filedes, message, strlen(message)); @@ -715,3 +724,57 @@ static int TestPage(cGH *cctkGH, httpRequest *request, void *data) return retval; } + + +static const char *notauthorized_page = +"<HTML>\n<HEAD><TITLE>Error 401: Not Authorized</TITLE></HEAD>\ +<BODY>You are not authorized to access this page</BODY>\n<HTML>\n"; + +static const char *authorized_page = +"<HTML>\n<HEAD><TITLE>Authorized</TITLE></HEAD>\ +<BODY>Congratulations !</BODY>\n<HTML>\n"; + +static int AuthPage(cGH *cctkGH, httpRequest *request, void *data) +{ + int retval; + char message[1024]; + + int notauthorised; + + notauthorised = HTTP_AuthenticateBasic(request, "user"); + + if(!notauthorised) + { + strcpy(message,"HTTP/1.0 200 Ok\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"WWW-Authenticate: Basic realm=\"foo\"\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"Content-Type: text/html\r\n\r\n"); + + write(request->filedes, message, strlen(message)); + + write(request->filedes, authorized_page, strlen(authorized_page)); + } + else + { + strcpy(message,"HTTP/1.0 401 Unauthorized\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"WWW-Authenticate: Basic realm=\"foo\"\r\n"); + + write(request->filedes, message, strlen(message)); + + strcpy(message,"Content-Type: text/html\r\n\r\n"); + + write(request->filedes, message, strlen(message)); + + write(request->filedes, notauthorized_page, strlen(notauthorized_page)); + } + + return 0; +} diff --git a/src/Startup.c b/src/Startup.c index ef2b4ba..495de8b 100644 --- a/src/Startup.c +++ b/src/Startup.c @@ -48,7 +48,10 @@ int HTTP_Startup(void) { while(1) { - HTTP_Poll(NULL, 10000,0); + if(CCTK_MyProc(NULL) == 0) + { + HTTP_Poll(NULL, 10000,0); + } } } @@ -74,11 +77,14 @@ void HTTP_Work(CCTK_ARGUMENTS) DECLARE_CCTK_ARGUMENTS DECLARE_CCTK_PARAMETERS - HTTP_Poll(cctkGH, timeout_seconds, timeout_useconds); + if(CCTK_MyProc(cctkGH) == 0) + { + HTTP_Poll(cctkGH, timeout_seconds, timeout_useconds); + } } /*@@ - @routine HTTP_Startup + @routine HTTP_Shutdown @date Wed Sep 13 21:26:56 2000 @author Tom Goodale @desc @@ -93,7 +99,11 @@ void HTTP_Work(CCTK_ARGUMENTS) @@*/ int HTTP_Shutdown(void) { - HTTP_ShutdownServer(); + + if(CCTK_MyProc(NULL) == 0) + { + HTTP_ShutdownServer(); + } return 0; } diff --git a/src/Steer.c b/src/Steer.c new file mode 100644 index 0000000..3935ded --- /dev/null +++ b/src/Steer.c @@ -0,0 +1,370 @@ + /*@@ + @file Steer.c + @date Fri Sep 15 09:51:01 2000 + @author Tom Goodale + @desc + Parameter steering interface for the webserver. + Perhaps should make these required driver functions ? + @enddesc + @version $Header$ + @@*/ + +#ifndef TEST_HTTP_STEER +#include "cctk.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef CCTK_MPI +#include "mpi.h" +#endif + +#ifndef TEST_HTTP_STEER +#include "cctk_Parameter.h" +#endif + +#include "http_Steer.h" + +static char *rcsid = "$Header$"; + +#ifdef CCTK_FILEVERSION +CCTK_FILEVERSION(DevThorns_httpd_Steer_c) +#endif + +/******************************************************************** + ********************* Local Data Types *********************** + ********************************************************************/ + +/******************************************************************** + ********************* Local Routine Prototypes ********************* + ********************************************************************/ + +static int CommunicateBuffer(void); +static int SteerParameters(void); + +/******************************************************************** + ********************* Other Routine Prototypes ********************* + ********************************************************************/ + +/******************************************************************** + ********************* Local Data ***************************** + ********************************************************************/ + +static char *queuebuffer = NULL; +static int queuebuffer_size = 0; + +/******************************************************************** + ********************* External Routines ********************** + ********************************************************************/ + + /*@@ + @routine HTTP_SteerQueue + @date Fri Sep 15 09:52:13 2000 + @author Tom Goodale + @desc + Adds a paremeter and its new value to the queue to be steered. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int HTTP_SteerQueue(const char *thorn, const char *parameter, const char *value) +{ + int retval; + int buffer_length; + int parameter_length; + char *tmp; + + retval = 0; + + buffer_length = queuebuffer ? strlen(queuebuffer) : 0; + + /* Added length will be lengthof(thorn::par=val\n) */ + parameter_length=strlen(thorn) + 2 + strlen(parameter)+ 1 + strlen(value)+1; + + if(buffer_length+parameter_length+1 > queuebuffer_size) + { + tmp = (char *)realloc(queuebuffer, buffer_length+parameter_length+1); + + if(tmp) + { + queuebuffer = tmp; + retval = 0; + } + else + { + retval = -1; + } + } + + if(!retval) + { + sprintf(queuebuffer,"%s%s::%s=%s\n", queuebuffer,thorn,parameter, value); + } + + return retval; +} + + /*@@ + @routine HTTP_SteerDispatch + @date Fri Sep 15 09:58:07 2000 + @author Tom Goodale + @desc + + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +int HTTP_SteerDispatch(void) +{ + CommunicateBuffer(); + + SteerParameters(); + + return 0; +} + +/******************************************************************** + ********************* Local Routines ************************* + ********************************************************************/ + + /*@@ + @routine CommunicateBuffer + @date Fri Sep 15 10:22:11 2000 + @author Tom Goodale + @desc + Communicates the contents of the queue buffer to all procs. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static int CommunicateBuffer(void) +{ +#ifdef CCTK_MPI + int rank; + int nprocs; + int buffer_size; + + /* Work out how many processes there are. */ + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + + if(nprocs > 1) + { + /* Work out if this is proc 0 or not. */ + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + if(rank == 0) + { + /* Sending process */ + + /* How much data must we send. */ + buffer_size = queuebuffer ? strlen(queuebuffer) : 0; + + /* Now account for final \0 */ + if(buffer_size) + { + buffer_size++; + } + + /* Tell other procs how much data to receive. */ + MPI_Bcast(&buffer_size, 1, MPI_INT, 0, MPI_COMM_WORLD); + + if(buffer_size > 0) + { + /* Send data to other procs */ + MPI_Bcast(queuebuffer, buffer_size, MPI_BYTE, 0, MPI_COMM_WORLD); + } + } + else + { + /* Receiving process */ + + /* Find out how much data to receive. */ + MPI_Bcast(&buffer_size, 1, MPI_INT, 0, MPI_COMM_WORLD); + +#ifdef TEST_HTTP_STEER + fprintf(stderr, "%d - buffer size %d queuebuffer size %d\n", rank, buffer_size, queuebuffer_size); +#endif + + if(buffer_size > queuebuffer_size) + { + /* Don't use realloc, as don't need to copy data */ + if(queuebuffer) + { + free(queuebuffer); + } + + queuebuffer = (char *)malloc(buffer_size); + + if(!queuebuffer) + { + /* Have no choice except to abort as other processes would + block. + */ + MPI_Abort(MPI_COMM_WORLD, 99); + } + + queuebuffer_size = buffer_size; + } + + /* Receive data from processor 0 */ + + if(buffer_size > 0) + { + MPI_Bcast(queuebuffer, buffer_size, MPI_BYTE, 0, MPI_COMM_WORLD); + } + } + } + +#endif /* CCTK_MPI */ + + return 0; +} + + /*@@ + @routine SteerParameters + @date Fri Sep 15 10:38:40 2000 + @author Tom Goodale + @desc + Steers parameters from queuebuffer. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ +static int SteerParameters(void) +{ + int retval; + + char *token; + char *thorn; + char *parameter; + char *value; + + retval = 0; + + if(queuebuffer) + { + token = strtok(queuebuffer, "\n"); + + while(token) + { + thorn = token; + + parameter = strchr(token, ':'); + + if(parameter) + { + /* Get rid of two colons */ + *parameter = 0; + parameter++; + *parameter = 0; + parameter++; + + value = strchr(parameter,'='); + + if(value) + { + *value = 0; + value++; + + CCTK_ParameterSet(parameter, /* The name of the parameter */ + thorn, /* The originating thorn */ + value); /* The value of the parameter */ + + retval++; + } + } + token = strtok(NULL,"\n"); + } + } + + if(queuebuffer) + { + *queuebuffer = 0; + } + + return retval; +} + +#ifdef TEST_HTTP_STEER + +int CCTK_ParameterSet(char *parameter, char *thorn, char *value) +{ + int rank; + +#ifdef CCTK_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &rank); +#else + rank = 0; +#endif + + fprintf(stderr, "%d - %s::%s='%s'\n", rank, thorn, parameter, value); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + int rank; + char value[20]; + +#ifdef CCTK_MPI + MPI_Init(&argc, &argv); +#endif + +#ifdef CCTK_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &rank); +#else + rank = 0; +#endif + + for(i = 0; i < 6; i++) + { + if(rank == 0) + { + sprintf(value,"iter %d\n", i); + + switch(i) + { + case 3 : + case 5 : + HTTP_SteerQueue("a","b",value); + HTTP_SteerQueue("b","c",value); + HTTP_SteerQueue("c","d",value); + case 1 : + HTTP_SteerQueue("d","e",value); + HTTP_SteerQueue("e","f",value); + HTTP_SteerQueue("f","g",value); + default : + } + } + + HTTP_SteerDispatch(); + } + +#ifdef CCTK_MPI + MPI_Finalize(); +#endif + + return 0; +} + +#endif /* TEST_HTTP_STEER */ diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..cc9f13b --- /dev/null +++ b/src/base64.c @@ -0,0 +1,330 @@ + /*@@ + @file base64.c + @date 1995 + @author Various people, see below. + @desc + + @enddesc + @history + @hdate Fri Sep 15 14:32:47 2000 @hauthor Tom Goodale + @hdesc Put into the httpd thorn. + @endhistory + + @version $Header$ + @@*/ +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include <sys/types.h> + +#include <ctype.h> +#include <stdio.h> + +#include <stdlib.h> +#include <string.h> + +#define Assert(Cond) if (!(Cond)) abort() + +#include "base64.h" + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int HTTP_b64_ntop(unsigned char *src, size_t srclength, + char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int HTTP_b64_pton(const char *src, unsigned char *target, size_t targsize) +{ + size_t tarindex; + int state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ +#ifdef _LIBC + /* To avoid warnings. */ + for ( ; ch != '\0'; ch = *src++) +#else + for (NULL; ch != '\0'; ch = *src++) +#endif + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ +#ifdef _LIBC + /* To avoid warnings. */ + for ( ; ch != '\0'; ch = *src++) +#else + for (NULL; ch != '\0'; ch = *src++) +#endif + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..d466d28 --- /dev/null +++ b/src/base64.h @@ -0,0 +1,29 @@ + /*@@ + @header base64.h + @date Fri Sep 15 12:03:21 2000 + @author Tom Goodale + @desc + Header for base64 encoding stuff. + @enddesc + @version $Header$ + @@*/ + +#ifndef __BASE64_H__ +#define __BASE64_H__ 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +int HTTP_b64_ntop(unsigned char *src, size_t srclength, + char *target, size_t targsize); + +int HTTP_b64_pton(const char *src, unsigned char *target, size_t targsize); + +#ifdef __cplusplus +} +#endif + +#endif /* __BASE64_H__ */ + diff --git a/src/http_Auth.h b/src/http_Auth.h new file mode 100644 index 0000000..89442ec --- /dev/null +++ b/src/http_Auth.h @@ -0,0 +1,31 @@ + /*@@ + @header http_Auth.h + @date Fri Sep 15 13:20:01 2000 + @author Tom Goodale + @desc + + @enddesc + @version $Header$ + @@*/ + +#ifndef __HTTP_AUTH_H__ +#define __HTTP_AUTH_H__ 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +int HTTP_AuthAddUser(const char *database, + const char *name, + const char *password, + const char *encryption_scheme); + +int HTTP_AuthenticateBasic(httpRequest *request, + const char *database); + +#ifdef __cplusplus +} +#endif + +#endif /* __HTTP_AUTH_H__ */ diff --git a/src/http_Steer.h b/src/http_Steer.h new file mode 100644 index 0000000..3c02842 --- /dev/null +++ b/src/http_Steer.h @@ -0,0 +1,27 @@ + /*@@ + @header http_Steer.h + @date Fri Sep 15 11:31:04 2000 + @author Tom Goodale + @desc + Webserver parameter steering routines. + @enddesc + @version $Header$ + @@*/ + +#ifndef __HTTP_STEER_H__ +#define __HTTP_STEER_H__ 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +int HTTP_SteerQueue(const char *thorn, const char *parameter, const char *value); + +int HTTP_SteerDispatch(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __HTTP_STEER_H__ */ diff --git a/src/make.code.defn b/src/make.code.defn index a2f26b5..fcc4c5d 100644 --- a/src/make.code.defn +++ b/src/make.code.defn @@ -2,7 +2,18 @@ # $Header$ # Source files in this directory -SRCS = Startup.c Server.c Sockets.c http.c Content.c + +MISC_SRC = Startup.c + +SERVER_SRC = Server.c Sockets.c http.c + +CONTENT_SRC = Content.c + +STEERING_SRC = Steer.c + +AUTHENTICATION_SRC = Authorisation.c base64.c + +SRCS = $(MISC_SRC) $(SERVER_SRC) $(CONTENT_SRC) $(STEERING_SRC) $(AUTHENTICATION_SRC) # Subdirectories containing source files SUBDIRS = |