Skip to content

Commit

Permalink
Merge pull request #10998 from wangkx/h16332
Browse files Browse the repository at this point in the history
HPCC-16332 Send error message if root authorization fails

Reviewed-By: Russ Whitehead <william.whitehead@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
  • Loading branch information
richardkchapman committed Apr 10, 2018
2 parents a6cbc5d + 1c09389 commit b673e6b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
21 changes: 18 additions & 3 deletions esp/bindings/http/platform/httpbinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
ctx->getUserID(userid);
if(userid.length() == 0)
{
ctx->setAuthError(EspAuthErrorEmptyUserID);
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authentication", "Access Denied: No username provided");
return false;
}

Expand All @@ -603,27 +605,37 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
if(user == NULL)
{
WARNLOG("Can't find user in context");
ctx->setAuthError(EspAuthErrorUserNotFoundInContext);
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authentication", "Access Denied: No username provided");
return false;
}

if(m_secmgr.get() == NULL)
{
WARNLOG("No mechanism established for authentication");
ctx->setAuthError(EspAuthErrorNoAuthMechanism);
return false;
}

ISecResourceList* rlist = ctx->queryResources();
if(rlist == NULL)
{
WARNLOG("No Security Resource");
ctx->setAuthError(EspAuthErrorEmptySecResource);
return false;
}

