1 /* 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 it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * 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 WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 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 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * 27 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 28 * Copyright 1997 The Open Group Research Institute. All rights reserved. 29 */ 30 31 package sun.security.krb5.internal; 32 33 import sun.security.krb5.Config; 34 import sun.security.krb5.KrbException; 35 import sun.security.krb5.Asn1Exception; 36 import sun.security.krb5.internal.util.KerberosFlags; 37 import sun.security.util.*; 38 import java.io.IOException; 39 40 /** 41 * Implements the ASN.1 KDCOptions type. 42 * 43 * <pre>{@code 44 * KDCOptions ::= KerberosFlags 45 * -- reserved(0), 46 * -- forwardable(1), 47 * -- forwarded(2), 48 * -- proxiable(3), 49 * -- proxy(4), 50 * -- allow-postdate(5), 51 * -- postdated(6), 52 * -- unused7(7), 53 * -- renewable(8), 54 * -- unused9(9), 55 * -- unused10(10), 56 * -- opt-hardware-auth(11), 57 * -- unused12(12), 58 * -- unused13(13), 59 * -- 15 is reserved for canonicalize 60 * -- unused15(15), 61 * -- 26 was unused in 1510 62 * -- disable-transited-check(26), 63 * -- renewable-ok(27), 64 * -- enc-tkt-in-skey(28), 65 * -- renew(30), 66 * -- validate(31) 67 * 68 * KerberosFlags ::= BIT STRING (SIZE (32..MAX)) 69 * -- minimum number of bits shall be sent, 70 * -- but no fewer than 32 71 * 72 * }</pre> 73 * 74 * <p> 75 * This definition reflects the Network Working Group RFC 4120 76 * specification available at 77 * <a href="http://www.ietf.org/rfc/rfc4120.txt"> 78 * http://www.ietf.org/rfc/rfc4120.txt</a>. 79 * 80 * <p> 81 * This class appears as data field in the initial request(KRB_AS_REQ) 82 * or subsequent request(KRB_TGS_REQ) to the KDC and indicates the flags 83 * that the client wants to set on the tickets. 84 * 85 * The optional bits are: 86 * <UL> 87 * <LI>KDCOptions.RESERVED 88 * <LI>KDCOptions.FORWARDABLE 89 * <LI>KDCOptions.FORWARDED 90 * <LI>KDCOptions.PROXIABLE 91 * <LI>KDCOptions.PROXY 92 * <LI>KDCOptions.ALLOW_POSTDATE 93 * <LI>KDCOptions.POSTDATED 94 * <LI>KDCOptions.RENEWABLE 95 * <LI>KDCOptions.RENEWABLE_OK 96 * <LI>KDCOptions.ENC_TKT_IN_SKEY 97 * <LI>KDCOptions.RENEW 98 * <LI>KDCOptions.VALIDATE 99 * </UL> 100 * <p> Various checks must be made before honoring an option. The restrictions 101 * on the use of some options are as follows: 102 * <ol> 103 * <li> FORWARDABLE, FORWARDED, PROXIABLE, RENEWABLE options may be set in 104 * subsequent request only if the ticket_granting ticket on which it is based has 105 * the same options (FORWARDABLE, FORWARDED, PROXIABLE, RENEWABLE) set. 106 * <li> ALLOW_POSTDATE may be set in subsequent request only if the 107 * ticket-granting ticket on which it is based also has its MAY_POSTDATE flag set. 108 * <li> POSTDATED may be set in subsequent request only if the 109 * ticket-granting ticket on which it is based also has its MAY_POSTDATE flag set. 110 * <li> RENEWABLE or RENEW may be set in subsequent request only if the 111 * ticket-granting ticket on which it is based also has its RENEWABLE flag set. 112 * <li> POXY may be set in subsequent request only if the ticket-granting ticket 113 * on which it is based also has its PROXIABLE flag set, and the address(es) of 114 * the host from which the resulting ticket is to be valid should be included 115 * in the addresses field of the request. 116 * <li>FORWARDED, PROXY, ENC_TKT_IN_SKEY, RENEW, VALIDATE are used only in 117 * subsequent requests. 118 * </ol> 119 */ 120 121 public class KDCOptions extends KerberosFlags { 122 123 private static final int KDC_OPT_PROXIABLE = 0x10000000; 124 private static final int KDC_OPT_RENEWABLE_OK = 0x00000010; 125 private static final int KDC_OPT_FORWARDABLE = 0x40000000; 126 127 128 // KDC Options 129 130 public static final int RESERVED = 0; 131 public static final int FORWARDABLE = 1; 132 public static final int FORWARDED = 2; 133 public static final int PROXIABLE = 3; 134 public static final int PROXY = 4; 135 public static final int ALLOW_POSTDATE = 5; 136 public static final int POSTDATED = 6; 137 public static final int UNUSED7 = 7; 138 public static final int RENEWABLE = 8; 139 public static final int UNUSED9 = 9; 140 public static final int UNUSED10 = 10; 141 public static final int UNUSED11 = 11; 142 public static final int CNAME_IN_ADDL_TKT = 14; 143 public static final int CANONICALIZE = 15; 144 public static final int RENEWABLE_OK = 27; 145 public static final int ENC_TKT_IN_SKEY = 28; 146 public static final int RENEW = 30; 147 public static final int VALIDATE = 31; 148 149 private static final String[] names = { 150 "RESERVED", //0 151 "FORWARDABLE", //1; 152 "FORWARDED", //2; 153 "PROXIABLE", //3; 154 "PROXY", //4; 155 "ALLOW_POSTDATE", //5; 156 "POSTDATED", //6; 157 "UNUSED7", //7; 158 "RENEWABLE", //8; 159 "UNUSED9", //9; 160 "UNUSED10", //10; 161 "UNUSED11", //11; 162 null,null, 163 "CNAME_IN_ADDL_TKT",//14; 164 "CANONICALIZE", //15; 165 null,null,null,null,null,null,null,null,null,null,null, 166 "RENEWABLE_OK", //27; 167 "ENC_TKT_IN_SKEY", //28; 168 null, 169 "RENEW", //30; 170 "VALIDATE", //31; 171 }; 172 173 private boolean DEBUG = Krb5.DEBUG; 174 with(int... flags)175 public static KDCOptions with(int... flags) { 176 KDCOptions options = new KDCOptions(); 177 for (int flag: flags) { 178 options.set(flag, true); 179 } 180 return options; 181 } 182 KDCOptions()183 public KDCOptions() { 184 super(Krb5.KDC_OPTS_MAX + 1); 185 setDefault(); 186 } 187 KDCOptions(int size, byte[] data)188 public KDCOptions(int size, byte[] data) throws Asn1Exception { 189 super(size, data); 190 if ((size > data.length * BITS_PER_UNIT) || (size > Krb5.KDC_OPTS_MAX + 1)) 191 throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH); 192 } 193 194 /** 195 * Constructs a KDCOptions from the specified bit settings. 196 * 197 * @param data the bits to be set for the KDCOptions. 198 * @exception Asn1Exception if an error occurs while decoding an ASN1 199 * encoded data. 200 * 201 */ KDCOptions(boolean[] data)202 public KDCOptions(boolean[] data) throws Asn1Exception { 203 super(data); 204 if (data.length > Krb5.KDC_OPTS_MAX + 1) { 205 throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH); 206 } 207 } 208 KDCOptions(DerValue encoding)209 public KDCOptions(DerValue encoding) throws Asn1Exception, IOException { 210 this(encoding.getUnalignedBitString(true).toBooleanArray()); 211 } 212 213 /** 214 * Constructs a KDCOptions from the passed bit settings. 215 * 216 * @param options the bits to be set for the KDCOptions. 217 * 218 */ KDCOptions(byte[] options)219 public KDCOptions(byte[] options) { 220 super(options.length * BITS_PER_UNIT, options); 221 } 222 223 /** 224 * Parse (unmarshal) a KDCOptions from a DER input stream. This form 225 * parsing might be used when expanding a value which is part of 226 * a constructed sequence and uses explicitly tagged type. 227 * 228 * @param data the Der input stream value, which contains one or more 229 * marshaled value. 230 * @param explicitTag tag number. 231 * @param optional indicate if this data field is optional 232 * @return an instance of KDCOptions. 233 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 234 * @exception IOException if an I/O error occurs while reading encoded data. 235 * 236 */ 237 parse(DerInputStream data, byte explicitTag, boolean optional)238 public static KDCOptions parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException { 239 if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) 240 return null; 241 DerValue der = data.getDerValue(); 242 if (explicitTag != (der.getTag() & (byte)0x1F)) { 243 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 244 } else { 245 DerValue subDer = der.getData().getDerValue(); 246 return new KDCOptions(subDer); 247 } 248 } 249 250 /** 251 * Sets the value(true/false) for one of the <code>KDCOptions</code>. 252 * 253 * @param option an option bit. 254 * @param value true if the option is selected, false if the option is not selected. 255 * @exception ArrayIndexOutOfBoundsException if array index out of bound occurs. 256 * @see sun.security.krb5.internal.Krb5 257 */ set(int option, boolean value)258 public void set(int option, boolean value) throws ArrayIndexOutOfBoundsException { 259 super.set(option, value); 260 } 261 262 /** 263 * Gets the value(true/false) for one of the <code>KDCOptions</code>. 264 * 265 * @param option an option bit. 266 * @return value true if the option is selected, false if the option is not selected. 267 * @exception ArrayIndexOutOfBoundsException if array index out of bound occurs. 268 * @see sun.security.krb5.internal.Krb5 269 */ 270 get(int option)271 public boolean get(int option) throws ArrayIndexOutOfBoundsException { 272 return super.get(option); 273 } 274 toString()275 @Override public String toString() { 276 StringBuilder sb = new StringBuilder(); 277 sb.append("KDCOptions: "); 278 for (int i=0; i<Krb5.KDC_OPTS_MAX+1; i++) { 279 if (get(i)) { 280 if (names[i] != null) { 281 sb.append(names[i]).append(","); 282 } else { 283 sb.append(i).append(","); 284 } 285 } 286 } 287 return sb.toString(); 288 } 289 setDefault()290 private void setDefault() { 291 try { 292 293 Config config = Config.getInstance(); 294 295 // If key not present, returns Integer.MIN_VALUE, which is 296 // almost all zero. 297 298 int options = config.getIntValue("libdefaults", 299 "kdc_default_options"); 300 301 if ((options & KDC_OPT_RENEWABLE_OK) == KDC_OPT_RENEWABLE_OK) { 302 set(RENEWABLE_OK, true); 303 } else { 304 if (config.getBooleanObject("libdefaults", "renewable") == Boolean.TRUE) { 305 set(RENEWABLE_OK, true); 306 } 307 } 308 if ((options & KDC_OPT_PROXIABLE) == KDC_OPT_PROXIABLE) { 309 set(PROXIABLE, true); 310 } else { 311 if (config.getBooleanObject("libdefaults", "proxiable") == Boolean.TRUE) { 312 set(PROXIABLE, true); 313 } 314 } 315 316 if ((options & KDC_OPT_FORWARDABLE) == KDC_OPT_FORWARDABLE) { 317 set(FORWARDABLE, true); 318 } else { 319 if (config.getBooleanObject("libdefaults", "forwardable") == Boolean.TRUE) { 320 set(FORWARDABLE, true); 321 } 322 } 323 } catch (KrbException e) { 324 if (DEBUG) { 325 System.out.println("Exception in getting default values for " + 326 "KDC Options from the configuration "); 327 e.printStackTrace(); 328 329 } 330 } 331 } 332 } 333