SpriteHTTPD - embedded HTTP server with read-only filesystem and templating, originally developed for ESP8266, now stand-alone and POSIX compatible.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
spritehttpd/spritehttpd/src/httpd-auth.c

101 lines
3.2 KiB

/*
HTTP auth implementation. Only does basic authentication for now.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "httpd-auth.h"
#include "httpd.h"
#include "utils/base64.h"
#include <ctype.h>
// base64 increases length by about 33%
#define BA_HDRBUFLEN ((AUTH_MAX_USER_LEN + AUTH_MAX_PASS_LEN + 2) * 2)
httpd_cgi_state cgiAuthBasic(HttpdConnData *connData)
{
int r;
char hdr[BA_HDRBUFLEN]; // +2 because of the terminator + colon ?
if (connData->conn == NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
r = httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr));
if (r && strncmp(hdr, "Basic", 5) == 0) {
const char *token = hdr + 5;
// discard leading whitepsace
while (isspace(*token)) {
token++;
}
r = httpd_base64_decode(strlen(token), token, BA_HDRBUFLEN, (uint8_t *) hdr); // Decoding in-place
if (r < 0) { r = 0; } //just clean out string on decode error
hdr[r] = 0; //zero-terminate user:pass string
char * colon_ptr = strchr(hdr, ':');
if (colon_ptr) {
*colon_ptr = 0; // null-terminate username
colon_ptr++;
if (((HttpdBasicAuthCb) (connData->cgiArg))(connData, hdr, colon_ptr)) {
return HTTPD_CGI_AUTHENTICATED;
}
}
}
//Not authenticated. Go bug user with login screen.
httpdStartResponse(connData, 401);
httpdHeader(connData, "Content-Type", "text/plain");
httpdHeader(connData, "WWW-Authenticate", "Basic realm=\""HTTP_AUTH_REALM"\"");
httpdEndHeaders(connData);
httpdSendStr(connData, "401 Unauthorized.");
//Okay, all done.
return HTTPD_CGI_DONE;
}
httpd_cgi_state cgiAuthBearer(HttpdConnData *connData)
{
int r;
char hdr[AUTH_MAX_TOKEN_LEN + 1];
if (connData->conn == NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
r = httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr));
if (r && strncmp(hdr, "Bearer", 6) == 0) {
// Don't base64-decode, token may not be encoded!
hdr[AUTH_MAX_TOKEN_LEN] = 0; //zero-terminate
char *token = hdr + 6;
// discard leading whitepsace
while (isspace(*token)) {
token++;
}
if (((HttpdBearerAuthCb) (connData->cgiArg))(connData, token)) {
return HTTPD_CGI_AUTHENTICATED;
}
}
//Not authenticated. Go bug user with login screen.
httpdStartResponse(connData, 401);
httpdHeader(connData, "Content-Type", "text/plain");
httpdHeader(connData, "WWW-Authenticate", "Basic realm=\""HTTP_AUTH_REALM"\"");
httpdEndHeaders(connData);
httpdSendStr(connData, "401 Unauthorized.");
//Okay, all done.
return HTTPD_CGI_DONE;
}