Add test main and update nginx config to have HTTP basic auth for api/login
authorJeremy Tan <[email protected]>
Sun, 18 Aug 2013 12:44:25 +0000 (20:44 +0800)
committerJeremy Tan <[email protected]>
Sun, 18 Aug 2013 12:44:25 +0000 (20:44 +0800)
testing/fastcgi-approach/-etc-nginx/fastcgi_params
testing/fastcgi-approach/-etc-nginx/sites-enabled/default
testing/fastcgi-approach/Makefile
testing/fastcgi-approach/common.h [new file with mode: 0644]
testing/fastcgi-approach/default [deleted file]
testing/fastcgi-approach/fastcgi.c
testing/fastcgi-approach/hashtest.c [deleted file]
testing/fastcgi-approach/main.c [new file with mode: 0644]

index ec905ca..51aa692 100644 (file)
@@ -16,6 +16,7 @@ fastcgi_param SERVER_HOSTNAME         mctxsoft;
 
 fastcgi_param  REMOTE_ADDR             $remote_addr;
 fastcgi_param  REMOTE_PORT             $remote_port;
+fastcgi_param  REMOTE_USER             $remote_user;
 fastcgi_param  SERVER_ADDR             $server_addr;
 fastcgi_param  SERVER_PORT             $server_port;
 fastcgi_param  SERVER_NAME             $server_name;
index b11b2e4..541f6d1 100644 (file)
@@ -35,14 +35,6 @@ server {
                # include /etc/nginx/naxsi.rules
        }
 
-       location /doc/ {
-               alias /usr/share/doc/;
-               autoindex on;
-               allow 127.0.0.1;
-               allow ::1;
-               deny all;
-       }
-
        # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
        #location /RequestDenied {
        #       proxy_pass http://127.0.0.1:8080;    
@@ -77,12 +69,25 @@ server {
        location ~ /\.ht {
                deny all;
        }
-
-        location ~ ^/api/?([^?]*) {
-                fastcgi_pass 127.0.0.1:9005;
-                fastcgi_param DOCUMENT_URI_LOCAL $1;
-                include fastcgi_params;
-        }
+       
+       #Login area
+       location ^~ /api/login {
+               auth_basic "Restricted Access";
+               auth_basic_user_file /usr/share/nginx/access/.htpasswd;
+       
+               fastcgi_pass 127.0.0.1:9005;
+               fastcgi_param DOCUMENT_URI_LOCAL login;
+               include fastcgi_params;
+       }
+       
+       #MCTX API
+       location /api {
+               location ~ ^/api/?([^?]*) {
+                       fastcgi_pass 127.0.0.1:9005;
+                       fastcgi_param DOCUMENT_URI_LOCAL $1;
+                       include fastcgi_params;
+               }
+       }
 }
 
 
index 03be42f..61b7c40 100644 (file)
@@ -1,7 +1,7 @@
-CXX = gcc
+CXX = clang
 FLAGS = -std=c99 -Wall -Werror -pedantic -g
-LIB = -lpthread -lfcgi
-OBJ = fastcgi.o
+LIB = -lpthread -lfcgi -lcrypto
+OBJ = main.o fastcgi.o
 RM = rm -f
 
 BIN = fast
