Path: blob/master/src/java.security.jgss/share/classes/sun/security/jgss/krb5/InitSecContextToken.java
41161 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.jgss.krb5;2627import org.ietf.jgss.*;28import java.io.InputStream;29import java.io.IOException;3031import sun.security.action.GetPropertyAction;32import sun.security.krb5.*;33import java.net.InetAddress;34import sun.security.krb5.internal.AuthorizationData;35import sun.security.krb5.internal.KerberosTime;3637class InitSecContextToken extends InitialToken {3839// If non-mutual authentication is requested, there is no AP-REP message.40// The acceptor thus has no chance to send the seq-number field to the41// initiator. In this case, the initiator and acceptor should has an42// agreement to derive acceptor's initial seq-number if the acceptor wishes43// to send messages to the initiator.4445// If this flag is true, it will the same as the initiator's initial46// seq-number (as MIT krb5 and Windows SSPI do). Otherwise, it will be zero47// (as Heimdal does). The default value is true.48private static final boolean ACCEPTOR_USE_INITIATOR_SEQNUM;4950static {51// The ACCEPTOR_USE_INITIATOR_SEQNUM value is determined by the system52// property "sun.security.krb5.acceptor.sequence.number.nonmutual",53// which can be set to "initiator", "zero" or "0".54String propName = "sun.security.krb5.acceptor.sequence.number.nonmutual";55String s = GetPropertyAction.privilegedGetProperty(propName, "initiator");56if (s.equals("initiator")) {57ACCEPTOR_USE_INITIATOR_SEQNUM = true;58} else if (s.equals("zero") || s.equals("0")) {59ACCEPTOR_USE_INITIATOR_SEQNUM = false;60} else {61throw new AssertionError("Unrecognized value for " + propName62+ ": " + s);63}64}6566private KrbApReq apReq = null;6768/**69* For the context initiator to call. It constructs a new70* InitSecContextToken to send over to the peer containing the desired71* flags and the AP-REQ. It also updates the context with the local72* sequence number and shared context key.73* (When mutual auth is enabled the peer has an opportunity to74* renegotiate the session key in the followup AcceptSecContextToken75* that it sends.)76*/77InitSecContextToken(Krb5Context context,78Credentials tgt,79Credentials serviceTicket)80throws KrbException, IOException, GSSException {8182boolean mutualRequired = context.getMutualAuthState();83boolean useSubkey = true; // MIT Impl will crash if this is not set!84boolean useSequenceNumber = true;8586OverloadedChecksum gssChecksum =87new OverloadedChecksum(context, tgt, serviceTicket);8889Checksum checksum = gssChecksum.getChecksum();9091context.setTktFlags(serviceTicket.getFlags());92context.setAuthTime(93new KerberosTime(serviceTicket.getAuthTime()).toString());94apReq = new KrbApReq(serviceTicket,95mutualRequired,96useSubkey,97useSequenceNumber,98checksum);99100context.resetMySequenceNumber(apReq.getSeqNumber().intValue());101102EncryptionKey subKey = apReq.getSubKey();103if (subKey != null)104context.setKey(Krb5Context.INITIATOR_SUBKEY, subKey);105else106context.setKey(Krb5Context.SESSION_KEY, serviceTicket.getSessionKey());107108if (!mutualRequired)109context.resetPeerSequenceNumber(110ACCEPTOR_USE_INITIATOR_SEQNUM111? apReq.getSeqNumber().intValue()112: 0);113}114115/**116* For the context acceptor to call. It reads the bytes out of an117* InputStream and constructs an InitSecContextToken with them.118*/119InitSecContextToken(Krb5Context context, Krb5AcceptCredential cred,120InputStream is)121throws IOException, GSSException, KrbException {122123int tokenId = ((is.read()<<8) | is.read());124125if (tokenId != Krb5Token.AP_REQ_ID)126throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,127"AP_REQ token id does not match!");128129// XXX Modify KrbApReq cons to take an InputStream130byte[] apReqBytes =131new sun.security.util.DerValue(is).toByteArray();132//debug("=====ApReqBytes: [" + getHexBytes(apReqBytes) + "]\n");133134InetAddress addr = null;135if (context.getChannelBinding() != null) {136addr = context.getChannelBinding().getInitiatorAddress();137}138apReq = new KrbApReq(apReqBytes, cred, addr);139//debug("\nReceived AP-REQ and authenticated it.\n");140141EncryptionKey sessionKey = apReq.getCreds().getSessionKey();142143/*144System.out.println("\n\nSession key from service ticket is: " +145getHexBytes(sessionKey.getBytes()));146*/147148EncryptionKey subKey = apReq.getSubKey();149if (subKey != null) {150context.setKey(Krb5Context.INITIATOR_SUBKEY, subKey);151/*152System.out.println("Sub-Session key from authenticator is: " +153getHexBytes(subKey.getBytes()) + "\n");154*/155} else {156context.setKey(Krb5Context.SESSION_KEY, sessionKey);157//System.out.println("Sub-Session Key Missing in Authenticator.\n");158}159160OverloadedChecksum gssChecksum = new OverloadedChecksum(161context, apReq.getChecksum(), sessionKey, subKey);162gssChecksum.setContextFlags(context);163Credentials delegCred = gssChecksum.getDelegatedCreds();164if (delegCred != null) {165Krb5CredElement credElement =166Krb5InitCredential.getInstance(167(Krb5NameElement)context.getSrcName(),168delegCred);169context.setDelegCred(credElement);170}171172Integer apReqSeqNumber = apReq.getSeqNumber();173int peerSeqNumber = (apReqSeqNumber != null ?174apReqSeqNumber.intValue() :1750);176context.resetPeerSequenceNumber(peerSeqNumber);177if (!context.getMutualAuthState()) {178context.resetMySequenceNumber(179ACCEPTOR_USE_INITIATOR_SEQNUM180? peerSeqNumber181: 0);182}183context.setAuthTime(184new KerberosTime(apReq.getCreds().getAuthTime()).toString());185context.setTktFlags(apReq.getCreds().getFlags());186AuthorizationData ad = apReq.getCreds().getAuthzData();187context.setAuthzData(ad);188}189190public final KrbApReq getKrbApReq() {191return apReq;192}193194public final byte[] encode() throws IOException {195byte[] apReqBytes = apReq.getMessage();196byte[] retVal = new byte[2 + apReqBytes.length];197writeInt(Krb5Token.AP_REQ_ID, retVal, 0);198System.arraycopy(apReqBytes, 0, retVal, 2, apReqBytes.length);199// System.out.println("GSS-Token with AP_REQ is:");200// System.out.println(getHexBytes(retVal));201return retVal;202}203}204205206