1 /* 2 * Copyright (c) 2010, 2012, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6844193 27 * @modules java.base/sun.net.spi.nameservice 28 * java.base/sun.security.util 29 * java.security.jgss/sun.security.krb5 30 * java.security.jgss/sun.security.krb5.internal 31 * java.security.jgss/sun.security.krb5.internal.ccache 32 * java.security.jgss/sun.security.krb5.internal.crypto 33 * java.security.jgss/sun.security.krb5.internal.ktab 34 * @compile -XDignore.symbol.file MaxRetries.java 35 * @run main/othervm/timeout=300 MaxRetries 36 * @summary support max_retries in krb5.conf 37 */ 38 39 import java.io.*; 40 import java.net.DatagramSocket; 41 import java.security.Security; 42 43 public class MaxRetries { 44 public static void main(String[] args) 45 throws Exception { 46 47 System.setProperty("sun.security.krb5.debug", "true"); 48 new OneKDC(null).writeJAASConf(); 49 50 // An idle UDP socket to revent PortUnreachableException 51 DatagramSocket ds = new DatagramSocket(33333); 52 53 System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); 54 55 // For tryLast 56 Security.setProperty("krb5.kdc.bad.policy", "trylast"); 57 rewriteMaxRetries(4); 58 test1(4000, 6); // 1 1 1 1 2 2 59 test1(4000, 2); // 2 2 60 61 rewriteMaxRetries(1); 62 test1(1000, 3); // 1 2 2 63 test1(1000, 2); // 2 2 64 65 rewriteMaxRetries(-1); 66 test1(5000, 4); // 1 1 2 2 67 test1(5000, 2); // 2 2 68 69 // For tryLess 70 Security.setProperty("krb5.kdc.bad.policy", "tryless:1," + BadKdc.toReal(5000)); 71 rewriteMaxRetries(4); 72 test1(4000, 7); // 1 1 1 1 2 1 2 73 test1(4000, 4); // 1 2 1 2 74 75 rewriteMaxRetries(1); 76 test1(1000, 4); // 1 2 1 2 77 test1(1000, 4); // 1 2 1 2 78 79 rewriteMaxRetries(-1); 80 test1(5000, 5); // 1 1 2 1 2 81 test1(5000, 4); // 1 2 1 2 82 83 rewriteUdpPrefLimit(-1, -1); // default, no limit 84 test2("UDP"); 85 86 rewriteUdpPrefLimit(10, -1); // global rules 87 test2("TCP"); 88 89 rewriteUdpPrefLimit(10, 10000); // realm rules 90 test2("UDP"); 91 92 rewriteUdpPrefLimit(10000, 10); // realm rules 93 test2("TCP"); 94 95 ds.close(); 96 } 97 98 /** 99 * One round of test for max_retries and timeout. 100 * @param timeout the expected timeout 101 * @param count the expected total try 102 */ 103 private static void test1(int timeout, int count) throws Exception { 104 String timeoutTag = "timeout=" + BadKdc.toReal(timeout); 105 ByteArrayOutputStream bo = new ByteArrayOutputStream(); 106 PrintStream oldout = System.out; 107 System.setOut(new PrintStream(bo)); 108 Context c = Context.fromJAAS("client"); 109 System.setOut(oldout); 110 111 String[] lines = new String(bo.toByteArray()).split("\n"); 112 System.out.println("----------------- TEST (" + timeout + "," + 113 count + ") -----------------"); 114 for (String line: lines) { 115 if (line.startsWith(">>> KDCCommunication")) { 116 System.out.println(line); 117 if (line.indexOf(timeoutTag) < 0) { 118 throw new Exception("Wrong timeout value" + timeoutTag); 119 } 120 count--; 121 } 122 } 123 if (count != 0) { 124 throw new Exception("Retry count is " + count + " less"); 125 } 126 } 127 128 /** 129 * One round of test for udp_preference_limit. 130 * @param proto the expected protocol used 131 */ 132 private static void test2(String proto) throws Exception { 133 ByteArrayOutputStream bo = new ByteArrayOutputStream(); 134 PrintStream oldout = System.out; 135 System.setOut(new PrintStream(bo)); 136 Context c = Context.fromJAAS("client"); 137 System.setOut(oldout); 138 139 int count = 2; 140 String[] lines = new String(bo.toByteArray()).split("\n"); 141 System.out.println("----------------- TEST -----------------"); 142 for (String line: lines) { 143 if (line.startsWith(">>> KDCCommunication")) { 144 System.out.println(line); 145 count--; 146 if (line.indexOf(proto) < 0) { 147 throw new Exception("Wrong timeout value"); 148 } 149 } 150 } 151 if (count != 0) { 152 throw new Exception("Retry count is " + count + " less"); 153 } 154 } 155 156 /** 157 * Set udp_preference_limit for global and realm 158 */ 159 private static void rewriteUdpPrefLimit(int global, int realm) 160 throws Exception { 161 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF)); 162 FileWriter fw = new FileWriter("alternative-krb5.conf"); 163 while (true) { 164 String s = fr.readLine(); 165 if (s == null) { 166 break; 167 } 168 if (s.startsWith("[realms]")) { 169 // Reconfig global setting 170 if (global != -1) { 171 fw.write("udp_preference_limit = " + global + "\n"); 172 } 173 } else if (s.trim().startsWith("kdc = ")) { 174 if (realm != -1) { 175 // Reconfig for realm 176 fw.write(" udp_preference_limit = " + realm + "\n"); 177 } 178 } 179 fw.write(s + "\n"); 180 } 181 fr.close(); 182 fw.close(); 183 sun.security.krb5.Config.refresh(); 184 } 185 186 /** 187 * Set max_retries and timeout value for realm. The global value is always 188 * 2 and 5000. 189 * @param value max_retries and timeout/1000 for a realm, -1 means none. 190 */ 191 private static void rewriteMaxRetries(int value) throws Exception { 192 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF)); 193 FileWriter fw = new FileWriter("alternative-krb5.conf"); 194 while (true) { 195 String s = fr.readLine(); 196 if (s == null) { 197 break; 198 } 199 if (s.startsWith("[realms]")) { 200 // Reconfig global setting 201 fw.write("max_retries = 2\n"); 202 fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n"); 203 } else if (s.trim().startsWith("kdc = ")) { 204 if (value != -1) { 205 // Reconfig for realm 206 fw.write(" max_retries = " + value + "\n"); 207 fw.write(" kdc_timeout = " + BadKdc.toReal(value*1000) + "\n"); 208 } 209 // Add a bad KDC as the first candidate 210 fw.write(" kdc = localhost:33333\n"); 211 } 212 fw.write(s + "\n"); 213 } 214 fr.close(); 215 fw.close(); 216 sun.security.krb5.Config.refresh(); 217 } 218 }