Skip to content

Package: SpnegoEngine

SpnegoEngine

nameinstructionbranchcomplexitylinemethod
SpnegoEngine()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
SpnegoEngine(SpnegoTokenGenerator)
M: 11 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
generateToken(String)
M: 219 C: 0
0%
M: 24 C: 0
0%
M: 13 C: 0
0%
M: 53 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
3: * Copyright (c) 2010-2015 Sonatype, Inc. All rights reserved.
4: *
5: * This program is licensed to you under the Apache License Version 2.0,
6: * and you may not use this file except in compliance with the Apache License Version 2.0.
7: * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
8: *
9: * Unless required by applicable law or agreed to in writing,
10: * software distributed under the Apache License Version 2.0 is distributed on an
11: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12: * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
13: */
14:
15: /*
16: * ====================================================================
17: *
18: * Licensed to the Apache Software Foundation (ASF) under one or more
19: * contributor license agreements. See the NOTICE file distributed with
20: * this work for additional information regarding copyright ownership.
21: * The ASF licenses this file to You under the Apache License, Version 2.0
22: * (the "License"); you may not use this file except in compliance with
23: * the License. You may obtain a copy of the License at
24: *
25: * http://www.apache.org/licenses/LICENSE-2.0
26: *
27: * Unless required by applicable law or agreed to in writing, software
28: * distributed under the License is distributed on an "AS IS" BASIS,
29: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30: * See the License for the specific language governing permissions and
31: * limitations under the License.
32: * ====================================================================
33: *
34: * This software consists of voluntary contributions made by many
35: * individuals on behalf of the Apache Software Foundation. For more
36: * information on the Apache Software Foundation, please see
37: * <http://www.apache.org/>.
38: */
39:
40: package com.ning.http.client.spnego;
41:
42: import org.ietf.jgss.GSSContext;
43: import org.ietf.jgss.GSSException;
44: import org.ietf.jgss.GSSManager;
45: import org.ietf.jgss.GSSName;
46: import org.ietf.jgss.Oid;
47: import org.slf4j.Logger;
48: import org.slf4j.LoggerFactory;
49:
50: import com.ning.http.util.Base64;
51:
52: import java.io.IOException;
53:
54: /**
55: * SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) authentication
56: * scheme.
57: *
58: * @since 4.1
59: */
60: public class SpnegoEngine {
61:
62: private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
63: private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
64:
65: private final Logger log = LoggerFactory.getLogger(getClass());
66:
67: private final SpnegoTokenGenerator spnegoGenerator;
68:
69: public static final SpnegoEngine INSTANCE = new SpnegoEngine();
70:
71: public SpnegoEngine(final SpnegoTokenGenerator spnegoGenerator) {
72: this.spnegoGenerator = spnegoGenerator;
73: }
74:
75: public SpnegoEngine() {
76: this(null);
77: }
78:
79: public String generateToken(String server) throws Throwable {
80:
81: try {
82: log.debug("init {}", server);
83: /* Using the SPNEGO OID is the correct method.
84: * Kerberos v5 works for IIS but not JBoss. Unwrapping
85: * the initial token when using SPNEGO OID looks like what is
86: * described here...
87: *
88: * http://msdn.microsoft.com/en-us/library/ms995330.aspx
89: *
90: * Another helpful URL...
91: *
92: * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html
93: *
94: * Unfortunately SPNEGO is JRE >=1.6.
95: */
96:
97: GSSContext gssContext = null;
98: byte[] token = null; // base64 decoded challenge
99: Oid negotiationOid = null;
100:
101: /** Try SPNEGO by default, fall back to Kerberos later if error */
102: negotiationOid = new Oid(SPNEGO_OID);
103:
104: boolean tryKerberos = false;
105: try {
106: GSSManager manager = GSSManager.getInstance();
107: GSSName serverName = manager.createName("HTTP@" + server, GSSName.NT_HOSTBASED_SERVICE);
108: gssContext = manager.createContext(
109: serverName.canonicalize(negotiationOid), negotiationOid, null,
110: GSSContext.DEFAULT_LIFETIME);
111: gssContext.requestMutualAuth(true);
112: gssContext.requestCredDeleg(true);
113: } catch (GSSException ex) {
114: log.error("generateToken", ex);
115: // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH.
116: // Rethrow any other exception.
117:• if (ex.getMajor() == GSSException.BAD_MECH) {
118: log.debug("GSSException BAD_MECH, retry with Kerberos MECH");
119: tryKerberos = true;
120: } else {
121: throw ex;
122: }
123:
124: }
125:• if (tryKerberos) {
126: /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/
127: log.debug("Using Kerberos MECH {}", KERBEROS_OID);
128: negotiationOid = new Oid(KERBEROS_OID);
129: GSSManager manager = GSSManager.getInstance();
130: GSSName serverName = manager.createName("HTTP@" + server, GSSName.NT_HOSTBASED_SERVICE);
131: gssContext = manager.createContext(
132: serverName.canonicalize(negotiationOid), negotiationOid, null,
133: GSSContext.DEFAULT_LIFETIME);
134: gssContext.requestMutualAuth(true);
135: gssContext.requestCredDeleg(true);
136: }
137:
138: // TODO suspicious: this will always be null because no value has been assigned before. Assign directly?
139:• if (token == null) {
140: token = new byte[0];
141: }
142:
143: token = gssContext.initSecContext(token, 0, token.length);
144:• if (token == null) {
145: throw new Exception("GSS security context initialization failed");
146: }
147:
148: /*
149: * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish?
150: * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token.
151: */
152:• if (spnegoGenerator != null && negotiationOid.toString().equals(KERBEROS_OID)) {
153: token = spnegoGenerator.generateSpnegoDERObject(token);
154: }
155:
156: gssContext.dispose();
157:
158: String tokenstr = new String(Base64.encode(token));
159: log.debug("Sending response '{}' back to the server", tokenstr);
160:
161: return tokenstr;
162: } catch (GSSException gsse) {
163: log.error("generateToken", gsse);
164:• if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
165:• || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED)
166: throw new Exception(gsse.getMessage(), gsse);
167:• if (gsse.getMajor() == GSSException.NO_CRED)
168: throw new Exception(gsse.getMessage(), gsse);
169:• if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
170:• || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
171:• || gsse.getMajor() == GSSException.OLD_TOKEN)
172: throw new Exception(gsse.getMessage(), gsse);
173: // other error
174: throw new Exception(gsse.getMessage());
175: } catch (IOException ex) {
176: throw new Exception(ex.getMessage());
177: }
178: }
179: }