From a6ae915f96e9769fc6f67deb4ddfaa7e6efcf464 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Sun, 18 Aug 2013 20:44:25 +0800 Subject: [PATCH] Add test main and update nginx config to have HTTP basic auth for api/login --- .../-etc-nginx/fastcgi_params | 1 + .../-etc-nginx/sites-enabled/default | 33 +++-- testing/fastcgi-approach/Makefile | 6 +- testing/fastcgi-approach/common.h | 20 +++ testing/fastcgi-approach/default | 126 ----------------- testing/fastcgi-approach/fastcgi.c | 63 ++++++++- testing/fastcgi-approach/hashtest.c | 130 ------------------ testing/fastcgi-approach/main.c | 50 +++++++ 8 files changed, 152 insertions(+), 277 deletions(-) create mode 100644 testing/fastcgi-approach/common.h delete mode 100644 testing/fastcgi-approach/default delete mode 100644 testing/fastcgi-approach/hashtest.c create mode 100644 testing/fastcgi-approach/main.c diff --git a/testing/fastcgi-approach/-etc-nginx/fastcgi_params b/testing/fastcgi-approach/-etc-nginx/fastcgi_params index ec905ca..51aa692 100644 --- a/testing/fastcgi-approach/-etc-nginx/fastcgi_params +++ b/testing/fastcgi-approach/-etc-nginx/fastcgi_params @@ -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; diff --git a/testing/fastcgi-approach/-etc-nginx/sites-enabled/default b/testing/fastcgi-approach/-etc-nginx/sites-enabled/default index b11b2e4..541f6d1 100644 --- a/testing/fastcgi-approach/-etc-nginx/sites-enabled/default +++ b/testing/fastcgi-approach/-etc-nginx/sites-enabled/default @@ -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; + } + } } diff --git a/testing/fastcgi-approach/Makefile b/testing/fastcgi-approach/Makefile index 03be42f..61b7c40 100644 --- a/testing/fastcgi-approach/Makefile +++ b/testing/fastcgi-approach/Makefile @@ -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 index 0000000..0777772 --- /dev/null +++ b/testing/fastcgi-approach/common.h @@ -0,0 +1,20 @@ +/** + * @file common.h + * @purpose Common header includes + */ + +#ifndef _COMMON_H +#define _COMMON_H + +#include +#include +#include +#include +#include +#include +#include + +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 index b11b2e4..0000000 --- a/testing/fastcgi-approach/default +++ /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; -# } -#} diff --git a/testing/fastcgi-approach/fastcgi.c b/testing/fastcgi-approach/fastcgi.c index 298764d..a518c7a 100644 --- a/testing/fastcgi-approach/fastcgi.c +++ b/testing/fastcgi-approach/fastcgi.c @@ -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 +#include #include "fastcgi.h" -//#include "common.h" +#include "common.h" +#include + +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(×tamp)); + 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 index 477f01e..0000000 --- a/testing/fastcgi-approach/hashtest.c +++ /dev/null @@ -1,130 +0,0 @@ -#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/main.c b/testing/fastcgi-approach/main.c new file mode 100644 index 0000000..f5f7ae3 --- /dev/null +++ b/testing/fastcgi-approach/main.c @@ -0,0 +1,50 @@ +#define _BSD_SOURCE +#include "common.h" +#include "fastcgi.h" +#include + +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); +} -- 2.20.1