Update fastcgi testcode and add hashed password test code
authorJeremy Tan <[email protected]>
Sun, 18 Aug 2013 03:10:54 +0000 (11:10 +0800)
committerJeremy Tan <[email protected]>
Sun, 18 Aug 2013 03:10:54 +0000 (11:10 +0800)
testing/fastcgi-approach/fastcgi.c
testing/fastcgi-approach/fastcgi.h [new file with mode: 0644]
testing/fastcgi-approach/hashtest.c [new file with mode: 0644]
testing/fastcgi-approach/mctxserv [new file with mode: 0644]

index c2444c8..298764d 100644 (file)
@@ -2,23 +2,13 @@
  * @file fastcgi.c
  * @purpose Runs the FCGI request loop to handle web interface requests.
  * 
- * <stdio.h> 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 <fcgi_stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-/*
-       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
+ * &param 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 (file)
index 0000000..4e0cda7
--- /dev/null
@@ -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 (file)
index 0000000..477f01e
--- /dev/null
@@ -0,0 +1,130 @@
+#include <openssl/sha.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..969a338
--- /dev/null
@@ -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

UCC git Repository :: git.ucc.asn.au