src/share/classes/sun/security/krb5/KrbKdcRep.java

Sun, 31 May 2020 10:13:04 +0800

author
mbalao
date
Sun, 31 May 2020 10:13:04 +0800
changeset 14203
d8bd882cfd2a
parent 14114
971263b8cd56
child 14222
5a272e10d7e7
permissions
-rw-r--r--

8246193: Possible NPE in ENC-PA-REP search in AS-REQ
Reviewed-by: zgu, andrew

duke@3 1 /*
duke@3 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@3 3 *
duke@3 4 * This code is free software; you can redistribute it and/or modify it
duke@3 5 * under the terms of the GNU General Public License version 2 only, as
ohair@2365 6 * published by the Free Software Foundation. Oracle designates this
duke@3 7 * particular file as subject to the "Classpath" exception as provided
ohair@2365 8 * by Oracle in the LICENSE file that accompanied this code.
duke@3 9 *
duke@3 10 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@3 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@3 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@3 13 * version 2 for more details (a copy is included in the LICENSE file that
duke@3 14 * accompanied this code).
duke@3 15 *
duke@3 16 * You should have received a copy of the GNU General Public License version
duke@3 17 * 2 along with this work; if not, write to the Free Software Foundation,
duke@3 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@3 19 *
ohair@2365 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@2365 21 * or visit www.oracle.com if you need additional information or have any
ohair@2365 22 * questions.
duke@3 23 */
duke@3 24
duke@3 25 /*
duke@3 26 *
duke@3 27 * (C) Copyright IBM Corp. 1999 All Rights Reserved.
duke@3 28 * Copyright 1997 The Open Group Research Institute. All rights reserved.
duke@3 29 */
duke@3 30
duke@3 31 package sun.security.krb5;
duke@3 32
duke@3 33 import sun.security.krb5.internal.*;
mbalao@13811 34 import sun.security.krb5.internal.crypto.KeyUsage;
mbalao@13811 35 import sun.security.util.DerInputStream;
duke@3 36
duke@3 37 abstract class KrbKdcRep {
duke@3 38
duke@3 39 static void check(
weijun@5623 40 boolean isAsReq,
duke@3 41 KDCReq req,
mbalao@13811 42 KDCRep rep,
mbalao@13811 43 EncryptionKey replyKey
duke@3 44 ) throws KrbApErrException {
duke@3 45
mbalao@13811 46 // cname change in AS-REP is allowed only if the client
mbalao@14114 47 // sent CANONICALIZE or an NT-ENTERPRISE cname in the request, and the
mbalao@14114 48 // server supports RFC 6806 - Section 11 FAST scheme (ENC-PA-REP flag).
mbalao@13811 49 if (isAsReq && !req.reqBody.cname.equals(rep.cname) &&
mbalao@14114 50 ((!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) &&
mbalao@14114 51 req.reqBody.cname.getNameType() !=
mbalao@14114 52 PrincipalName.KRB_NT_ENTERPRISE) ||
mbalao@14114 53 !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) {
duke@3 54 rep.encKDCRepPart.key.destroy();
duke@3 55 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 56 }
duke@3 57
mbalao@13811 58 // sname change in TGS-REP is allowed only if client
mbalao@13811 59 // sent CANONICALIZE and new sname is a referral of
mbalao@13811 60 // the form krbtgt/TO-REALM.COM@FROM-REALM.COM.
weijun@5623 61 if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) {
mbalao@13811 62 String[] snameStrings = rep.encKDCRepPart.sname.getNameStrings();
mbalao@13811 63 if (isAsReq || !req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) ||
mbalao@13811 64 snameStrings == null || snameStrings.length != 2 ||
mbalao@13811 65 !snameStrings[0].equals(PrincipalName.TGS_DEFAULT_SRV_NAME) ||
mbalao@13811 66 !rep.encKDCRepPart.sname.getRealmString().equals(
mbalao@13811 67 req.reqBody.sname.getRealmString())) {
mbalao@13811 68 rep.encKDCRepPart.key.destroy();
mbalao@13811 69 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
mbalao@13811 70 }
duke@3 71 }
duke@3 72
duke@3 73 if (req.reqBody.getNonce() != rep.encKDCRepPart.nonce) {
duke@3 74 rep.encKDCRepPart.key.destroy();
duke@3 75 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 76 }
duke@3 77
duke@3 78 if (
duke@3 79 ((req.reqBody.addresses != null && rep.encKDCRepPart.caddr != null) &&
duke@3 80 !req.reqBody.addresses.equals(rep.encKDCRepPart.caddr))) {
duke@3 81 rep.encKDCRepPart.key.destroy();
duke@3 82 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 83 }
duke@3 84
weijun@11700 85 // We allow KDC to return a non-forwardable ticket if request has -f
weijun@11700 86 for (int i = 2; i < 6; i++) {
duke@3 87 if (req.reqBody.kdcOptions.get(i) !=
weijun@6093 88 rep.encKDCRepPart.flags.get(i)) {
weijun@6093 89 if (Krb5.DEBUG) {
weijun@6093 90 System.out.println("> KrbKdcRep.check: at #" + i
weijun@6093 91 + ". request for " + req.reqBody.kdcOptions.get(i)
weijun@6093 92 + ", received " + rep.encKDCRepPart.flags.get(i));
weijun@6093 93 }
duke@3 94 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 95 }
duke@3 96 }
duke@3 97
pkoppula@13316 98 // Reply to a renewable request should be renewable, but if request does
pkoppula@13316 99 // not contain renewable, KDC is free to issue a renewable ticket (for
pkoppula@13316 100 // example, if ticket_lifetime is too big).
pkoppula@13316 101 if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) &&
pkoppula@13316 102 !rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
duke@3 103 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 104 }
andrew@13814 105
andrew@13814 106 if ((req.reqBody.from == null) || req.reqBody.from.isZero()) {
duke@3 107 // verify this is allowed
duke@3 108 if ((rep.encKDCRepPart.starttime != null) &&
andrew@13814 109 !rep.encKDCRepPart.starttime.inClockSkew()) {
duke@3 110 rep.encKDCRepPart.key.destroy();
duke@3 111 throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
duke@3 112 }
andrew@13814 113 }
duke@3 114
andrew@13814 115 if ((req.reqBody.from != null) && !req.reqBody.from.isZero()) {
duke@3 116 // verify this is allowed
duke@3 117 if ((rep.encKDCRepPart.starttime != null) &&
andrew@13814 118 !req.reqBody.from.equals(rep.encKDCRepPart.starttime)) {
duke@3 119 rep.encKDCRepPart.key.destroy();
duke@3 120 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 121 }
andrew@13814 122 }
duke@3 123
duke@3 124 if (!req.reqBody.till.isZero() &&
andrew@13814 125 rep.encKDCRepPart.endtime.greaterThan(req.reqBody.till)) {
duke@3 126 rep.encKDCRepPart.key.destroy();
duke@3 127 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 128 }
duke@3 129
mbalao@13811 130 // RFC 6806 - Section 11 mechanism check
mbalao@14114 131 // The availability of the ENC-PA-REP flag in the KDC response is
mbalao@14114 132 // mandatory on some cases (see Krb5.TKT_OPTS_ENC_PA_REP check above).
mbalao@14114 133 if (rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP)) {
mbalao@13811 134 boolean reqPaReqEncPaRep = false;
mbalao@13811 135 boolean repPaReqEncPaRepValid = false;
mbalao@13811 136
mbalao@14203 137 if (req.pAData != null) {
mbalao@14203 138 for (PAData pa : req.pAData) {
mbalao@14203 139 if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) {
mbalao@14203 140 // The KDC supports RFC 6806 and ENC-PA-REP was sent in
mbalao@14203 141 // the request (AS-REQ). A valid checksum is now required.
mbalao@14203 142 reqPaReqEncPaRep = true;
mbalao@14203 143 break;
mbalao@14203 144 }
mbalao@13811 145 }
mbalao@13811 146 }
mbalao@13811 147
mbalao@13811 148 if (rep.encKDCRepPart.pAData != null) {
mbalao@13811 149 for (PAData pa : rep.encKDCRepPart.pAData) {
mbalao@13811 150 if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) {
mbalao@13811 151 try {
mbalao@13811 152 Checksum repCksum = new Checksum(
mbalao@13811 153 new DerInputStream(
mbalao@13811 154 pa.getValue()).getDerValue());
weijun@13812 155 // The checksum is inside encKDCRepPart so we don't
weijun@13812 156 // care if it's keyed or not.
mbalao@13811 157 repPaReqEncPaRepValid =
weijun@13812 158 repCksum.verifyAnyChecksum(
mbalao@13811 159 req.asn1Encode(), replyKey,
mbalao@13811 160 KeyUsage.KU_AS_REQ);
mbalao@13811 161 } catch (Exception e) {
mbalao@13811 162 if (Krb5.DEBUG) {
mbalao@13811 163 e.printStackTrace();
mbalao@13811 164 }
mbalao@13811 165 }
mbalao@13811 166 break;
mbalao@13811 167 }
mbalao@13811 168 }
mbalao@13811 169 }
mbalao@13811 170
mbalao@13811 171 if (reqPaReqEncPaRep && !repPaReqEncPaRepValid) {
mbalao@13811 172 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
mbalao@13811 173 }
mbalao@13811 174 }
mbalao@13811 175
andrew@13814 176 if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE)) {
andrew@13814 177 if (req.reqBody.rtime != null && !req.reqBody.rtime.isZero()) {
andrew@13814 178 // verify this is required
duke@3 179 if ((rep.encKDCRepPart.renewTill == null) ||
andrew@13814 180 rep.encKDCRepPart.renewTill.greaterThan(req.reqBody.rtime)
andrew@13814 181 ) {
duke@3 182 rep.encKDCRepPart.key.destroy();
duke@3 183 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
duke@3 184 }
duke@3 185
andrew@13814 186 }
andrew@13814 187 }
duke@3 188 }
duke@3 189 }

mercurial