mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-01 03:26:58 +03:00
Digest Authentication in Webserver Library (#3053)
* Add Digest Auth * Check for Opaque and Nonce * Remove Serial Debug and fix Indentation * Added example sketch with documentation,Fixed indentation and Defaults * Digest Authentication minor changes + new padded 32 digit random function * update license to public domain * renaming functions
This commit is contained in:
committed by
Ivan Grokhotkov
parent
3e9caf7a3d
commit
eebc5ec593
@ -94,6 +94,12 @@ void ESP8266WebServer::begin() {
|
||||
collectHeaders(0, 0);
|
||||
}
|
||||
|
||||
String ESP8266WebServer::_exractParam(String& authReq,const String& param,const char delimit){
|
||||
int _begin = authReq.indexOf(param);
|
||||
if (_begin==-1) return "";
|
||||
return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length()));
|
||||
}
|
||||
|
||||
bool ESP8266WebServer::authenticate(const char * username, const char * password){
|
||||
if(hasHeader(AUTHORIZATION_HEADER)){
|
||||
String authReq = header(AUTHORIZATION_HEADER);
|
||||
@ -121,15 +127,106 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password
|
||||
}
|
||||
delete[] toencode;
|
||||
delete[] encoded;
|
||||
}else if(authReq.startsWith("Digest")){
|
||||
authReq = authReq.substring(7);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println(authReq);
|
||||
#endif
|
||||
String _username = _exractParam(authReq,"username=\"");
|
||||
if((!_username.length())||_username!=String(username)){
|
||||
authReq = String();
|
||||
return false;
|
||||
}
|
||||
// extracting required parameters for RFC 2069 simpler Digest
|
||||
String _realm = _exractParam(authReq,"realm=\"");
|
||||
String _nonce = _exractParam(authReq,"nonce=\"");
|
||||
String _uri = _exractParam(authReq,"uri=\"");
|
||||
String _response = _exractParam(authReq,"response=\"");
|
||||
String _opaque = _exractParam(authReq,"opaque=\"");
|
||||
|
||||
if((!_realm.length())||(!_nonce.length())||(!_uri.length())||(!_response.length())||(!_opaque.length())){
|
||||
authReq = String();
|
||||
return false;
|
||||
}
|
||||
if((_opaque!=_sopaque)||(_nonce!=_snonce)||(_realm!=_srealm)){
|
||||
authReq = String();
|
||||
return false;
|
||||
}
|
||||
// parameters for the RFC 2617 newer Digest
|
||||
String _nc,_cnonce;
|
||||
if(authReq.indexOf("qop=auth") != -1){
|
||||
_nc = _exractParam(authReq,"nc=",',');
|
||||
_cnonce = _exractParam(authReq,"cnonce=\"");
|
||||
}
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
md5.add(String(username)+":"+_realm+":"+String(password)); // md5 of the user:realm:user
|
||||
md5.calculate();
|
||||
String _H1 = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Hash of user:realm:pass=" + _H1);
|
||||
#endif
|
||||
md5.begin();
|
||||
if(_currentMethod == HTTP_GET){
|
||||
md5.add("GET:"+_uri);
|
||||
}else if(_currentMethod == HTTP_POST){
|
||||
md5.add("POST:"+_uri);
|
||||
}else if(_currentMethod == HTTP_PUT){
|
||||
md5.add("PUT:"+_uri);
|
||||
}else if(_currentMethod == HTTP_DELETE){
|
||||
md5.add("DELETE:"+_uri);
|
||||
}else{
|
||||
md5.add("GET:"+_uri);
|
||||
}
|
||||
md5.calculate();
|
||||
String _H2 = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2);
|
||||
#endif
|
||||
md5.begin();
|
||||
if(authReq.indexOf("qop=auth") != -1){
|
||||
md5.add(_H1+":"+_nonce+":"+_nc+":"+_cnonce+":auth:"+_H2);
|
||||
}else{
|
||||
md5.add(_H1+":"+_nonce+":"+_H2);
|
||||
}
|
||||
md5.calculate();
|
||||
String _responsecheck = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("The Proper response=" +_responsecheck);
|
||||
#endif
|
||||
if(_response==_responsecheck){
|
||||
authReq = String();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
authReq = String();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ESP8266WebServer::requestAuthentication(){
|
||||
sendHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
|
||||
send(401);
|
||||
String ESP8266WebServer::_getRandomHexString(){
|
||||
char buffer[33]; // buffer to hold 32 Hex Digit + /0
|
||||
int i;
|
||||
for(i=0;i<4;i++){
|
||||
sprintf (buffer+(i*8), "%08x", RANDOM_REG32);
|
||||
}
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg){
|
||||
if(realm==NULL){
|
||||
_srealm = "Login Required";
|
||||
}else{
|
||||
_srealm = String(realm);
|
||||
}
|
||||
if(mode==BASIC_AUTH){
|
||||
sendHeader("WWW-Authenticate", "Basic realm=\"" + _srealm + "\"");
|
||||
}else{
|
||||
_snonce=_getRandomHexString();
|
||||
_sopaque=_getRandomHexString();
|
||||
sendHeader("WWW-Authenticate", "Digest realm=\"" +_srealm + "\", qop=\"auth\", nonce=\""+_snonce+"\", opaque=\""+_sopaque+"\"");
|
||||
}
|
||||
send(401,"text/html",authFailMsg);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::on(const String &uri, ESP8266WebServer::THandlerFunction handler) {
|
||||
|
Reference in New Issue
Block a user