Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java
38830 views
/*1* Copyright (c) 2000, 2019, 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*/2425/*26*27* (C) Copyright IBM Corp. 1999 All Rights Reserved.28* Copyright 1997 The Open Group Research Institute. All rights reserved.29*/3031package sun.security.krb5;3233import sun.security.krb5.internal.*;34import sun.security.krb5.internal.crypto.*;35import java.io.IOException;36import java.net.UnknownHostException;37import java.time.Instant;38import java.util.Arrays;3940/**41* This class encapsulates a Kerberos TGS-REQ that is sent from the42* client to the KDC.43*/44public class KrbTgsReq {4546private PrincipalName princName;47private PrincipalName clientAlias;48private PrincipalName servName;49private PrincipalName serverAlias;50private TGSReq tgsReqMessg;51private KerberosTime ctime;52private Ticket secondTicket = null;53private boolean useSubkey = false;54EncryptionKey tgsReqKey;5556private static final boolean DEBUG = Krb5.DEBUG;5758private byte[] obuf;59private byte[] ibuf;6061// Used in CredentialsUtil62public KrbTgsReq(KDCOptions options, Credentials asCreds,63PrincipalName cname, PrincipalName clientAlias,64PrincipalName sname, PrincipalName serverAlias,65Ticket[] additionalTickets, PAData[] extraPAs)66throws KrbException, IOException {67this(options,68asCreds,69cname,70clientAlias,71sname,72serverAlias,73null, // KerberosTime from74null, // KerberosTime till75null, // KerberosTime rtime76null, // int[] eTypes77null, // HostAddresses addresses78null, // AuthorizationData authorizationData79additionalTickets,80null, // EncryptionKey subKey81extraPAs);82}8384// Called by Credentials, KrbCred85KrbTgsReq(86KDCOptions options,87Credentials asCreds,88PrincipalName sname,89PrincipalName serverAlias,90KerberosTime from,91KerberosTime till,92KerberosTime rtime,93int[] eTypes,94HostAddresses addresses,95AuthorizationData authorizationData,96Ticket[] additionalTickets,97EncryptionKey subKey) throws KrbException, IOException {98this(options, asCreds, asCreds.getClient(), asCreds.getClientAlias(),99sname, serverAlias, from, till, rtime, eTypes,100addresses, authorizationData, additionalTickets, subKey, null);101}102103private KrbTgsReq(104KDCOptions options,105Credentials asCreds,106PrincipalName cname,107PrincipalName clientAlias,108PrincipalName sname,109PrincipalName serverAlias,110KerberosTime from,111KerberosTime till,112KerberosTime rtime,113int[] eTypes,114HostAddresses addresses,115AuthorizationData authorizationData,116Ticket[] additionalTickets,117EncryptionKey subKey,118PAData[] extraPAs) throws KrbException, IOException {119120princName = cname;121this.clientAlias = clientAlias;122servName = sname;123this.serverAlias = serverAlias;124ctime = KerberosTime.now();125126// check if they are valid arguments. The optional fields127// should be consistent with settings in KDCOptions.128129if (options.get(KDCOptions.FORWARDABLE) &&130(!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {131options.set(KDCOptions.FORWARDABLE, false);132}133if (options.get(KDCOptions.FORWARDED)) {134if (!(asCreds.flags.get(KDCOptions.FORWARDABLE)))135throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);136}137if (options.get(KDCOptions.PROXIABLE) &&138(!(asCreds.flags.get(Krb5.TKT_OPTS_PROXIABLE)))) {139throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);140}141if (options.get(KDCOptions.PROXY)) {142if (!(asCreds.flags.get(KDCOptions.PROXIABLE)))143throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);144}145if (options.get(KDCOptions.ALLOW_POSTDATE) &&146(!(asCreds.flags.get(Krb5.TKT_OPTS_MAY_POSTDATE)))) {147throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);148}149if (options.get(KDCOptions.RENEWABLE) &&150(!(asCreds.flags.get(Krb5.TKT_OPTS_RENEWABLE)))) {151throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);152}153154if (options.get(KDCOptions.POSTDATED)) {155if (!(asCreds.flags.get(KDCOptions.POSTDATED)))156throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);157} else {158if (from != null) from = null;159}160if (options.get(KDCOptions.RENEWABLE)) {161if (!(asCreds.flags.get(KDCOptions.RENEWABLE)))162throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);163} else {164if (rtime != null) rtime = null;165}166if (options.get(KDCOptions.ENC_TKT_IN_SKEY) || options.get(KDCOptions.CNAME_IN_ADDL_TKT)) {167if (additionalTickets == null)168throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);169// in TGS_REQ there could be more than one additional170// tickets, but in file-based credential cache,171// there is only one additional ticket field.172secondTicket = additionalTickets[0];173} else {174if (additionalTickets != null)175additionalTickets = null;176}177178tgsReqMessg = createRequest(179options,180asCreds.ticket,181asCreds.key,182ctime,183princName,184servName,185from,186till,187rtime,188eTypes,189addresses,190authorizationData,191additionalTickets,192subKey,193extraPAs);194obuf = tgsReqMessg.asn1Encode();195196// XXX We need to revisit this to see if can't move it197// up such that FORWARDED flag set in the options198// is included in the marshaled request.199/*200* If this is based on a forwarded ticket, record that in the201* options, because the returned TgsRep will contain the202* FORWARDED flag set.203*/204if (asCreds.flags.get(KDCOptions.FORWARDED))205options.set(KDCOptions.FORWARDED, true);206207208}209210/**211* Sends a TGS request to the realm of the target.212* @throws KrbException213* @throws IOException214*/215public void send() throws IOException, KrbException {216String realmStr = null;217if (servName != null)218realmStr = servName.getRealmString();219KdcComm comm = new KdcComm(realmStr);220ibuf = comm.send(obuf);221}222223public KrbTgsRep getReply()224throws KrbException, IOException {225return new KrbTgsRep(ibuf, this);226}227228/**229* Sends the request, waits for a reply, and returns the Credentials.230* Used in Credentials, KrbCred, and internal/CredentialsUtil.231*/232public Credentials sendAndGetCreds() throws IOException, KrbException {233KrbTgsRep tgs_rep = null;234String kdc = null;235send();236tgs_rep = getReply();237return tgs_rep.getCreds();238}239240KerberosTime getCtime() {241return ctime;242}243244private TGSReq createRequest(245KDCOptions kdc_options,246Ticket ticket,247EncryptionKey key,248KerberosTime ctime,249PrincipalName cname,250PrincipalName sname,251KerberosTime from,252KerberosTime till,253KerberosTime rtime,254int[] eTypes,255HostAddresses addresses,256AuthorizationData authorizationData,257Ticket[] additionalTickets,258EncryptionKey subKey,259PAData[] extraPAs)260throws IOException, KrbException, UnknownHostException {261KerberosTime req_till = null;262if (till == null) {263String d = Config.getInstance().get("libdefaults", "ticket_lifetime");264if (d != null) {265req_till = new KerberosTime(Instant.now().plusSeconds(Config.duration(d)));266} else {267req_till = new KerberosTime(0); // Choose KDC maximum allowed268}269} else {270req_till = till;271}272273/*274* RFC 4120, Section 5.4.2.275* For KRB_TGS_REP, the ciphertext is encrypted in the276* sub-session key from the Authenticator, or if absent,277* the session key from the ticket-granting ticket used278* in the request.279*280* To support this, use tgsReqKey to remember which key to use.281*/282tgsReqKey = key;283284int[] req_eTypes = null;285if (eTypes == null) {286req_eTypes = EType.getDefaults("default_tgs_enctypes");287} else {288req_eTypes = eTypes;289}290291EncryptionKey reqKey = null;292EncryptedData encAuthorizationData = null;293if (authorizationData != null) {294byte[] ad = authorizationData.asn1Encode();295if (subKey != null) {296reqKey = subKey;297tgsReqKey = subKey; // Key to use to decrypt reply298useSubkey = true;299encAuthorizationData = new EncryptedData(reqKey, ad,300KeyUsage.KU_TGS_REQ_AUTH_DATA_SUBKEY);301} else302encAuthorizationData = new EncryptedData(key, ad,303KeyUsage.KU_TGS_REQ_AUTH_DATA_SESSKEY);304}305306KDCReqBody reqBody = new KDCReqBody(307kdc_options,308cname,309sname,310from,311req_till,312rtime,313Nonce.value(),314req_eTypes,315addresses,316encAuthorizationData,317additionalTickets);318319byte[] temp = reqBody.asn1Encode(Krb5.KRB_TGS_REQ);320// if the checksum type is one of the keyed checksum types,321// use session key.322Checksum cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,323KeyUsage.KU_PA_TGS_REQ_CKSUM);324325// Usage will be KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR326327byte[] tgs_ap_req = new KrbApReq(328new APOptions(),329ticket,330key,331cname,332cksum,333ctime,334reqKey,335null,336null).getMessage();337338PAData tgsPAData = new PAData(Krb5.PA_TGS_REQ, tgs_ap_req);339PAData[] pa;340if (extraPAs != null) {341pa = Arrays.copyOf(extraPAs, extraPAs.length + 1);342pa[extraPAs.length] = tgsPAData;343} else {344pa = new PAData[] {tgsPAData};345}346return new TGSReq(pa, reqBody);347}348349TGSReq getMessage() {350return tgsReqMessg;351}352353Ticket getSecondTicket() {354return secondTicket;355}356357PrincipalName getClientAlias() {358return clientAlias;359}360361PrincipalName getServerAlias() {362return serverAlias;363}364365private static void debug(String message) {366// System.err.println(">>> KrbTgsReq: " + message);367}368369boolean usedSubkey() {370return useSubkey;371}372373}374375376