added auth stuff to ctx + demo for authentication layer

This commit is contained in:
overflowerror 2021-05-26 22:48:16 +02:00
parent f9670860df
commit d89225b614
9 changed files with 138 additions and 9 deletions

View file

@ -8,7 +8,7 @@ LIBARGO = libargo/libargo.a
LIBPARCIVAL = libparcival/libparcival.a
LIBS = $(CFLOOR_LIB) $(LIBARGO) $(LIBPARCIVAL)
OBJS = obj/router.o obj/request.o obj/base_cfloor.o obj/base_cgi.o
OBJS = obj/router.o obj/request.o obj/base_cfloor.o obj/base_cgi.o obj/auth.o obj/base64.o
DEPS = $(OBJS:%.o=%.d)
DEMO_OBJS = obj/demo.o obj/entities.tab.o obj/template.tab.o

View file

@ -1,5 +1,5 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <controller.h>
@ -18,6 +18,18 @@ response_t foobar(ctx_t ctx) {
}
response_t authenticate(ctx_t ctx) {
if (ctx.auth.type != BASIC) {
return basicAuthResponse(401, "Protected Area");
}
if (strcmp(ctx.auth.basic.user, "admin") != 0 ||
strcmp(ctx.auth.basic.password, "password") != 0
) {
// username or password wrong
return basicAuthResponse(401, "Protected Area");
}
return next();
}

65
src/auth.c Normal file
View file

@ -0,0 +1,65 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <headers.h>
#include "auth.h"
#include "base64.h"
struct auth getAuthData(struct headers* headers) {
struct auth auth = {
.type = NONE,
.basic = {
.user = NULL,
.password = NULL,
}
};
const char* header = headers_get(headers, "Authorization");
if (header == NULL) {
// no auth header
return auth;
}
if (strncmp(header, "Basic ", 6) != 0) {
// unsupported auth type
return auth;
}
header += 6;
while (*header == ' ') header++;
char* decoded = base64_decode(header);
if (decoded == NULL) {
// unable to parse base64
return auth;
}
char* username = decoded;
char* password = decoded;
while(*password != '\0' && *password != ':') password++;
if (*password == '\0') {
free(decoded);
// unable to parse credential string
return auth;
}
*password = '\0';
password++;
auth.type = BASIC;
auth.basic.user = username;
auth.basic.password = password;
return auth;
}
void freeAuthData(struct auth auth) {
if (auth.basic.user != NULL)
free(auth.basic.user);
// password should be freed with user;
}

25
src/auth.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef AUTH_H_
#define AUTH_H_
#include <stdbool.h>
#include <headers.h>
enum authType {
NONE,
BASIC
};
struct auth {
enum authType type;
struct {
char* user;
char* password;
} basic;
};
struct auth getAuthData(struct headers*);
void freeAuthData(struct auth);
#endif

View file

@ -11,7 +11,7 @@ static unsigned char inverseTable[256];
__attribute__((constructor)) static void buildInverseTable() {
memset(inverseTable, 0x80, 256);
size_t tableLength = strlen(charTable);
size_t tableLength = strlen((const char*) charTable);
for (unsigned int i = 0; i < tableLength; i++) {
inverseTable[charTable[i]] = i;
}
@ -52,10 +52,12 @@ char* base64_encode(const char* decoded) {
return encoded;
}
char* base64_decode(const char* encoded) {
size_t length = strlen(encoded);
char* base64_decode(const char* _encoded) {
size_t length = strlen(_encoded);
size_t count = 0;
unsigned const char* encoded = (unsigned char*) _encoded;
for (size_t i = 0; i < length; i++) {
if (inverseTable[encoded[i]] != 0x80) {
count++;

View file

@ -11,6 +11,7 @@
#include <logging.h>
#include "router.h"
#include "auth.h"
struct networkingConfig netConfig;
@ -20,13 +21,16 @@ static void handler(struct request request, struct response _response) {
path: request.metaData.path,
queryString: request.metaData.queryString,
peerAddr: request.peer.addr,
peerPort: request.peer.port
peerPort: request.peer.port,
auth: getAuthData(request.headers)
};
response_t response = routerHandler(ctx);
if (response.output == NULL) {
response = errorResponse(500, "route did not provide a reponse handler");
}
freeAuthData(ctx.auth);
int fd = _response.sendHeader(response.status, &response.headers, &request);
headers_free(&response.headers);

View file

@ -104,21 +104,24 @@ int main(int argc, char** argv) {
}
// TODO use request headers
headers_free(&headers);
ctx_t ctx = {
method: getMethod(or(getenv("REQUEST_METHOD"), "GET")),
path: or(getenv("PATH_INFO"), "/"),
queryString: or(getenv("QUERY_STRING"), ""),
peerAddr: or(getenv("REMOTE_ADDR"), ""),
peerPort: 0 // TODO
peerPort: 0, // TODO
auth: getAuthData(request.headers)
};
headers_free(&headers);
response_t response = routerHandler(ctx);
if (response.output == NULL) {
response = errorResponse(500, "route did not provide a reponse handler");
}
freeAuthData(ctx.auth);
printf("Status: %d\n\r", response.status);
headers_dump(&response.headers, stdout);

View file

@ -258,3 +258,17 @@ response_t next() {
response.status = NEXT_RESPONSE_STATUS;
return response;
}
response_t basicAuthResponse(int status, const char* realm) {
response_t response = emptyResponse();
response.status = status;
response._userData = "";
response.output = rawOutput;
size_t bufferLength = strlen(realm) + 14;
char buffer[bufferLength + 1];
snprintf(buffer, bufferLength + 1, "Basic realm=\"%s\"", realm);
headers_mod(&response.headers, "WWW-Authenticate", buffer);
return response;
}

View file

@ -7,6 +7,7 @@
#include <headers.h>
#include "common.h"
#include "auth.h"
#define NEXT_RESPONSE_STATUS (0)
@ -16,6 +17,7 @@ typedef struct {
const char* queryString;
const char* peerAddr;
int peerPort;
struct auth auth;
} ctx_t;
typedef struct {
@ -37,6 +39,8 @@ response_t emptyResponse();
response_t next();
response_t basicAuthResponse(int status, const char* realm);
response_t statusResponse(int status, const char* message);
response_t errorResponse(int status, const char* message);