Skip to content
This repository has been archived by the owner on Jan 19, 2021. It is now read-only.

Commit

Permalink
Added interface pages authorization
Browse files Browse the repository at this point in the history
Fixed base64 functions
  • Loading branch information
TETYYS committed Jul 9, 2015
1 parent 4617e2d commit aa03414
Show file tree
Hide file tree
Showing 15 changed files with 569 additions and 162 deletions.
11 changes: 8 additions & 3 deletions Base64.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>

size_t MEM_OUT Base64Encode(const unsigned char* buffer, size_t length, char** b64text) {
// outputs with NUL
BIO *bio, *b64;
BUF_MEM *bufferPtr;

Expand All @@ -23,7 +25,8 @@ size_t MEM_OUT Base64Encode(const unsigned char* buffer, size_t length, char** b
BIO_set_close(bio, BIO_NOCLOSE);
BIO_free_all(bio);

*b64text = bufferPtr->data;
*b64text = realloc(bufferPtr->data, bufferPtr->length + 1); // HACK HACK oops
(*b64text)[bufferPtr->length] = 0x00;
return bufferPtr->length;
}

Expand All @@ -39,7 +42,7 @@ static size_t CalcDecodeLength(const char* b64input) {
return (len * 3) / 4 - padding;
}

int MEM_OUT Base64Decode(char* b64message, unsigned char** buffer, size_t* length) {
bool MEM_OUT Base64Decode(char* b64message, unsigned char** buffer, size_t* length) {
BIO *bio, *b64;

int decodeLen = CalcDecodeLength(b64message);
Expand All @@ -52,8 +55,10 @@ int MEM_OUT Base64Decode(char* b64message, unsigned char** buffer, size_t* lengt

BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
*length = BIO_read(bio, *buffer, strlen(b64message));
if (*length != decodeLen)
if (*length != decodeLen) {
free(*buffer);
return false;
}
BIO_free_all(bio);

return true;
Expand Down
3 changes: 2 additions & 1 deletion Base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "Global.h"
#include <stddef.h>
#include <stdbool.h>

size_t MEM_OUT Base64Encode(const unsigned char* buffer, size_t length, char** b64text);
int MEM_OUT Base64Decode(char* b64message, unsigned char** buffer, size_t* length);
bool MEM_OUT Base64Decode(char* b64message, unsigned char** buffer, size_t* length);
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ project (LIVEPROXIES)

set (CMAKE_C_FLAGS "--std=c99 -pthread ${CMAKE_C_FLAGS}")

add_executable(LiveProxies Base64.c Global.c Harvester.c Interface.c IPv6Map.c LiveProxies.c Logger.c ProxyLists.c ProxyRemove.c ProxyRequest.c WServer.c)
add_executable(LiveProxies Base64.c Global.c Harvester.c Interface.c IPv6Map.c LiveProxies.c Logger.c ProxyLists.c ProxyRemove.c ProxyRequest.c WServer.c PBKDF2.c)
target_link_libraries(LiveProxies event GeoIP crypto python2.7 pcre config m util)
3 changes: 2 additions & 1 deletion Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ uint16_t ServerPort;
uint64_t SimultaneousChecks;
IPv6Map *GlobalIp;
char *HarvestersPath;
bool DisableIPv6;
bool DisableIPv6;
uint64_t AuthLoginExpiry;
11 changes: 10 additions & 1 deletion IPv6Map.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ MEM_OUT char *IPv6MapToString2(IPv6Map *In) {

MEM_OUT struct sockaddr *IPv6MapToRaw(IPv6Map *In, uint16_t Port) {
if (GetIPType(In) == IPV4) {
struct sockaddr_in *sin = calloc(1, sizeof(struct sockaddr_in)); // change to struct sockaddr if doesn't work
struct sockaddr_in *sin = calloc(1, sizeof(struct sockaddr_in));
*((uint32_t*)(&(sin->sin_addr.s_addr))) = In->Data[3];
sin->sin_family = AF_INET;
sin->sin_port = htons(Port);
Expand Down Expand Up @@ -121,4 +121,13 @@ MEM_OUT IPv6Map *GetIPFromHSock(int hSock) {
}

return ret;
}

bool IPv6MapCompare(IPv6Map *a, IPv6Map *b) {
IPV6_TYPE type;
if (GetIPType(a) != GetIPType(b))
return false;
type = GetIPType(a);

return memcmp(a->Data, b->Data, type == IPV4 ? IPV4_SIZE : IPV6_SIZE) == 0;
}
4 changes: 3 additions & 1 deletion IPv6Map.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <stdint.h>
#include <stdbool.h>
#include "Global.h"

typedef enum _IPV6_TYPE {
Expand All @@ -22,4 +23,5 @@ char *IPv6MapToString(IPv6Map *In);
char *IPv6MapToString2(IPv6Map *In);
IPV6_TYPE GetIPType(IPv6Map *In);
IPv6Map *GetIPFromHSock(int hSock);
struct sockaddr *IPv6MapToRaw(IPv6Map *In, uint16_t Port);
struct sockaddr *IPv6MapToRaw(IPv6Map *In, uint16_t Port);
bool IPv6MapCompare(IPv6Map *a, IPv6Map *b);
192 changes: 188 additions & 4 deletions Interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,186 @@
#include "Global.h"
#include "Logger.h"
#include "Config.h"
#include "Base64.h"
#include "PBKDF2.h"
#include <event2/buffer.h>
#include <stdlib.h>

bool AuthVerify(struct evhttp_request *evRequest) {
if (AuthLocalList == NULL)
return true; // Pass through all users if auth list is empty

struct evkeyvalq *headers = evhttp_request_get_input_headers(evRequest);
struct evkeyval *header;

for (header = headers->tqh_first; header; header = header->next.tqe_next) {
/* Authorize by login */ {
char *username, *password;
char *authStr;

if (strcmp(header->key, "Authorization") != 0)
continue;

/* Resolve username:password from authorization header */ {
char *authStrb64 = strstr(header->value, "Basic ") + (sizeof(char)* 6);
if (authStrb64 == (sizeof(char)* 6))
return false;

size_t trash;
if (!Base64Decode(authStrb64, &authStr, &trash))
return false;


char *delimiterIndex = strchr(authStr, ':');

if (delimiterIndex == NULL) {
free(authStr);
return false;
}

password = delimiterIndex + (1 * sizeof(char));
*delimiterIndex = 0x00; // Are we allowed to modify inputted headers by evhttp???
username = authStr;
}

sem_wait(&AuthLocalLock); {
for (size_t x = 0; x < AuthLocalCount; x++) {
if (strcmp(AuthLocalList[x]->username, username) != 0)
continue;

char *saltb64;
uint8_t *salt;
size_t saltLen;
char *firstDelimiter = strchr(AuthLocalList[x]->password, '$');
char *secondDelimiter = strchr(firstDelimiter + (1 * sizeof(char)), '$');

size_t iterations = atoll(AuthLocalList[x]->password);
size_t saltb64Len = (secondDelimiter - (firstDelimiter + 1)) * (sizeof(char));

saltb64 = malloc(saltb64Len + 1 /* NUL */); {
memcpy(saltb64, firstDelimiter + (1 * sizeof(char)), saltb64Len);
saltb64[saltb64Len] = 0x00;
Base64Decode(saltb64, &salt, &saltLen);
} free(saltb64);

char *pbkdf2 = PBKDF2_HMAC_SHA_512Ex(password, strlen(password), salt, saltLen, iterations); // TODO: Possible DoS, needs login limit
free(salt);

if (strcmp(AuthLocalList[x]->password, pbkdf2) == 0) {
free(pbkdf2);

sem_wait(&AuthWebLock); {
char *sIp;
uint16_t port;
evhttp_connection_get_peer(evhttp_request_get_connection(evRequest), &sIp, &port);

for (size_t x = 0; x < AuthWebCount; x++) {
IPv6Map *ip = StringToIPv6Map(sIp); {
if (IPv6MapCompare(ip, AuthWebList[x]->ip)) {
free(ip);
if (AuthWebList[x]->expiry >(GetUnixTimestampMilliseconds() / 1000)) {
sem_post(&AuthLocalLock);
sem_post(&AuthWebLock);
return true;
} else {
free(AuthWebList[x]->username);
free(AuthWebList[x]->rndVerify);
free(AuthWebList[x]->ip);
free(AuthWebList[x]);
AuthWebList[x] = AuthWebList[AuthWebCount];

sem_post(&AuthLocalLock);
sem_post(&AuthWebLock);
return false; // Auth expired
}
}
} free(ip);
}

if (AuthWebList == NULL)
AuthWebList = malloc(++AuthWebCount * sizeof(AuthWebList));

AuthWebList[AuthWebCount - 1] = malloc(sizeof(AUTH_WEB));
AuthWebList[AuthWebCount - 1]->expiry = (GetUnixTimestampMilliseconds() / 1000) + AuthLoginExpiry;
AuthWebList[AuthWebCount - 1]->username = malloc(strlen(username) + 1 /* NUL */);
AuthWebList[AuthWebCount - 1]->ip = StringToIPv6Map(sIp);
strcpy(AuthWebList[AuthWebCount - 1]->username, username);

free(authStr); // invalidates username and password from headers

uint8_t randBytes[64];
RAND_pseudo_bytes(randBytes, 64);
size_t b64VerifyLen = Base64Encode(randBytes, 64, &(AuthWebList[AuthWebCount - 1]->rndVerify));

char *cookieFormat = malloc(((7 + b64VerifyLen) * sizeof(char)) + 1 /* NUL */); {
sprintf(cookieFormat, "LPAuth=%s", AuthWebList[AuthWebCount - 1]->rndVerify);
evhttp_add_header(evhttp_request_get_output_headers(evRequest), "Set-Cookie", cookieFormat);
} free(cookieFormat);
} sem_post(&AuthWebLock);

sem_post(&AuthLocalLock);
return true;
}
else
free(pbkdf2);
}
} sem_post(&AuthLocalLock);

free(authStr);
} /* End authorize by login */

/* Authorize by cookie */ {
if (AuthWebList == NULL)
return false;
if (strcmp(header->key, "Cookie") != 0)
continue;

char *lpAuth; // not this is not long pointer
char *cookieLpAuth = strstr(header->value, "LPAuth");

if (cookieLpAuth != NULL) {
char *cookieDelimiter = strchr(cookieLpAuth, '=');
if (cookieDelimiter == NULL)
return false;

cookieDelimiter = 0x00; // Are we allowed to modify inputted headers by evhttp???
lpAuth = cookieDelimiter + 1;
char *nextCookie = strchr(lpAuth, ';');
if (nextCookie != NULL)
nextCookie = 0x00; // Are we allowed to modify inputted headers by evhttp???

sem_wait(&AuthWebLock); {
for (size_t x = 0; x < AuthWebCount; x++) {
if (strcmp(AuthWebList[x]->rndVerify, lpAuth) == 0) {
if (AuthWebList[x]->expiry >(GetUnixTimestampMilliseconds() / 1000))
return true;
else {
free(AuthWebList[x]->username);
free(AuthWebList[x]->rndVerify);
free(AuthWebList[x]->ip);
free(AuthWebList[x]);
AuthWebList[x] = AuthWebList[AuthWebCount];
return false; // Auth token expired
}
}
}
} sem_post(&AuthWebLock);
}
} /* End authorize by cookie */
}

return false;
}

void InterfaceWeb(struct evhttp_request *evRequest, void *arg) {
if (!AuthVerify(evRequest)) {
evhttp_add_header(evhttp_request_get_output_headers(evRequest), "WWW-Authenticate", "Basic realm=\""HTTP_AUTHORIZATION_REALM"\"");
struct evbuffer *buff = evbuffer_new(); {
evbuffer_add_reference(buff, "Not Authorized", 14, NULL, NULL);
evhttp_send_reply(evRequest, 401 /* Forbidden */, "Not Authorized", buff);
} evbuffer_free(buff);
return;
}
struct evbuffer *buff = evbuffer_new(); {
evbuffer_add_printf(buff, "<html><head><title>LiveProxies %s interface: Checked proxies</title></head><body>", VERSION);

Expand Down Expand Up @@ -39,6 +215,14 @@ static void IntBlock3(size_t In, size_t *Out1, size_t *Out2) {
}

void InterfaceWebUnchecked(struct evhttp_request *evRequest, void *arg) {
if (!AuthVerify(evRequest)) {
evhttp_add_header(evhttp_request_get_output_headers(evRequest), "WWW-Authenticate", "Basic realm=\""HTTP_AUTHORIZATION_REALM"\"");
struct evbuffer *buff = evbuffer_new(); {
evbuffer_add_reference(buff, "Not Authorized", 14, NULL, NULL);
evhttp_send_reply(evRequest, 401 /* Forbidden */, "Not Authorized", buff);
} evbuffer_free(buff);
return;
}
struct evbuffer *buff = evbuffer_new(); {
evbuffer_add_printf(buff, "<html><head><title>LiveProxies %s interface: Unchecked proxies</title></head><body>", VERSION);

Expand Down Expand Up @@ -83,19 +267,19 @@ void InterfaceWebUnchecked(struct evhttp_request *evRequest, void *arg) {
timeinfo = localtime(&timeRaw);
strftime(timeBuff, 20, "%F %H:%M:%S", timeinfo);
//evbuffer_add_reference(buff, ", requestTime: ", 15, NULL, NULL);
//evbuffer_add_reference(buff, timeBuff, 20, NULL, NULL);
evbuffer_add_printf(buff, ", requestTime: %s", timeBuff);*
}
if (uncheckedProxies[x]->requestTimeHttpMs != 0) {
}
if (uncheckedProxies[x]->requestTimeHttpMs != 0) {
/*timeRaw = uncheckedProxies[x]->requestTimeHttpMs / 1000;
localtime_r(&timeRaw, timeinfo);
strftime(timeBuff, 20, "%F %H:%M:%S", timeinfo);
evbuffer_add_printf(buff, ", requestTimeHttp: %s", timeBuff);*
}*/
}*/

if (lockVal == LOCK_BLOCKED)
evbuffer_add_reference(buff, " <b>PROCESSING</b>", 18, NULL, NULL);
Expand Down
24 changes: 24 additions & 0 deletions Interface.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
#pragma once

#include <evhttp.h>
#include <semaphore.h>
#include "IPv6Map.h"

#define HTTP_AUTHORIZATION_REALM "Live Proxies interface - private access"

typedef struct _AUTH_WEB {
char *username;
char *rndVerify;
uint64_t expiry;
IPv6Map *ip;
} AUTH_WEB;

typedef struct _AUTH_LOCAL {
char *username;
char *password;
} AUTH_LOCAL;

sem_t AuthWebLock;
AUTH_WEB **AuthWebList;
size_t AuthWebCount;

sem_t AuthLocalLock;
AUTH_LOCAL **AuthLocalList;
size_t AuthLocalCount;

void InterfaceWeb(struct evhttp_request *evRequest, void *arg);
void InterfaceWebUnchecked(struct evhttp_request *evRequest, void *arg);
Loading

0 comments on commit aa03414

Please sign in to comment.