[ 
https://issues.apache.org/jira/browse/RANGER-3619?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ramesh Mani reassigned RANGER-3619:
-----------------------------------

    Assignee: kirby zhou

> REST API should return 403 when authenticated client is not allowed to access 
> API.
> ----------------------------------------------------------------------------------
>
>                 Key: RANGER-3619
>                 URL: https://issues.apache.org/jira/browse/RANGER-3619
>             Project: Ranger
>          Issue Type: Bug
>          Components: Ranger
>    Affects Versions: 3.0.0, 2.2.0
>            Reporter: kirby zhou
>            Assignee: kirby zhou
>            Priority: Major
>
> REST API should return 403-Forbidden when authenticated client is not allowed 
> to access API to avoid crash Ranger Clients.
>  
> Now, some API returns 401-Unauthorized instead of 403-Forbidden when client 
> is already passed authentication but now allowed to do something.
> In general, this will not cause any serious problems. However, there is a 
> flaw in the SPNEGO protocol implementation of Java HTTPUrlConnection. It 
> causes the Client to throw an unexpected exception. This will trouble the 
> operators and developers.
>  
> Let me show you how it happens:
>  
> For example:
>  
> The RangerAdminClient inside KMS  want to access API 
> "/service/secure/policies/download", but the principal is not in the 
> allowlist.
>  
>  # RangerAdminClient is based on Jersey-Client
>  # JerseyClient sends a HTTP-request to Ranger Service without authentication 
> information
>  # Tomcat/Spring inside Ranger returns 401 with HTTP header 
> “WWW-Authentication: Neogotiate”
>  # JerseyClient sends request again with Kerberos/SPNEGO authentication 
> tokens.
>  # Tomcat/Spring inside Ranger accept the authentication, then call 
> ServiceRest::getSecureServicePoliciesIfUpdated to reply the API calling.
>  # ServiceRest::getSecureServicePoliciesIfUpdated checks allowlist of “kms 
> service”, and refuse client with 401.
>  # Tomcat/Spring inside Ranger returns 401 with HTTP header 
> “WWW-Authentication: Neogotiate….” for notifying RangerAdminClient the 
> authentication is passed.
>  
> Now, there is a malformed state. HTTP-status code told client authenticate is 
> failed, but HTTP header told client authentication is passed.
>  
> In the RangerAdminClient side, 
>  
>  # sun.net.www.protocol.http.HttpURLConnection.getInputStream0() see the 
> second 401.
>  # 'inNegotiate' = true, so it is in the progress of _Negotiate._
>  # It checks that: if "WWW-Authenticate: Negotiate" exist then disable 
> negotiate for following code to avoid try {_}Negotiate once again{_}.
>  # But "WWW-Authenticate: Negotiate xczsd324…" does not the rule above.
>  # So HttpURLConnection calls AuthenticationInfo.sendHeaders to generate a 
> new request header.
>  # Wow, Null exception happens.
>  # Logs "ERROR RangerAdminRESTClient - Error getting policies; Received NULL 
> response!!. secureMode=true, user=… (auth:KERBEROS), serviceName=kmsdev"
>  # Log of KMS: "ERROR RangerAdminRESTClient - Failed to get response, Error 
> is : java.lang.RuntimeException: java.lang.NullPointerException"
>  
> This log makes admin confused.
>  
>  
> {code:java}
> //ServiceRest::getServicePoliciesIfUpdated
> if (isAllowed) {
> //...
> } else {
>    httpCode = HttpServletResponse.SC_UNAUTHORIZED;
> }
>  {code}
> {code:java}
> // sun.net.www.protocol.http.HttpURLConnection.getInputStream0()
> // Read comments labeled "Failed Negotiate" for details.
> boolean dontUseNegotiate = false;
> Iterator<String> iter = responses.multiValueIterator("WWW-Authenticate");
> while (iter.hasNext()) {
>     String value = iter.next().trim();
>     if (value.equalsIgnoreCase("Negotiate") ||
>             value.equalsIgnoreCase("Kerberos")) {
>         if (!inNegotiate) {
>             inNegotiate = true;
>         } else {
>             dontUseNegotiate = true;
>             doingNTLM2ndStage = false;
>             serverAuthentication = null;
>         }
>         break;
>     }
> }
> /**
>  * Failed Negotiate
>  *
>  * In some cases, the Negotiate auth is supported for the
>  * remote host but the negotiate process still fails (For
>  * example, if the web page is located on a backend server
>  * and delegation is needed but fails). The authentication
>  * process will start again, and we need to detect this
>  * kind of failure and do proper fallback (say, to NTLM).
>  *
>  * In order to achieve this, the inNegotiate flag is set
>  * when the first negotiate challenge is met (and reset
>  * if authentication is finished). If a fresh new negotiate
>  * challenge (no parameter) is found while inNegotiate is
>  * set, we know there's a failed auth attempt recently.
>  * Here we'll ignore the header line so that fallback
>  * can be practiced.
>  *
>  * inNegotiateProxy is for proxy authentication.
>  */
>   {code}
>  
>  
>  
>  



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

Reply via email to