1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27 package org.apache.http.impl.auth;
28
29 import java.io.IOException;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.http.Header;
34 import org.apache.http.HttpRequest;
35 import org.apache.http.auth.AuthenticationException;
36 import org.apache.http.auth.Credentials;
37 import org.apache.http.protocol.HttpContext;
38 import org.apache.http.util.Args;
39 import org.ietf.jgss.GSSException;
40 import org.ietf.jgss.Oid;
41
42 /**
43 * SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) authentication
44 * scheme.
45 *
46 * @since 4.1
47 *
48 * @deprecated (4.2) use {@link SPNegoScheme} or {@link KerberosScheme}.
49 */
50 @Deprecated
51 public class NegotiateScheme extends GGSSchemeBase {
52
53 private final Log log = LogFactory.getLog(getClass());
54
55 private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
56 private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
57
58 private final SpnegoTokenGenerator spengoGenerator;
59
60 /**
61 * Default constructor for the Negotiate authentication scheme.
62 *
63 */
64 public NegotiateScheme(final SpnegoTokenGenerator spengoGenerator, final boolean stripPort) {
65 super(stripPort);
66 this.spengoGenerator = spengoGenerator;
67 }
68
69 public NegotiateScheme(final SpnegoTokenGenerator spengoGenerator) {
70 this(spengoGenerator, false);
71 }
72
73 public NegotiateScheme() {
74 this(null, false);
75 }
76
77 /**
78 * Returns textual designation of the Negotiate authentication scheme.
79 *
80 * @return <code>Negotiate</code>
81 */
82 public String getSchemeName() {
83 return "Negotiate";
84 }
85
86 @Override
87 public Header authenticate(
88 final Credentials credentials,
89 final HttpRequest request) throws AuthenticationException {
90 return authenticate(credentials, request, null);
91 }
92
93 /**
94 * Produces Negotiate authorization Header based on token created by
95 * processChallenge.
96 *
97 * @param credentials Never used be the Negotiate scheme but must be provided to
98 * satisfy common-httpclient API. Credentials from JAAS will be used instead.
99 * @param request The request being authenticated
100 *
101 * @throws AuthenticationException if authorisation string cannot
102 * be generated due to an authentication failure
103 *
104 * @return an Negotiate authorisation Header
105 */
106 @Override
107 public Header authenticate(
108 final Credentials credentials,
109 final HttpRequest request,
110 final HttpContext context) throws AuthenticationException {
111 return super.authenticate(credentials, request, context);
112 }
113
114 @Override
115 protected byte[] generateToken(final byte[] input, final String authServer) throws GSSException {
116 /* Using the SPNEGO OID is the correct method.
117 * Kerberos v5 works for IIS but not JBoss. Unwrapping
118 * the initial token when using SPNEGO OID looks like what is
119 * described here...
120 *
121 * http://msdn.microsoft.com/en-us/library/ms995330.aspx
122 *
123 * Another helpful URL...
124 *
125 * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html
126 *
127 * Unfortunately SPNEGO is JRE >=1.6.
128 */
129
130 /** Try SPNEGO by default, fall back to Kerberos later if error */
131 Oid negotiationOid = new Oid(SPNEGO_OID);
132
133 byte[] token = input;
134 boolean tryKerberos = false;
135 try {
136 token = generateGSSToken(token, negotiationOid, authServer);
137 } catch (final GSSException ex){
138 // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH.
139 // Rethrow any other exception.
140 if (ex.getMajor() == GSSException.BAD_MECH ){
141 log.debug("GSSException BAD_MECH, retry with Kerberos MECH");
142 tryKerberos = true;
143 } else {
144 throw ex;
145 }
146
147 }
148 if (tryKerberos){
149 /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/
150 log.debug("Using Kerberos MECH " + KERBEROS_OID);
151 negotiationOid = new Oid(KERBEROS_OID);
152 token = generateGSSToken(token, negotiationOid, authServer);
153
154 /*
155 * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish?
156 * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token.
157 */
158 if (token != null && spengoGenerator != null) {
159 try {
160 token = spengoGenerator.generateSpnegoDERObject(token);
161 } catch (final IOException ex) {
162 log.error(ex.getMessage(), ex);
163 }
164 }
165 }
166 return token;
167 }
168
169 /**
170 * Returns the authentication parameter with the given name, if available.
171 *
172 * <p>There are no valid parameters for Negotiate authentication so this
173 * method always returns <tt>null</tt>.</p>
174 *
175 * @param name The name of the parameter to be returned
176 *
177 * @return the parameter with the given name
178 */
179 public String getParameter(final String name) {
180 Args.notNull(name, "Parameter name");
181 return null;
182 }
183
184 /**
185 * The concept of an authentication realm is not supported by the Negotiate
186 * authentication scheme. Always returns <code>null</code>.
187 *
188 * @return <code>null</code>
189 */
190 public String getRealm() {
191 return null;
192 }
193
194 /**
195 * Returns <tt>true</tt>.
196 * Negotiate authentication scheme is connection based.
197 *
198 * @return <tt>true</tt>.
199 */
200 public boolean isConnectionBased() {
201 return true;
202 }
203
204 }