/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.http.impl.auth; import java.util.Locale; import org.apache.http.FormattedHeader; import org.apache.http.Header; import org.apache.http.HttpRequest; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.ChallengeState; import org.apache.http.auth.ContextAwareAuthScheme; import org.apache.http.auth.Credentials; import org.apache.http.auth.MalformedChallengeException; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; import org.apache.http.util.CharArrayBuffer; /** * Abstract authentication scheme class that serves as a basis * for all authentication schemes supported by HttpClient. This class * defines the generic way of parsing an authentication challenge. It * does not make any assumptions regarding the format of the challenge * nor does it impose any specific way of responding to that challenge. * * * @since 4.0 */ @NotThreadSafe public abstract class AuthSchemeBase implements ContextAwareAuthScheme { protected ChallengeState challengeState; /** * Creates an instance of {@code AuthSchemeBase} with the given challenge * state. * * @since 4.2 * * @deprecated (4.3) do not use. */ @Deprecated public AuthSchemeBase(final ChallengeState challengeState) { super(); this.challengeState = challengeState; } public AuthSchemeBase() { super(); } /** * Processes the given challenge token. Some authentication schemes * may involve multiple challenge-response exchanges. Such schemes must be able * to maintain the state information when dealing with sequential challenges * * @param header the challenge header * * @throws MalformedChallengeException is thrown if the authentication challenge * is malformed */ @Override public void processChallenge(final Header header) throws MalformedChallengeException { Args.notNull(header, "Header"); final String authheader = header.getName(); if (authheader.equalsIgnoreCase(AUTH.WWW_AUTH)) { this.challengeState = ChallengeState.TARGET; } else if (authheader.equalsIgnoreCase(AUTH.PROXY_AUTH)) { this.challengeState = ChallengeState.PROXY; } else { throw new MalformedChallengeException("Unexpected header name: " + authheader); } final CharArrayBuffer buffer; int pos; if (header instanceof FormattedHeader) { buffer = ((FormattedHeader) header).getBuffer(); pos = ((FormattedHeader) header).getValuePos(); } else { final String s = header.getValue(); if (s == null) { throw new MalformedChallengeException("Header value is null"); } buffer = new CharArrayBuffer(s.length()); buffer.append(s); pos = 0; } while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) { pos++; } final int beginIndex = pos; while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) { pos++; } final int endIndex = pos; final String s = buffer.substring(beginIndex, endIndex); if (!s.equalsIgnoreCase(getSchemeName())) { throw new MalformedChallengeException("Invalid scheme identifier: " + s); } parseChallenge(buffer, pos, buffer.length()); } @Override @SuppressWarnings("deprecation") public Header authenticate( final Credentials credentials, final HttpRequest request, final HttpContext context) throws AuthenticationException { return authenticate(credentials, request); } protected abstract void parseChallenge( CharArrayBuffer buffer, int beginIndex, int endIndex) throws MalformedChallengeException; /** * Returns {@code true} if authenticating against a proxy, {@code false} * otherwise. */ public boolean isProxy() { return this.challengeState != null && this.challengeState == ChallengeState.PROXY; } /** * Returns {@link ChallengeState} value or {@code null} if unchallenged. * * @since 4.2 */ public ChallengeState getChallengeState() { return this.challengeState; } @Override public String toString() { final String name = getSchemeName(); if (name != null) { return name.toUpperCase(Locale.ROOT); } else { return super.toString(); } } }