diff --git a/testing/fastcgi-approach/common.h b/testing/fastcgi-approach/common.h
new file mode 100644 (file)
index 0000000..0777772
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * @file common.h
+ * @purpose Common header includes
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+
+extern void Handler_Sensors(void *data, char *params);
+
+#endif //_COMMON_H
+
diff --git a/testing/fastcgi-approach/default b/testing/fastcgi-approach/default
deleted file mode 100644 (file)
index b11b2e4..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-# You may add here your
-# server {
-#      ...
-# }
-# statements for each of your virtual hosts to this file
-
-##
-# You should look at the following URL's in order to grasp a solid understanding
-# of Nginx configuration files in order to fully unleash the power of Nginx.
-# http://wiki.nginx.org/Pitfalls
-# http://wiki.nginx.org/QuickStart
-# http://wiki.nginx.org/Configuration
-#
-# Generally, you will want to move this file somewhere, and start with a clean
-# file but keep this around for reference. Or just disable in sites-enabled.
-#
-# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
-##
-
-server {
-       listen 80;
-       listen [::]:80 default_server ipv6only=on;
-
-       root /usr/share/nginx/html;
-       index index.php index.html index.htm;
-
-       # Make site accessible from http://localhost/
-       server_name localhost;
-
-       location / {
-               # First attempt to serve request as file, then
-               # as directory, then fall back to displaying a 404.
-               try_files $uri $uri/ =404;
-               # Uncomment to enable naxsi on this location
-               # include /etc/nginx/naxsi.rules
-       }
-
-       location /doc/ {
-               alias /usr/share/doc/;
-               autoindex on;
-               allow 127.0.0.1;
-               allow ::1;
-               deny all;
-       }
-
-       # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
-       #location /RequestDenied {
-       #       proxy_pass http://127.0.0.1:8080;    
-       #}
-
-       #error_page 404 /404.html;
-
-       # redirect server error pages to the static page /50x.html
-       #
-       #error_page 500 502 503 504 /50x.html;
-       #location = /50x.html {
-       #       root /usr/share/nginx/html;
-       #}
-
-       # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
-       #
-       location ~ \.php$ {
-               fastcgi_split_path_info ^(.+\.php)(/.+)$;
-       #       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
-       #
-       #       # With php5-cgi alone:
-       #       fastcgi_pass 127.0.0.1:9000;
-       #       # With php5-fpm:
-               fastcgi_pass unix:/var/run/php5-fpm.sock;
-               fastcgi_index index.php;
-               include fastcgi_params;
-       }
-
-       # deny access to .htaccess files, if Apache's document root
-       # concurs with nginx's one
-       #
-       location ~ /\.ht {
-               deny all;
-       }
-
-        location ~ ^/api/?([^?]*) {
-                fastcgi_pass 127.0.0.1:9005;
-                fastcgi_param DOCUMENT_URI_LOCAL $1;
-                include fastcgi_params;
-        }
-}
-
-
-# another virtual host using mix of IP-, name-, and port-based configuration
-#
-#server {
-#      listen 8000;
-#      listen somename:8080;
-#      server_name somename alias another.alias;
-#      root html;
-#      index index.html index.htm;
-#
-#      location / {
-#              try_files $uri $uri/ =404;
-#      }
-#}
-
-
-# HTTPS server
-#
-#server {
-#      listen 443;
-#      server_name localhost;
-#
-#      root html;
-#      index index.html index.htm;
-#
-#      ssl on;
-#      ssl_certificate cert.pem;
-#      ssl_certificate_key cert.key;
-#
-#      ssl_session_timeout 5m;
-#
-#      ssl_protocols SSLv3 TLSv1;
-#      ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
-#      ssl_prefer_server_ciphers on;
-#
-#      location / {
-#              try_files $uri $uri/ =404;
-#      }
-#}
index 298764d..a518c7a 100644 (file)
@@ -1,14 +1,65 @@
 /**
  * @file fastcgi.c
  * @purpose Runs the FCGI request loop to handle web interface requests.
- * 
+ *
  * fcgi_stdio.h must be included before all else so the stdio function
  * redirection works ok.
  */
+
 #include <fcgi_stdio.h>
+#include <openssl/sha.h>
 #include "fastcgi.h"
