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