Added basic authentication
This commit is contained in:
@@ -4,3 +4,6 @@
|
|||||||
|
|
||||||
//Pos of esp fs in flash
|
//Pos of esp fs in flash
|
||||||
#define ESPFS_POS 0x12000
|
#define ESPFS_POS 0x12000
|
||||||
|
|
||||||
|
//If you want, you can define a realm for the authentication system.
|
||||||
|
//#define HTTP_AUTH_REALM "MyRealm"
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
HTTP auth implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* "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 <string.h>
|
||||||
|
#include <osapi.h>
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "httpd.h"
|
||||||
|
#include "cgi.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "base64.h"
|
||||||
|
#include "espmissingincludes.h"
|
||||||
|
#include <ip_addr.h>
|
||||||
|
|
||||||
|
int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) {
|
||||||
|
const char *forbidden="401 Forbidden.";
|
||||||
|
int no=0;
|
||||||
|
int r;
|
||||||
|
char hdr[(AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2)*10];
|
||||||
|
char userpass[AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2];
|
||||||
|
char user[AUTH_MAX_USER_LEN];
|
||||||
|
char pass[AUTH_MAX_PASS_LEN];
|
||||||
|
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) {
|
||||||
|
r=base64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass);
|
||||||
|
if (r<0) r=0;
|
||||||
|
userpass[r]=0;
|
||||||
|
os_printf("Auth: %s\n", userpass);
|
||||||
|
while (((AuthGetUserPw)(connData->cgiArg))(connData, no,
|
||||||
|
user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) {
|
||||||
|
//Check user/pass against auth header
|
||||||
|
if (strlen(userpass)==strlen(user)+strlen(pass)+1 &&
|
||||||
|
os_strncmp(userpass, user, strlen(user))==0 &&
|
||||||
|
userpass[strlen(user)]==':' &&
|
||||||
|
os_strcmp(userpass+strlen(user)+1, pass)==0) {
|
||||||
|
//Authenticated. Yay!
|
||||||
|
return HTTPD_CGI_AUTHENTICATED;
|
||||||
|
}
|
||||||
|
no++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
espconn_sent(connData->conn, (uint8 *)forbidden, os_strlen(forbidden));
|
||||||
|
return HTTPD_CGI_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef AUTH_H
|
||||||
|
#define AUTH_H
|
||||||
|
|
||||||
|
#include "httpdconfig.h"
|
||||||
|
|
||||||
|
#ifndef HTTP_AUTH_REALM
|
||||||
|
#define HTTP_AUTH_REALM "Protected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HTTPD_AUTH_SINGLE 0
|
||||||
|
#define HTTPD_AUTH_CALLBACK 1
|
||||||
|
|
||||||
|
#define AUTH_MAX_USER_LEN 32
|
||||||
|
#define AUTH_MAX_PASS_LEN 32
|
||||||
|
|
||||||
|
//Parameter given to authWhatever functions. This callback returns the usernames/passwords the device
|
||||||
|
//has.
|
||||||
|
typedef int (* AuthGetUserPw)(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen);
|
||||||
|
|
||||||
|
int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData);
|
||||||
|
|
||||||
|
#endif
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/* base64.c : base-64 / MIME encode/decode */
|
||||||
|
/* PUBLIC DOMAIN - Jon Mayo - November 13, 2003 */
|
||||||
|
#include "espmissingincludes.h"
|
||||||
|
#include "c_types.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
static const uint8_t base64dec_tab[256]= {
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
|
||||||
|
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
|
||||||
|
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) {
|
||||||
|
uint8_t v[4];
|
||||||
|
|
||||||
|
v[0]=base64dec_tab[(unsigned)in[0]];
|
||||||
|
v[1]=base64dec_tab[(unsigned)in[1]];
|
||||||
|
v[2]=base64dec_tab[(unsigned)in[2]];
|
||||||
|
v[3]=base64dec_tab[(unsigned)in[3]];
|
||||||
|
|
||||||
|
out[0]=(v[0]<<2)|(v[1]>>4);
|
||||||
|
out[1]=(v[1]<<4)|(v[2]>>2);
|
||||||
|
out[2]=(v[2]<<6)|(v[3]);
|
||||||
|
return (v[0]|v[1]|v[2]|v[3])!=255 ? in[3]=='=' ? in[2]=='=' ? 1 : 2 : 3 : 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* decode a base64 string in one shot */
|
||||||
|
int ICACHE_FLASH_ATTR base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) {
|
||||||
|
unsigned ii, io;
|
||||||
|
uint32_t v;
|
||||||
|
unsigned rem;
|
||||||
|
|
||||||
|
for(io=0,ii=0,v=0,rem=0;ii<in_len;ii++) {
|
||||||
|
unsigned char ch;
|
||||||
|
if(isspace(in[ii])) continue;
|
||||||
|
if(in[ii]=='=') break; /* stop at = */
|
||||||
|
ch=base64dec_tab[(unsigned)in[ii]];
|
||||||
|
if(ch==255) break; /* stop at a parse error */
|
||||||
|
v=(v<<6)|ch;
|
||||||
|
rem+=6;
|
||||||
|
if(rem>=8) {
|
||||||
|
rem-=8;
|
||||||
|
if(io>=out_len) return -1; /* truncation is failure */
|
||||||
|
out[io++]=(v>>rem)&255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(rem>=8) {
|
||||||
|
rem-=8;
|
||||||
|
if(io>=out_len) return -1; /* truncation is failure */
|
||||||
|
out[io++]=(v>>rem)&255;
|
||||||
|
}
|
||||||
|
return io;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Only need decode functions for now.
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
static const uint8_t base64enc_tab[64]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
void base64encode(const unsigned char in[3], unsigned char out[4], int count) {
|
||||||
|
out[0]=base64enc_tab[(in[0]>>2)];
|
||||||
|
out[1]=base64enc_tab[((in[0]&3)<<4)|(in[1]>>4)];
|
||||||
|
out[2]=count<2 ? '=' : base64enc_tab[((in[1]&15)<<2)|(in[2]>>6)];
|
||||||
|
out[3]=count<3 ? '=' : base64enc_tab[(in[2]&63)];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out) {
|
||||||
|
unsigned ii, io;
|
||||||
|
uint_least32_t v;
|
||||||
|
unsigned rem;
|
||||||
|
|
||||||
|
for(io=0,ii=0,v=0,rem=0;ii<in_len;ii++) {
|
||||||
|
unsigned char ch;
|
||||||
|
ch=in[ii];
|
||||||
|
v=(v<<8)|ch;
|
||||||
|
rem+=8;
|
||||||
|
while(rem>=6) {
|
||||||
|
rem-=6;
|
||||||
|
if(io>=out_len) return -1; /* truncation is failure */
|
||||||
|
out[io++]=base64enc_tab[(v>>rem)&63];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(rem) {
|
||||||
|
v<<=(6-rem);
|
||||||
|
if(io>=out_len) return -1; /* truncation is failure */
|
||||||
|
out[io++]=base64enc_tab[v&63];
|
||||||
|
}
|
||||||
|
while(io&3) {
|
||||||
|
if(io>=out_len) return -1; /* truncation is failure */
|
||||||
|
out[io++]='=';
|
||||||
|
}
|
||||||
|
if(io>=out_len) return -1; /* no room for null terminator */
|
||||||
|
out[io]=0;
|
||||||
|
return io;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
int base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out);
|
||||||
+22
-1
@@ -19,6 +19,24 @@
|
|||||||
#include "cgi.h"
|
#include "cgi.h"
|
||||||
#include "cgiwifi.h"
|
#include "cgiwifi.h"
|
||||||
#include "stdout.h"
|
#include "stdout.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
|
//Function that tells the authentication system what users/passwords live on the system.
|
||||||
|
//This is disabled in the default build; if you want to try it, enable the authBasic line in
|
||||||
|
//the builtInUrls below.
|
||||||
|
int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) {
|
||||||
|
if (no==0) {
|
||||||
|
os_strcpy(user, "admin");
|
||||||
|
os_strcpy(pass, "s3cr3t");
|
||||||
|
return 1;
|
||||||
|
//Add more users this way
|
||||||
|
// } else if (no==1) {
|
||||||
|
// os_strcpy(user, "user1");
|
||||||
|
// os_strcpy(pass, "something");
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
HttpdBuiltInUrl builtInUrls[]={
|
HttpdBuiltInUrl builtInUrls[]={
|
||||||
{"/", cgiRedirect, "/index.tpl"},
|
{"/", cgiRedirect, "/index.tpl"},
|
||||||
@@ -28,6 +46,10 @@ HttpdBuiltInUrl builtInUrls[]={
|
|||||||
{"/led.cgi", cgiLed, NULL},
|
{"/led.cgi", cgiLed, NULL},
|
||||||
|
|
||||||
//Routines to make the /wifi URL and everything beneath it work.
|
//Routines to make the /wifi URL and everything beneath it work.
|
||||||
|
|
||||||
|
//Enable the line below to protect the WiFi configuration with an username/password combo.
|
||||||
|
// {"/wifi/*", authBasic, myPassFn},
|
||||||
|
|
||||||
{"/wifi", cgiRedirect, "/wifi/wifi.tpl"},
|
{"/wifi", cgiRedirect, "/wifi/wifi.tpl"},
|
||||||
{"/wifi/", cgiRedirect, "/wifi/wifi.tpl"},
|
{"/wifi/", cgiRedirect, "/wifi/wifi.tpl"},
|
||||||
{"/wifi/wifiscan.cgi", cgiWiFiScan, NULL},
|
{"/wifi/wifiscan.cgi", cgiWiFiScan, NULL},
|
||||||
@@ -35,7 +57,6 @@ HttpdBuiltInUrl builtInUrls[]={
|
|||||||
{"/wifi/connect.cgi", cgiWiFiConnect, NULL},
|
{"/wifi/connect.cgi", cgiWiFiConnect, NULL},
|
||||||
{"/wifi/setmode.cgi", cgiWifiSetMode, NULL},
|
{"/wifi/setmode.cgi", cgiWifiSetMode, NULL},
|
||||||
|
|
||||||
|
|
||||||
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem
|
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user