-//#include "common.h"
+#include "common.h"
+#include <time.h>
+
+static void LoginHandler(void *data, char *params) {
+       static char loginkey[41] = {0}, ip[256];
+       static time_t timestamp = 0;
+       const char *key, *value;
+       int force = 0, end = 0;
+
+       while ((params = FCGI_KeyPair(params, &key, &value))) {
+               if (!strcmp(key, "force"))
+                       force = !force;
+               else if (!strcmp(key, "end"))
+                       end = !end;
+       }
+
+       if (end) {
+               *loginkey = 0;
+               FCGI_BeginJSON(200, "login");
+               FCGI_EndJSON();
+               return;
+       }
+
+       time_t now = time(NULL);
+       if (force || !*loginkey || (now - timestamp > 180)) {
+               SHA_CTX sha1ctx;
+               unsigned char sha1[20];
+               int i = rand();
+
+               SHA1_Init(&sha1ctx);
+               SHA1_Update(&sha1ctx, &now, sizeof(now));
+               SHA1_Update(&sha1ctx, &i, sizeof(i));
+               SHA1_Final(sha1, &sha1ctx);
+
+               timestamp = now;
+               for (i = 0; i < 20; i++)
+                       sprintf(loginkey+i*2, "%02x", sha1[i]);
+               sprintf(ip, "%s", getenv("REMOTE_ADDR"));
+               FCGI_BeginJSON(200, "login");
+               FCGI_BuildJSON("key", loginkey);
+               FCGI_EndJSON();
+       } else {
+               char buf[128];
+               strftime(buf, 128, "%H:%M:%S %d-%m-%Y",localtime(&timestamp)); 
+               FCGI_BeginJSON(401, "login");
+               FCGI_BuildJSON("description", "Already logged in");
+               FCGI_BuildJSON("user", ip); 
+               FCGI_BuildJSON("time", buf);
+               FCGI_EndJSON();
+       }
+}
 
 /**
  * Extracts a key/value pair from a request string.
@@ -111,7 +162,9 @@ void FCGI_RequestLoop (void *data)
                
 
                if (!strcmp("sensors", module)) {
-                       //module_handler = Handler_Sensors;
+                       module_handler = Handler_Sensors;
+               } else if (!strcmp("login", module)) {
+                       module_handler = LoginHandler;
                } else if (!strcmp("actuators", module)) {
                        
                }
@@ -127,6 +180,8 @@ void FCGI_RequestLoop (void *data)
                        FCGI_BuildJSON("request-number", buf);
                        FCGI_BuildJSON("params", params);
                        FCGI_BuildJSON("host", getenv("SERVER_HOSTNAME"));
+                       FCGI_BuildJSON("user", getenv("REMOTE_USER"));
+                       FCGI_BuildJSON("userip", getenv("REMOTE_ADDR"));
                        FCGI_EndJSON();
                }
 
diff --git a/testing/fastcgi-approach/hashtest.c b/testing/fastcgi-approach/hashtest.c
deleted file mode 100644 (file)
index 477f01e..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-#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/main.c b/testing/fastcgi-approach/main.c
new file mode 100644 (file)
index 0000000..f5f7ae3
--- /dev/null
@@ -0,0 +1,50 @@
+#define _BSD_SOURCE
+#include "common.h"
+#include "fastcgi.h"
+#include <time.h>
+
+typedef struct Data {
+       pthread_t sensors;
+       pthread_mutex_t mutex;
+       volatile int sensor_value;
+} Data;
+
+void Handler_Sensors(void *arg, char *params) 
+{
+       const char *key, *value;
+       char buf[5];
+       Data *data = (Data*) arg;
+       
+       //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);
+       }
+       pthread_mutex_lock(&(data->mutex));
+       snprintf(buf, 128, "%d", data->sensor_value);
+       FCGI_BuildJSON("sensor_value", buf); 
+       pthread_mutex_unlock(&(data->mutex));
+       FCGI_EndJSON();
+}
+
+void *SensorsLoop(void *arg) {
+       Data *data = (Data*) arg;
+       srand(time(NULL));
+       //Csection
+       while(1) {
+               pthread_mutex_lock(&(data->mutex));
+               data->sensor_value = rand() % 1024;
+               pthread_mutex_unlock(&(data->mutex));
+               usleep(200*1000); //200ms
+       }
+}
+
+int main(int argc, char *argv[]) {
+       Data data = {0};
+       pthread_mutex_init(&(data.mutex), NULL);
+       //data.mutex = PTHREAD_MUTEX_INITIALIZER;
+       
+//     pthread_create(&data.sensors, NULL, SensorsLoop, &data);
+       FCGI_RequestLoop(&data);
+}

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