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 * @compile -XDignore.symbol.file MaxRetries.java
28 * @run main/othervm/timeout=300 MaxRetries
29 * @summary support max_retries in krb5.conf
30 */
31
32 import java.io.*;
33 import java.net.DatagramSocket;
34 import java.security.Security;
35
36 public class MaxRetries {
37 public static void main(String[] args)
38 throws Exception {
39
40 System.setProperty("sun.security.krb5.debug", "true");
41 new OneKDC(null).writeJAASConf();
42
43 // An idle UDP socket to revent PortUnreachableException
44 DatagramSocket ds = new DatagramSocket(33333);
45
46 System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
47
48 // For tryLast
49 Security.setProperty("krb5.kdc.bad.policy", "trylast");
50 rewriteMaxRetries(4);
51 test1(4000, 6); // 1 1 1 1 2 2
52 test1(4000, 2); // 2 2
53
54 rewriteMaxRetries(1);
55 test1(1000, 3); // 1 2 2
56 test1(1000, 2); // 2 2
57
58 rewriteMaxRetries(-1);
59 test1(5000, 4); // 1 1 2 2
60 test1(5000, 2); // 2 2
61
62 // For tryLess
63 Security.setProperty("krb5.kdc.bad.policy", "tryless:1," + BadKdc.toReal(5000));
64 rewriteMaxRetries(4);
65 test1(4000, 7); // 1 1 1 1 2 1 2
66 test1(4000, 4); // 1 2 1 2
67
68 rewriteMaxRetries(1);
69 test1(1000, 4); // 1 2 1 2
70 test1(1000, 4); // 1 2 1 2
71
72 rewriteMaxRetries(-1);
73 test1(5000, 5); // 1 1 2 1 2
74 test1(5000, 4); // 1 2 1 2
75
76 rewriteUdpPrefLimit(-1, -1); // default, no limit
77 test2("UDP");
78
79 rewriteUdpPrefLimit(10, -1); // global rules
80 test2("TCP");
81
82 rewriteUdpPrefLimit(10, 10000); // realm rules
83 test2("UDP");
84
85 rewriteUdpPrefLimit(10000, 10); // realm rules
86 test2("TCP");
87
88 ds.close();
89 }
90
91 /**
92 * One round of test for max_retries and timeout.
93 * @param timeout the expected timeout
94 * @param count the expected total try
95 */
96 private static void test1(int timeout, int count) throws Exception {
97 String timeoutTag = "timeout=" + BadKdc.toReal(timeout);
98 ByteArrayOutputStream bo = new ByteArrayOutputStream();
99 PrintStream oldout = System.out;
100 System.setOut(new PrintStream(bo));
101 Context c = Context.fromJAAS("client");
102 System.setOut(oldout);
103
104 String[] lines = new String(bo.toByteArray()).split("\n");
105 System.out.println("----------------- TEST (" + timeout + "," +
106 count + ") -----------------");
107 for (String line: lines) {
108 if (line.startsWith(">>> KDCCommunication")) {
109 System.out.println(line);
110 if (line.indexOf(timeoutTag) < 0) {
111 throw new Exception("Wrong timeout value" + timeoutTag);
112 }
113 count--;
114 }
115 }
116 if (count != 0) {
117 throw new Exception("Retry count is " + count + " less");
118 }
119 }
120
121 /**
122 * One round of test for udp_preference_limit.
123 * @param proto the expected protocol used
124 */
125 private static void test2(String proto) throws Exception {
126 ByteArrayOutputStream bo = new ByteArrayOutputStream();
127 PrintStream oldout = System.out;
128 System.setOut(new PrintStream(bo));
129 Context c = Context.fromJAAS("client");
130 System.setOut(oldout);
131
132 int count = 2;
133 String[] lines = new String(bo.toByteArray()).split("\n");
134 System.out.println("----------------- TEST -----------------");
135 for (String line: lines) {
136 if (line.startsWith(">>> KDCCommunication")) {
137 System.out.println(line);
138 count--;
139 if (line.indexOf(proto) < 0) {
140 throw new Exception("Wrong timeout value");
141 }
142 }
143 }
144 if (count != 0) {
145 throw new Exception("Retry count is " + count + " less");
146 }
147 }
148
149 /**
150 * Set udp_preference_limit for global and realm
151 */
152 private static void rewriteUdpPrefLimit(int global, int realm)
153 throws Exception {
154 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF));
155 FileWriter fw = new FileWriter("alternative-krb5.conf");
156 while (true) {
157 String s = fr.readLine();
158 if (s == null) {
159 break;
160 }
161 if (s.startsWith("[realms]")) {
162 // Reconfig global setting
163 if (global != -1) {
164 fw.write("udp_preference_limit = " + global + "\n");
165 }
166 } else if (s.trim().startsWith("kdc = ")) {
167 if (realm != -1) {
168 // Reconfig for realm
169 fw.write(" udp_preference_limit = " + realm + "\n");
170 }
171 }
172 fw.write(s + "\n");
173 }
174 fr.close();
175 fw.close();
176 sun.security.krb5.Config.refresh();
177 }
178
179 /**
180 * Set max_retries and timeout value for realm. The global value is always
181 * 2 and 5000.
182 * @param value max_retries and timeout/1000 for a realm, -1 means none.
183 */
184 private static void rewriteMaxRetries(int value) throws Exception {
185 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF));
186 FileWriter fw = new FileWriter("alternative-krb5.conf");
187 while (true) {
188 String s = fr.readLine();
189 if (s == null) {
190 break;
191 }
192 if (s.startsWith("[realms]")) {
193 // Reconfig global setting
194 fw.write("max_retries = 2\n");
195 fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n");
196 } else if (s.trim().startsWith("kdc = ")) {
197 if (value != -1) {
198 // Reconfig for realm
199 fw.write(" max_retries = " + value + "\n");
200 fw.write(" kdc_timeout = " + BadKdc.toReal(value*1000) + "\n");
201 }
202 // Add a bad KDC as the first candidate
203 fw.write(" kdc = localhost:33333\n");
204 }
205 fw.write(s + "\n");
206 }
207 fr.close();
208 fw.close();
209 sun.security.krb5.Config.refresh();
210 }
211 }
|
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 * @compile -XDignore.symbol.file MaxRetries.java
28 * @run main/othervm/timeout=300 MaxRetries
29 * @summary support max_retries in krb5.conf
30 */
31
32 import javax.security.auth.login.LoginException;
33 import java.io.*;
34 import java.net.DatagramSocket;
35 import java.security.Security;
36
37 public class MaxRetries {
38
39 static int idlePort = -1;
40 static CommMatcher cm = new CommMatcher();
41
42 public static void main(String[] args)
43 throws Exception {
44
45 System.setProperty("sun.security.krb5.debug", "true");
46 OneKDC kdc = new OneKDC(null).writeJAASConf();
47
48 // An idle UDP socket to prevent PortUnreachableException
49 DatagramSocket ds = new DatagramSocket();
50 idlePort = ds.getLocalPort();
51
52 cm.addPort(idlePort);
53 cm.addPort(kdc.getPort());
54
55 System.setProperty("java.security.krb5.conf", "alternative-krb5.conf");
56
57 Security.setProperty("krb5.kdc.bad.policy", "trylast");
58
59 // We always make the real timeout to be 1 second
60 BadKdc.setRatio(0.25f);
61 rewriteMaxRetries(4);
62
63 // Explanation: In this case, max_retries=4 and timeout=4s.
64 // For AS-REQ without preauth, we will see 4 4s timeout on kdc#1
65 // ("a4" repeat 4 times), and one 4s timeout on kdc#2 ("b4"). For
66 // AS-REQ with preauth, one 4s timeout on kdc#2 (second "b4").
67 // we tolerate 4 real timeout on kdc#2, so make it "(b4){2,6}".
68 test1("a4a4a4a4b4b4", "a4a4a4a4(b4){2,6}");
69 test1("b4b4", "(b4){2,6}");
70
71 BadKdc.setRatio(1f);
72 rewriteMaxRetries(1);
73 // Explanation: Since max_retries=1 only, we could fail in 1st or 2nd
74 // AS-REQ to kdc#2.
75 String actual = test1("a1b1b1", "(a1b1b1|a1b1x|a1b1b1x)");
76 if (actual.endsWith("x")) {
77 // If 1st attempt fails, all bads are back available
78 test1("a1b1b1", "(a1b1b1|a1b1x|a1b1b1x)");
79 } else {
80 test1("b1b1", "(b1b1|b1x|b1b1x)");
81 }
82
83 BadKdc.setRatio(0.2f);
84 rewriteMaxRetries(-1);
85 test1("a5a5a5b5b5", "a5a5a5(b5){2,4}");
86 test1("b5b5", "(b5){2,4}");
87
88 BadKdc.setRatio(0.25f);
89 Security.setProperty("krb5.kdc.bad.policy",
90 "tryless:1,1000");
91 rewriteMaxRetries(4);
92 test1("a4a4a4a4b4a4b4", "a4a4a4a4(b4){1,3}a4(b4){1,3}");
93 test1("a4b4a4b4", "a4(b4){1,3}a4(b4){1,3}");
94
95 BadKdc.setRatio(1f);
96 rewriteMaxRetries(1);
97 actual = test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)");
98 if (actual.endsWith("x")) {
99 test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)");
100 } else {
101 test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)");
102 }
103
104 BadKdc.setRatio(.2f);
105 rewriteMaxRetries(-1);
106 test1("a5a5a5b5a5b5", "a5a5a5(b5){1,2}a5(b5){1,2}");
107 test1("a5b5a5b5", "a5(b5){1,2}a5(b5){1,2}");
108
109 BadKdc.setRatio(1f);
110 rewriteMaxRetries(2);
111 if (BadKdc.toReal(2000) > 1000) {
112 // Explanation: if timeout is longer than 1s in tryLess,
113 // we will see "a1" at 2nd kdc#1 access
114 test1("a2a2b2a1b2", "a2a2(b2){1,2}a1(b2){1,2}");
115 } else {
116 test1("a2a2b2a2b2", "a2a2(b2){1,2}a2(b2){1,2}");
117 }
118
119 BadKdc.setRatio(1f);
120
121 rewriteUdpPrefLimit(-1, -1); // default, no limit
122 test2("UDP");
123
124 rewriteUdpPrefLimit(10, -1); // global rules
125 test2("TCP");
126
127 rewriteUdpPrefLimit(10, 10000); // realm rules
128 test2("UDP");
129
130 rewriteUdpPrefLimit(10000, 10); // realm rules
131 test2("TCP");
132
133 ds.close();
134 }
135
136 /**
137 * One round of test for max_retries and timeout.
138 *
139 * @param exact the expected exact match, where no timeout
140 * happens for real KDCs
141 * @param relaxed the expected relaxed match, where some timeout
142 * could happen for real KDCs
143 * @return the actual result
144 */
145 private static String test1(String exact, String relaxed) throws Exception {
146 ByteArrayOutputStream bo = new ByteArrayOutputStream();
147 PrintStream oldout = System.out;
148 System.setOut(new PrintStream(bo));
149 boolean failed = false;
150 long start = System.nanoTime();
151 try {
152 Context c = Context.fromJAAS("client");
153 } catch (LoginException e) {
154 failed = true;
155 }
156 System.setOut(oldout);
157
158 String[] lines = new String(bo.toByteArray()).split("\n");
159 System.out.println("----------------- TEST (" + exact
160 + ") -----------------");
161
162 // Result, a series of timeout + kdc#
163 StringBuilder sb = new StringBuilder();
164 for (String line: lines) {
165 if (cm.match(line)) {
166 System.out.println(line);
167 sb.append(cm.kdc()).append(cm.timeout());
168 }
169 }
170 if (failed) {
171 sb.append("x");
172 }
173 System.out.println("Time: " + (System.nanoTime() - start) / 1000000000d);
174 String actual = sb.toString();
175 System.out.println("Actual: " + actual);
176 if (actual.equals(exact)) {
177 System.out.println("Exact match: " + exact);
178 } else if (actual.matches(relaxed)) {
179 System.out.println("!!!! Tolerant match: " + relaxed);
180 } else {
181 throw new Exception("Match neither " + exact + " nor " + relaxed);
182 }
183 return actual;
184 }
185
186 /**
187 * One round of test for udp_preference_limit.
188 * @param proto the expected protocol used
189 */
190 private static void test2(String proto) throws Exception {
191 ByteArrayOutputStream bo = new ByteArrayOutputStream();
192 PrintStream oldout = System.out;
193 System.setOut(new PrintStream(bo));
194 Context c = Context.fromJAAS("client");
195 System.setOut(oldout);
196
197 int count = 2;
198 String[] lines = new String(bo.toByteArray()).split("\n");
199 System.out.println("----------------- TEST -----------------");
200 for (String line: lines) {
201 if (cm.match(line)) {
202 System.out.println(line);
203 count--;
204 if (!cm.protocol().equals(proto)) {
205 throw new Exception("Wrong protocol value");
206 }
207 }
208 }
209 if (count != 0) {
210 throw new Exception("Retry count is " + count + " less");
211 }
212 }
213
214 /**
215 * Set udp_preference_limit for global and realm
216 */
217 private static void rewriteUdpPrefLimit(int global, int realm)
218 throws Exception {
219 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF));
220 FileWriter fw = new FileWriter("alternative-krb5.conf");
221 while (true) {
222 String s = fr.readLine();
223 if (s == null) {
224 break;
225 }
226 if (s.startsWith("[realms]")) {
227 // Reconfig global setting
228 fw.write("kdc_timeout = 5000\n");
229 if (global != -1) {
230 fw.write("udp_preference_limit = " + global + "\n");
231 }
232 } else if (s.trim().startsWith("kdc = ")) {
233 if (realm != -1) {
234 // Reconfig for realm
235 fw.write(" udp_preference_limit = " + realm + "\n");
236 }
237 }
238 fw.write(s + "\n");
239 }
240 fr.close();
241 fw.close();
242 sun.security.krb5.Config.refresh();
243 }
244
245 /**
246 * Set max_retries and timeout value for realm. The global value is always
247 * 3 and 5000.
248 *
249 * @param value max_retries and timeout/1000 for a realm, -1 means none.
250 */
251 private static void rewriteMaxRetries(int value) throws Exception {
252 BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF));
253 FileWriter fw = new FileWriter("alternative-krb5.conf");
254 while (true) {
255 String s = fr.readLine();
256 if (s == null) {
257 break;
258 }
259 if (s.startsWith("[realms]")) {
260 // Reconfig global setting
261 fw.write("max_retries = 3\n");
262 fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n");
263 } else if (s.trim().startsWith("kdc = ")) {
264 if (value != -1) {
265 // Reconfig for realm
266 fw.write(" max_retries = " + value + "\n");
267 fw.write(" kdc_timeout = " + BadKdc.toReal(value*1000) + "\n");
268 }
269 // Add a bad KDC as the first candidate
270 fw.write(" kdc = localhost:" + idlePort + "\n");
271 }
272 fw.write(s + "\n");
273 }
274 fr.close();
275 fw.close();
276 sun.security.krb5.Config.refresh();
277 }
278 }
|