bool authenticated = m_secmgr->authorize(*user, rlist, ctx->querySecureContext());
if(!authenticated)
{
const char *desc = nullptr;
if (user->getAuthenticateStatus() == AS_PASSWORD_EXPIRED || user->getAuthenticateStatus() == AS_PASSWORD_VALID_BUT_EXPIRED)
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authentication", "ESP password is expired");
desc = "ESP password is expired";
else
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authentication", "Access Denied: User or password invalid");
desc = "Access Denied: User or password invalid";
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authentication", desc);
ctx->setAuthError(EspAuthErrorNotAuthenticated);
ctx->setRespMsg(desc);
return false;
}
bool authorized = true;
Expand All @@ -637,8 +649,11 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
if(access < required)
{
const char *desc=curres->getDescription();
ESPLOG(LogMin, "Access for user '%s' denied to: %s. Access=%d, Required=%d", user->getName(), desc?desc:"<no-desc>", access, required);
VStringBuffer msg("Access for user '%s' denied to: %s. Access=%d, Required=%d", user->getName(), desc?desc:"<no-desc>", access, required);
ESPLOG(LogMin, "%s", msg.str());
ctx->AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authorization", "Access Denied: Not Authorized", "Resource: %s [%s]", curres->getName(), (desc) ? desc : "");
ctx->setAuthError(EspAuthErrorNotAuthorized);
ctx->setRespMsg(msg.str());
authorized = false;
break;
}
Expand Down
34 changes: 33 additions & 1 deletion esp/bindings/http/platform/httpservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ EspAuthState CEspHttpServer::authNewSession(EspAuthRequest& authReq, const char*
authReq.ctx->setUserID(_userName);
authReq.ctx->setPassword(_password);
authReq.authBinding->populateRequest(m_request.get());
if (!authReq.authBinding->doAuth(authReq.ctx))
if (!authReq.authBinding->doAuth(authReq.ctx) && (authReq.ctx->getAuthError() != EspAuthErrorNotAuthorized))
{
ESPLOG(LogMin, "Authentication failed for %s@%s", _userName, peer.str());
return handleAuthFailed(true, authReq, unlock, "User authentication failed.");
Expand All @@ -1221,6 +1221,11 @@ EspAuthState CEspHttpServer::authNewSession(EspAuthRequest& authReq, const char*
addCookie(SESSION_TIMEOUT_COOKIE, cookieStr.str(), 0, false);
clearCookie(SESSION_AUTH_MSG_COOKIE);
clearCookie(SESSION_START_URL_COOKIE);
if (authReq.ctx->getAuthError() == EspAuthErrorNotAuthorized)
{
sendAuthorizationMsg(authReq);
return authSucceeded;
}
if (unlock)
{
sendLockResponse(false, false, "Unlocked");
Expand All @@ -1231,6 +1236,33 @@ EspAuthState CEspHttpServer::authNewSession(EspAuthRequest& authReq, const char*
return authSucceeded;
}

void CEspHttpServer::sendAuthorizationMsg(EspAuthRequest& authReq)
{
StringBuffer resp;
const char* errMsg = authReq.ctx->getRespMsg();
ESPSerializationFormat format = m_request->queryContext()->getResponseFormat();
if (format == ESPSerializationJSON)
{
resp.set("{ ");
resp.append(" \"LoginResponse\": { ");
if (isEmptyString(errMsg))
resp.append("\"Error\": \"Access Denied.\"");
else
resp.appendf("\"Error\": \"%s\"", errMsg);
resp.append(" }");
resp.append(" }");
}
else
{
resp.set("<LoginResponse><Error>");
resp.append("Access Denied.");
if (!isEmptyString(errMsg))
resp.append(" ").append(errMsg);
resp.append("</Error></LoginResponse>");
}
sendMessage(resp.str(), (format == ESPSerializationJSON) ? "application/json" : "text/xml");
}

void CEspHttpServer::sendLockResponse(bool lock, bool error, const char* msg)
{
StringBuffer resp;
Expand Down
1 change: 1 addition & 0 deletions esp/bindings/http/platform/httpservice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class CEspHttpServer : implements IHttpServerService, public CInterface
unsigned readCookie(const char* cookieName);
const char* readCookie(const char* cookieName, StringBuffer& cookieValue);
void sendLockResponse(bool lock, bool error, const char* msg);
void sendAuthorizationMsg(EspAuthRequest& authReq);
void createGetSessionTimeoutResponse(StringBuffer& resp, ESPSerializationFormat format, IPropertyTree* sessionTree);
void resetSessionTimeout(EspAuthRequest& authReq, unsigned sessionID, StringBuffer& resp, ESPSerializationFormat format, IPropertyTree* sessionTree);
void sendMessage(const char* msg, const char* msgType);
Expand Down
13 changes: 13 additions & 0 deletions esp/platform/espcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ class CEspContext : public CInterface, implements IEspContext
unsigned m_exceptionTime;
bool m_hasException;
int m_exceptionCode;
StringAttr respMsg;
StringAttr authenticationMethod;
AuthType domainAuthType;
AuthError authError = EspAuthErrorNone;

ESPSerializationFormat respSerializationFormat;

Expand Down Expand Up @@ -523,6 +525,17 @@ class CEspContext : public CInterface, implements IEspContext

virtual void setDomainAuthType(AuthType type) { domainAuthType = type; }
virtual AuthType getDomainAuthType(){ return domainAuthType; }
virtual void setAuthError(AuthError error) { authError = error; }
virtual AuthError getAuthError(){ return authError; }
virtual void setRespMsg(const char* msg)
{
respMsg.set(msg);
}

virtual const char* getRespMsg()
{
return respMsg.get();
}

virtual ESPSerializationFormat getResponseFormat(){return respSerializationFormat;}
virtual void setResponseFormat(ESPSerializationFormat fmt){respSerializationFormat = fmt;}
Expand Down
15 changes: 15 additions & 0 deletions esp/scm/esp.ecm
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ typedef enum AuthType_
AuthUserNameOnly
} AuthType;

typedef enum AuthError_
{
EspAuthErrorNone,
EspAuthErrorEmptyUserID,
EspAuthErrorUserNotFoundInContext,
EspAuthErrorNoAuthMechanism,
EspAuthErrorEmptySecResource,
EspAuthErrorNotAuthenticated,
EspAuthErrorNotAuthorized
} AuthError;

#define ESPCTX_NO_NAMESPACES 0x00000001
#define ESPCTX_WSDL 0x00000010
#define ESPCTX_WSDL_EXT 0x00000100
Expand Down Expand Up @@ -186,6 +197,10 @@ interface IEspContext : extends IInterface
virtual void setAuthenticationMethod(const char * method)=0;
virtual void setDomainAuthType(AuthType type)=0;
virtual AuthType getDomainAuthType()=0;
virtual void setAuthError(AuthError error)=0;
virtual AuthError getAuthError()=0;
virtual const char * getRespMsg()=0;
virtual void setRespMsg(const char * msg)=0;
};


Expand Down

0 comments on commit b673e6b

Please sign in to comment.