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 RENEWABLE_OK = 27; 144 public static final int ENC_TKT_IN_SKEY = 28; 145 public static final int RENEW = 30; 146 public static final int VALIDATE = 31; 147 148 private static final String[] names = { 149 "RESERVED", //0 150 "FORWARDABLE", //1; 151 "FORWARDED", //2; 152 "PROXIABLE", //3; 153 "PROXY", //4; 154 "ALLOW_POSTDATE", //5; 155 "POSTDATED", //6; 156 "UNUSED7", //7; 157 "RENEWABLE", //8; 158 "UNUSED9", //9; 159 "UNUSED10", //10; 160 "UNUSED11", //11; 161 null,null, 162 "CNAME_IN_ADDL_TKT",//14; 163 null,null,null,null,null,null,null,null,null,null,null,null, 164 "RENEWABLE_OK", //27; 165 "ENC_TKT_IN_SKEY", //28; 166 null, 167 "RENEW", //30; 168 "VALIDATE", //31; 169 }; 170 171 private boolean DEBUG = Krb5.DEBUG; 172 173 public static KDCOptions with(int... flags) { 174 KDCOptions options = new KDCOptions(); 175 for (int flag: flags) { 176 options.set(flag, true); 177 } 178 return options; 179 } 180 181 public KDCOptions() { 182 super(Krb5.KDC_OPTS_MAX + 1); 183 setDefault(); 184 } 185 186 public KDCOptions(int size, byte[] data) throws Asn1Exception { 187 super(size, data); 188 if ((size > data.length * BITS_PER_UNIT) || (size > Krb5.KDC_OPTS_MAX + 1)) 189 throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH); 190 } 191 192 /** 193 * Constructs a KDCOptions from the specified bit settings. 194 * 195 * @param data the bits to be set for the KDCOptions. 196 * @exception Asn1Exception if an error occurs while decoding an ASN1 197 * encoded data. 198 * 199 */ 200 public KDCOptions(boolean[] data) throws Asn1Exception { 201 super(data); 202 if (data.length > Krb5.KDC_OPTS_MAX + 1) { 203 throw new Asn1Exception(Krb5.BITSTRING_BAD_LENGTH); 204 } 205 } 206 207 public KDCOptions(DerValue encoding) throws Asn1Exception, IOException { 208 this(encoding.getUnalignedBitString(true).toBooleanArray()); 209 } 210 211 /** 212 * Constructs a KDCOptions from the passed bit settings. 213 * 214 * @param options the bits to be set for the KDCOptions. 215 * 216 */ 217 public KDCOptions(byte[] options) { 218 super(options.length * BITS_PER_UNIT, options); 219 } 220 221 /** 222 * Parse (unmarshal) a KDCOptions from a DER input stream. This form 223 * parsing might be used when expanding a value which is part of 224 * a constructed sequence and uses explicitly tagged type. 225 * 226 * @param data the Der input stream value, which contains one or more 227 * marshaled value. 228 * @param explicitTag tag number. 229 * @param optional indicate if this data field is optional 230 * @return an instance of KDCOptions. 231 * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data. 232 * @exception IOException if an I/O error occurs while reading encoded data. 233 * 234 */ 235 236 public static KDCOptions parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException { 237 if ((optional) && (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) 238 return null; 239 DerValue der = data.getDerValue(); 240 if (explicitTag != (der.getTag() & (byte)0x1F)) { 241 throw new Asn1Exception(Krb5.ASN1_BAD_ID); 242 } else { 243 DerValue subDer = der.getData().getDerValue(); 244 return new KDCOptions(subDer); 245 } 246 } 247 248 /** 249 * Sets the value(true/false) for one of the <code>KDCOptions</code>. 250 * 251 * @param option an option bit. 252 * @param value true if the option is selected, false if the option is not selected. 253 * @exception ArrayIndexOutOfBoundsException if array index out of bound occurs. 254 * @see sun.security.krb5.internal.Krb5 255 */ 256 public void set(int option, boolean value) throws ArrayIndexOutOfBoundsException { 257 super.set(option, value); 258 } 259 260 /** 261 * Gets the value(true/false) for one of the <code>KDCOptions</code>. 262 * 263 * @param option an option bit. 264 * @return value true if the option is selected, false if the option is not selected. 265 * @exception ArrayIndexOutOfBoundsException if array index out of bound occurs. 266 * @see sun.security.krb5.internal.Krb5 267 */ 268 269 public boolean get(int option) throws ArrayIndexOutOfBoundsException { 270 return super.get(option); 271 } 272 273 @Override public String toString() { 274 StringBuilder sb = new StringBuilder(); 275 sb.append("KDCOptions: "); 276 for (int i=0; i<Krb5.KDC_OPTS_MAX+1; i++) { 277 if (get(i)) { 278 if (names[i] != null) { 279 sb.append(names[i]).append(","); 280 } else { 281 sb.append(i).append(","); 282 } 283 } 284 } 285 return sb.toString(); 286 } 287 288 private void setDefault() { 289 try { 290 291 Config config = Config.getInstance(); 292 293 // If key not present, returns Integer.MIN_VALUE, which is 294 // almost all zero. 295 296 int options = config.getIntValue("libdefaults", 297 "kdc_default_options"); 298 299 if ((options & KDC_OPT_RENEWABLE_OK) == KDC_OPT_RENEWABLE_OK) { 300 set(RENEWABLE_OK, true); 301 } else { 302 if (config.getBooleanObject("libdefaults", "renewable") == Boolean.TRUE) { 303 set(RENEWABLE_OK, true); 304 } 305 } 306 if ((options & KDC_OPT_PROXIABLE) == KDC_OPT_PROXIABLE) { 307 set(PROXIABLE, true); 308 } else { 309 if (config.getBooleanObject("libdefaults", "proxiable") == Boolean.TRUE) { 310 set(PROXIABLE, true); 311 } 312 } 313 314 if ((options & KDC_OPT_FORWARDABLE) == KDC_OPT_FORWARDABLE) { 315 set(FORWARDABLE, true); 316 } else { 317 if (config.getBooleanObject("libdefaults", "forwardable") == Boolean.TRUE) { 318 set(FORWARDABLE, true); 319 } 320 } 321 } catch (KrbException e) { 322 if (DEBUG) { 323 System.out.println("Exception in getting default values for " + 324 "KDC Options from the configuration "); 325 e.printStackTrace(); 326 327 } 328 } 329 } 330 }