From 7dd5244447a0e39c1c700e6b8b6f938c7f962ba8 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Sun, 18 Aug 2013 11:10:54 +0800 Subject: [PATCH] Update fastcgi testcode and add hashed password test code --- testing/fastcgi-approach/fastcgi.c | 61 ++++++------- testing/fastcgi-approach/fastcgi.h | 23 +++++ testing/fastcgi-approach/hashtest.c | 130 ++++++++++++++++++++++++++++ testing/fastcgi-approach/mctxserv | 50 +++++++++++ 4 files changed, 229 insertions(+), 35 deletions(-) create mode 100644 testing/fastcgi-approach/fastcgi.h create mode 100644 testing/fastcgi-approach/hashtest.c create mode 100644 testing/fastcgi-approach/mctxserv diff --git a/testing/fastcgi-approach/fastcgi.c b/testing/fastcgi-approach/fastcgi.c index c2444c8..298764d 100644 --- a/testing/fastcgi-approach/fastcgi.c +++ b/testing/fastcgi-approach/fastcgi.c @@ -2,23 +2,13 @@ * @file fastcgi.c * @purpose Runs the FCGI request loop to handle web interface requests. * - * should not be included, because these functions are handled by - * fcgi_stdio.h. If included, it must be included after fcgi_stdio.h. + * fcgi_stdio.h must be included before all else so the stdio function + * redirection works ok. */ #include -#include -#include - -/* - But the suggestion was: FunctionName, variable_name (local or member), - Structure, ENUMVALUE, Extern_FunctionName, g_global -*/ - -enum {STATUS_OK = 200, STATUS_BADREQUEST = 400, - STATUS_UNAUTHORIZED = 401}; - -typedef void (*ModuleHandler) (void *data, char *params); +#include "fastcgi.h" +//#include "common.h" /** * Extracts a key/value pair from a request string. @@ -59,7 +49,12 @@ char *FCGI_KeyPair(char *in, const char **key, const char **value) return ptr; } -void FCGI_BeginJSON(int status_code, const char *module) +/** + * Begins a response to the client in JSON format. + * @param status_code The HTTP status code to be returned. + * @param module The name of the module that initiated the response. + */ +void FCGI_BeginJSON(StatusCodes status_code, const char *module) { switch (status_code) { case STATUS_OK: @@ -75,29 +70,29 @@ void FCGI_BeginJSON(int status_code, const char *module) printf("\t\"module\" : \"%s\"", module); } +/** + * Adds a key/value pair to a JSON response. The response must have already + * been initiated by FCGI_BeginJSON. Note that characters are not escaped. + * @param key The key of the JSON entry + * ¶m value The value associated with the key. + */ void FCGI_BuildJSON(const char *key, const char *value) { printf(",\r\n\t\"%s\" : \"%s\"", key, value); } +/** + * Ends a JSON response that was initiated by FCGI_BeginJSON. + */ void FCGI_EndJSON() { printf("\r\n}\r\n"); } -static void SensorsHandler(void *data, char *params) -{ - const char *key, *value; - - //Begin a request only when you know the final result - //E.g whether OK or not. - FCGI_BeginJSON(STATUS_OK, "sensors"); - while ((params = FCGI_KeyPair(params, &key, &value))) { - FCGI_BuildJSON(key, value); - } - FCGI_EndJSON(); -} - +/** + * Main FCGI request loop that receives/responds to client requests. + * @param data A data field to be passed to the selected module handler. + */ void FCGI_RequestLoop (void *data) { int count = 0; @@ -116,9 +111,9 @@ void FCGI_RequestLoop (void *data) if (!strcmp("sensors", module)) { - module_handler = SensorsHandler; - } else if (!strcmp("admin", module)) { - //module_handler = AdminHandlerReplace with pointer to admin handler + //module_handler = Handler_Sensors; + } else if (!strcmp("actuators", module)) { + } if (module_handler) { @@ -138,7 +133,3 @@ void FCGI_RequestLoop (void *data) count++; } } - -int main(int argc, char *argv[]) { - FCGI_RequestLoop(NULL); -} diff --git a/testing/fastcgi-approach/fastcgi.h b/testing/fastcgi-approach/fastcgi.h new file mode 100644 index 0000000..4e0cda7 --- /dev/null +++ b/testing/fastcgi-approach/fastcgi.h @@ -0,0 +1,23 @@ +/** + * @file fastcgi.h + * @purpose Headers for the fastcgi web interface + */ + +#ifndef _FASTCGI_H +#define _FASTCGI_H + +/**HTTP status codes that fcgi module handlers can return**/ +typedef enum StatusCodes { + STATUS_OK = 200, + STATUS_BADREQUEST = 400, + STATUS_UNAUTHORIZED = 401 +} StatusCodes; + +typedef void (*ModuleHandler) (void *data, char *params); + +extern char *FCGI_KeyPair(char *in, const char **key, const char **value); +extern void FCGI_BeginJSON(StatusCodes status_code, const char *module); +extern void FCGI_BuildJSON(const char *key, const char *value); +extern void FCGI_EndJSON(); +extern void FCGI_RequestLoop (void *data); +#endif diff --git a/testing/fastcgi-approach/hashtest.c b/testing/fastcgi-approach/hashtest.c new file mode 100644 index 0000000..477f01e --- /dev/null +++ b/testing/fastcgi-approach/hashtest.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#define SALT_LENGTH 20 + +int ReadBytes(char *str, unsigned char *buffer, size_t buffer_length) { + unsigned i, val; + if (strlen(str) != buffer_length * 2) + return 0; + for (i = 0; i < buffer_length; i++) { + sscanf(str + i*2, "%2x", &val); + buffer[i] = (unsigned char) val; + } + return 1; +} + +unsigned char *HashPass(const char *pass, unsigned char salt[SALT_LENGTH]) { + unsigned char *buffer, *result; + size_t pass_length = strlen(pass); + size_t buffer_length = pass_length + SALT_LENGTH; + buffer = malloc(buffer_length * sizeof(unsigned char)); + if (!buffer) + return NULL; + + memcpy(buffer, pass, pass_length); + memcpy(buffer + pass_length, salt, SALT_LENGTH); + result = SHA1(buffer, buffer_length, NULL); + free(buffer); + + return result; +} + +int WriteUserPass(FILE *fp, const char *user, const char *pass) { + unsigned char salt[SALT_LENGTH], *sha1; + size_t i; + + FILE *fpr = fopen("/dev/urandom", "r"); + if (!fpr) + return 0; + fread(salt, sizeof(unsigned char), SALT_LENGTH, fpr); + fclose(fpr); + + if (!fp) + return 0; + + sha1 = HashPass(pass, salt); + if (!sha1) + return 0; + + fprintf(fp, "%s:", user); + for (i = 0; i < SALT_LENGTH; i++) { + fprintf(fp, "%02x", salt[i]); + } + fprintf(fp, "$"); + for (i = 0; i < 20; i++) { + fprintf(fp, "%02x", sha1[i]); + } + fprintf(fp, "\n"); + + return 1; +} + +int CheckUserPass(const char *passfile, const char *cuser, const char *cpass) { + FILE *fp = fopen(passfile, "r"); + char buffer[BUFSIZ]; + int ret = 0; + if (!fp) + return 0; + + while (fgets(buffer, BUFSIZ, fp)) { + char *user, *salt, *hash, *ptr; + + user = buffer; + ptr = strchr(buffer, ':'); + if (ptr) { + *ptr++ = 0; + salt = ptr; + ptr = strchr(ptr, '$'); + if (ptr) { + *ptr++ = 0; + hash = ptr; + ptr = strchr(ptr, '\n'); + if (ptr) + *ptr = 0; + + if (strlen(hash) != 20 * 2) { + printf("Invalid SHA-1 hash: %s\n", hash); + continue; + } else if (strlen(salt) != SALT_LENGTH * 2) { + printf("Invalid salt length: %s\n", salt); + continue; + } else if (strcmp(user, cuser)) { + continue; + } + + unsigned char saltbytes[SALT_LENGTH], hashbytes[20]; + ReadBytes(salt, saltbytes, SALT_LENGTH); + ReadBytes(hash, hashbytes, 20); + if (!memcmp(HashPass(cpass, saltbytes), hashbytes, 20)) { + printf("Matched with user: %s\n", cuser); + ret = 1; + break; + } + + } + } + } + + fclose(fp); + return ret; +} + +int main(int argc, char *argv[]) { + if (argc != 4) { + printf("Usage: %s user pass fname\n", argv[0]); + return 1; + } + + FILE *fp = fopen(argv[3], "w"); + + if (!WriteUserPass(fp, argv[1], argv[2])) { + fprintf(stderr, "Failed to hash: %s:%s\n", argv[1], argv[2]); + return 1; + } + fclose(fp); + + CheckUserPass(argv[3], argv[1], argv[2]); + return 0; +} diff --git a/testing/fastcgi-approach/mctxserv b/testing/fastcgi-approach/mctxserv new file mode 100644 index 0000000..969a338 --- /dev/null +++ b/testing/fastcgi-approach/mctxserv @@ -0,0 +1,50 @@ +#!/bin/bash + +USER=www-data +GROUP=www-data +HOST=127.0.0.1 +PORT=9005 + +CGI_NAME=/usr/bin/mctxserv +CGI_BASENAME=`basename $CGI_NAME` +PID=/var/run/$CGI_BASENAME.pid +DAEMON=/usr/bin/spawn-fcgi +DAEMON_BASENAME=`basename $DAEMON` +DAEMON_OPTS="-a $HOST -p $PORT -u $USER -g $GROUP -P $PID $CGI_NAME" + +#Test if daemon exists +[ -x "$DAEMON" ] || (echo $DAEMON doesn\'t exist! && exit 1) +#Test if cgi module exists +[ -x "$CGI_NAME" ] || (echo $CGI_BASENAME doesn\'t exist! && exit 1) + +start() { + echo -n "Starting FastCGI Daemon: " + start-stop-daemon --start --quiet --pidfile $PID \ + --exec $DAEMON -- $DAEMON_OPTS > /dev/null + RETVAL=$? + echo "$CGI_BASENAME." +} +stop() { + echo -n "Stopping FastCGI Daemon: " + start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $PID + RETVAL=$? + echo "$CGI_BASENAME." +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + *) + echo "Usage: mctxserv {start|stop|restart}" + exit 1 + ;; +esac +exit $RETVAL -- 2.20.1