mirror of https://github.com/jeelabs/esp-link.git
parent
25a0984080
commit
784568c07f
@ -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; |
||||
} |
||||
|
@ -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 |
@ -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); |
Loading…
Reference in new issue