1 /* 2 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * 28 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 29 * Copyright 1997 The Open Group Research Institute. All rights reserved. 30 */ 31 32 package sun.security.krb5; 33 34 import sun.security.krb5.internal.*; 35 import sun.security.krb5.internal.crypto.Nonce; 36 import sun.security.krb5.internal.crypto.KeyUsage; 37 import java.io.IOException; 38 import java.time.Instant; 39 import java.util.Arrays; 40 41 /** 42 * This class encapsulates the KRB-AS-REQ message that the client 43 * sends to the KDC. 44 */ 45 public class KrbAsReq { 46 private ASReq asReqMessg; 47 48 private boolean DEBUG = Krb5.DEBUG; 49 50 /** 51 * Constructs an AS-REQ message. 52 */ 53 // Can be null? has default? 54 public KrbAsReq(EncryptionKey pakey, // ok 55 KDCOptions options, // ok, new KDCOptions() 56 PrincipalName cname, // NO and must have realm 57 PrincipalName sname, // ok, krgtgt@CREALM 58 KerberosTime from, // ok 59 KerberosTime till, // ok, will use 60 KerberosTime rtime, // ok 61 int[] eTypes, // NO 62 HostAddresses addresses, // ok 63 PAData[] extraPAs // ok 64 ) 65 throws KrbException, IOException { 66 67 if (options == null) { 68 options = new KDCOptions(); 69 } 70 // check if they are valid arguments. The optional fields should be 71 // consistent with settings in KDCOptions. Mar 17 2000 72 if (options.get(KDCOptions.FORWARDED) || 73 options.get(KDCOptions.PROXY) || 74 options.get(KDCOptions.ENC_TKT_IN_SKEY) || 75 options.get(KDCOptions.RENEW) || 76 options.get(KDCOptions.VALIDATE)) { 77 // this option is only specified in a request to the 78 // ticket-granting server 79 throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS); 80 } 81 if (options.get(KDCOptions.POSTDATED)) { 82 // if (from == null) 83 // throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS); 84 } else { 85 if (from != null) from = null; 86 } 87 88 PAData[] paData = null; 89 if (pakey != null) { 90 PAEncTSEnc ts = new PAEncTSEnc(); 91 byte[] temp = ts.asn1Encode(); 92 EncryptedData encTs = new EncryptedData(pakey, temp, 93 KeyUsage.KU_PA_ENC_TS); 94 paData = new PAData[1]; 95 paData[0] = new PAData( Krb5.PA_ENC_TIMESTAMP, 96 encTs.asn1Encode()); 97 } 98 if (extraPAs != null && extraPAs.length > 0) { 99 if (paData == null) { 100 paData = new PAData[extraPAs.length]; 101 } else { 102 paData = Arrays.copyOf(paData, paData.length + extraPAs.length); 103 } 104 System.arraycopy(extraPAs, 0, paData, 105 paData.length - extraPAs.length, extraPAs.length); 106 } 107 108 if (cname.getRealm() == null) { 109 throw new RealmException(Krb5.REALM_NULL, 110 "default realm not specified "); 111 } 112 113 if (DEBUG) { 114 System.out.println(">>> KrbAsReq creating message"); 115 } 116 117 Config cfg = Config.getInstance(); 118 119 // check to use addresses in tickets 120 if (addresses == null && cfg.useAddresses()) { 121 addresses = HostAddresses.getLocalAddresses(); 122 } 123 124 if (sname == null) { 125 String realm = cname.getRealmAsString(); 126 sname = PrincipalName.tgsService(realm, realm); 127 } 128 129 if (till == null) { 130 String d = cfg.get("libdefaults", "ticket_lifetime"); 131 if (d != null) { 132 till = new KerberosTime(Instant.now().plusSeconds(Config.duration(d))); 133 } else { 134 till = new KerberosTime(0); // Choose KDC maximum allowed 135 } 136 } 137 138 if (rtime == null) { 139 String d = cfg.get("libdefaults", "renew_lifetime"); 140 if (d != null) { 141 rtime = new KerberosTime(Instant.now().plusSeconds(Config.duration(d))); 142 } 143 } 144 145 if (rtime != null) { 146 options.set(KDCOptions.RENEWABLE, true); 147 if (till.greaterThan(rtime)) { 148 rtime = till; 149 } 150 } 151 152 // enc-authorization-data and additional-tickets never in AS-REQ 153 KDCReqBody kdc_req_body = new KDCReqBody(options, 154 cname, 155 sname, 156 from, 157 till, 158 rtime, 159 Nonce.value(), 160 eTypes, 161 addresses, 162 null, 163 null); 164 165 asReqMessg = new ASReq( 166 paData, 167 kdc_req_body); 168 } 169 170 byte[] encoding() throws IOException, Asn1Exception { 171 return asReqMessg.asn1Encode(); 172 } 173 174 // Used by KrbAsRep to validate AS-REP 175 ASReq getMessage() { 176 return asReqMessg; 177 } 178 }