Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.httpd; 16 : 17 : import static com.google.common.base.Strings.emptyToNull; 18 : import static com.google.common.net.HttpHeaders.AUTHORIZATION; 19 : import static java.nio.charset.StandardCharsets.UTF_8; 20 : 21 : import com.google.common.io.BaseEncoding; 22 : import com.google.gerrit.common.Nullable; 23 : import javax.servlet.http.HttpServletRequest; 24 : 25 0 : public class RemoteUserUtil { 26 : /** 27 : * Tries to get username from a request with following strategies: 28 : * 29 : * <ul> 30 : * <li>ServletRequest#getRemoteUser 31 : * <li>HTTP 'Authorization' header 32 : * <li>Custom HTTP header 33 : * </ul> 34 : * 35 : * @param req request to extract username from. 36 : * @param loginHeader name of header which is used for extracting username. 37 : * @return the extracted username or null. 38 : */ 39 : public static String getRemoteUser(HttpServletRequest req, String loginHeader) { 40 0 : if (AUTHORIZATION.equals(loginHeader)) { 41 0 : String user = emptyToNull(req.getRemoteUser()); 42 0 : if (user != null) { 43 : // The container performed the authentication, and has the user 44 : // identity already decoded for us. Honor that as we have been 45 : // configured to honor HTTP authentication. 46 0 : return user; 47 : } 48 : 49 : // If the container didn't do the authentication we might 50 : // have done it in the front-end web server. Try to split 51 : // the identity out of the Authorization header and honor it. 52 0 : String auth = req.getHeader(AUTHORIZATION); 53 0 : return extractUsername(auth); 54 : } 55 : // Nonstandard HTTP header. We have been told to trust this 56 : // header blindly as-is. 57 0 : return emptyToNull(req.getHeader(loginHeader)); 58 : } 59 : 60 : /** 61 : * Extracts username from an HTTP Basic or Digest authentication header. 62 : * 63 : * @param auth header value which is used for extracting. 64 : * @return username if available or null. 65 : */ 66 : @Nullable 67 : public static String extractUsername(String auth) { 68 1 : auth = emptyToNull(auth); 69 : 70 1 : if (auth == null) { 71 1 : return null; 72 : 73 1 : } else if (auth.startsWith("Basic ")) { 74 1 : auth = auth.substring("Basic ".length()); 75 1 : auth = new String(BaseEncoding.base64().decode(auth), UTF_8); 76 1 : final int c = auth.indexOf(':'); 77 1 : return c > 0 ? auth.substring(0, c) : null; 78 : 79 1 : } else if (auth.startsWith("Digest ")) { 80 1 : final int u = auth.indexOf("username=\""); 81 1 : if (u <= 0) { 82 0 : return null; 83 : } 84 1 : auth = auth.substring(u + 10); 85 1 : final int e = auth.indexOf('"'); 86 1 : return e > 0 ? auth.substring(0, e) : null; 87 : 88 : } else { 89 0 : return null; 90 : } 91 : } 92 : }