Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/net/SocketPermission.java
+++ new/src/share/classes/java/net/SocketPermission.java
1 1 /*
2 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 package java.net;
27 27
28 28 import java.util.Enumeration;
29 29 import java.util.Vector;
30 30 import java.util.List;
31 31 import java.util.ArrayList;
32 32 import java.util.Collections;
33 33 import java.util.StringTokenizer;
34 34 import java.net.InetAddress;
35 35 import java.security.Permission;
36 36 import java.security.PermissionCollection;
37 37 import java.io.Serializable;
38 38 import java.io.ObjectStreamField;
39 39 import java.io.ObjectOutputStream;
40 40 import java.io.ObjectInputStream;
41 41 import java.io.IOException;
42 42 import sun.net.util.IPAddressUtil;
43 43 import sun.net.RegisteredDomain;
44 44 import sun.security.util.SecurityConstants;
45 45 import sun.security.util.Debug;
46 46
47 47
48 48 /**
49 49 * This class represents access to a network via sockets.
50 50 * A SocketPermission consists of a
51 51 * host specification and a set of "actions" specifying ways to
52 52 * connect to that host. The host is specified as
53 53 * <pre>
54 54 * host = (hostname | IPv4address | iPv6reference) [:portrange]
55 55 * portrange = portnumber | -portnumber | portnumber-[portnumber]
56 56 * </pre>
57 57 * The host is expressed as a DNS name, as a numerical IP address,
58 58 * or as "localhost" (for the local machine).
59 59 * The wildcard "*" may be included once in a DNS name host
60 60 * specification. If it is included, it must be in the leftmost
61 61 * position, as in "*.sun.com".
62 62 * <p>
63 63 * The format of the IPv6reference should follow that specified in <a
64 64 * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC 2732: Format
65 65 * for Literal IPv6 Addresses in URLs</i></a>:
66 66 * <pre>
67 67 * ipv6reference = "[" IPv6address "]"
68 68 *</pre>
69 69 * For example, you can construct a SocketPermission instance
70 70 * as the following:
71 71 * <pre>
72 72 * String hostAddress = inetaddress.getHostAddress();
73 73 * if (inetaddress instanceof Inet6Address) {
74 74 * sp = new SocketPermission("[" + hostAddress + "]:" + port, action);
75 75 * } else {
76 76 * sp = new SocketPermission(hostAddress + ":" + port, action);
77 77 * }
78 78 * </pre>
79 79 * or
80 80 * <pre>
81 81 * String host = url.getHost();
82 82 * sp = new SocketPermission(host + ":" + port, action);
83 83 * </pre>
84 84 * <p>
85 85 * The <A HREF="Inet6Address.html#lform">full uncompressed form</A> of
86 86 * an IPv6 literal address is also valid.
87 87 * <p>
88 88 * The port or portrange is optional. A port specification of the
89 89 * form "N-", where <i>N</i> is a port number, signifies all ports
90 90 * numbered <i>N</i> and above, while a specification of the
91 91 * form "-N" indicates all ports numbered <i>N</i> and below.
92 92 * <p>
93 93 * The possible ways to connect to the host are
94 94 * <pre>
95 95 * accept
96 96 * connect
97 97 * listen
98 98 * resolve
99 99 * </pre>
100 100 * The "listen" action is only meaningful when used with "localhost".
101 101 * The "resolve" action is implied when any of the other actions are present.
102 102 * The action "resolve" refers to host/ip name service lookups.
103 103 * <P>
104 104 * The actions string is converted to lowercase before processing.
105 105 * <p>As an example of the creation and meaning of SocketPermissions,
106 106 * note that if the following permission:
107 107 *
108 108 * <pre>
109 109 * p1 = new SocketPermission("puffin.eng.sun.com:7777", "connect,accept");
110 110 * </pre>
111 111 *
112 112 * is granted to some code, it allows that code to connect to port 7777 on
113 113 * <code>puffin.eng.sun.com</code>, and to accept connections on that port.
114 114 *
115 115 * <p>Similarly, if the following permission:
116 116 *
117 117 * <pre>
118 118 * p2 = new SocketPermission("localhost:1024-", "accept,connect,listen");
119 119 * </pre>
120 120 *
121 121 * is granted to some code, it allows that code to
122 122 * accept connections on, connect to, or listen on any port between
123 123 * 1024 and 65535 on the local host.
124 124 *
125 125 * <p>Note: Granting code permission to accept or make connections to remote
126 126 * hosts may be dangerous because malevolent code can then more easily
127 127 * transfer and share confidential data among parties who may not
128 128 * otherwise have access to the data.
129 129 *
130 130 * @see java.security.Permissions
131 131 * @see SocketPermission
132 132 *
133 133 *
134 134 * @author Marianne Mueller
135 135 * @author Roland Schemers
136 136 *
137 137 * @serial exclude
138 138 */
139 139
140 140 public final class SocketPermission extends Permission
141 141 implements java.io.Serializable
142 142 {
143 143 private static final long serialVersionUID = -7204263841984476862L;
144 144
145 145 /**
146 146 * Connect to host:port
147 147 */
148 148 private final static int CONNECT = 0x1;
149 149
150 150 /**
151 151 * Listen on host:port
152 152 */
153 153 private final static int LISTEN = 0x2;
154 154
155 155 /**
156 156 * Accept a connection from host:port
157 157 */
158 158 private final static int ACCEPT = 0x4;
159 159
160 160 /**
161 161 * Resolve DNS queries
162 162 */
163 163 private final static int RESOLVE = 0x8;
164 164
165 165 /**
166 166 * No actions
167 167 */
168 168 private final static int NONE = 0x0;
169 169
170 170 /**
171 171 * All actions
172 172 */
173 173 private final static int ALL = CONNECT|LISTEN|ACCEPT|RESOLVE;
174 174
175 175 // various port constants
176 176 private static final int PORT_MIN = 0;
177 177 private static final int PORT_MAX = 65535;
178 178 private static final int PRIV_PORT_MAX = 1023;
179 179
180 180 // the actions mask
181 181 private transient int mask;
182 182
183 183 /**
184 184 * the actions string.
185 185 *
186 186 * @serial
187 187 */
188 188
189 189 private String actions; // Left null as long as possible, then
190 190 // created and re-used in the getAction function.
191 191
192 192 // hostname part as it is passed
193 193 private transient String hostname;
194 194
195 195 // the canonical name of the host
196 196 // in the case of "*.foo.com", cname is ".foo.com".
197 197
198 198 private transient String cname;
199 199
200 200 // all the IP addresses of the host
201 201 private transient InetAddress[] addresses;
202 202
203 203 // true if the hostname is a wildcard (e.g. "*.sun.com")
204 204 private transient boolean wildcard;
205 205
206 206 // true if we were initialized with a single numeric IP address
207 207 private transient boolean init_with_ip;
208 208
209 209 // true if this SocketPermission represents an invalid/unknown host
210 210 // used for implies when the delayed lookup has already failed
211 211 private transient boolean invalid;
212 212
213 213 // port range on host
214 214 private transient int[] portrange;
215 215
216 216 private transient boolean defaultDeny = false;
217 217
218 218 // true if this SocketPermission represents a hostname
219 219 // that failed our reverse mapping heuristic test
220 220 private transient boolean untrusted;
221 221 private transient boolean trusted;
222 222
223 223 // true if the sun.net.trustNameService system property is set
224 224 private static boolean trustNameService;
225 225
226 226 private static Debug debug = null;
227 227 private static boolean debugInit = false;
228 228
229 229 static {
230 230 Boolean tmp = java.security.AccessController.doPrivileged(
231 231 new sun.security.action.GetBooleanAction("sun.net.trustNameService"));
232 232 trustNameService = tmp.booleanValue();
233 233 }
234 234
235 235 private static synchronized Debug getDebug()
236 236 {
237 237 if (!debugInit) {
238 238 debug = Debug.getInstance("access");
239 239 debugInit = true;
240 240 }
241 241 return debug;
242 242 }
243 243
244 244 /**
245 245 * Creates a new SocketPermission object with the specified actions.
246 246 * The host is expressed as a DNS name, or as a numerical IP address.
247 247 * Optionally, a port or a portrange may be supplied (separated
248 248 * from the DNS name or IP address by a colon).
249 249 * <p>
250 250 * To specify the local machine, use "localhost" as the <i>host</i>.
251 251 * Also note: An empty <i>host</i> String ("") is equivalent to "localhost".
252 252 * <p>
253 253 * The <i>actions</i> parameter contains a comma-separated list of the
254 254 * actions granted for the specified host (and port(s)). Possible actions are
255 255 * "connect", "listen", "accept", "resolve", or
256 256 * any combination of those. "resolve" is automatically added
257 257 * when any of the other three are specified.
258 258 * <p>
259 259 * Examples of SocketPermission instantiation are the following:
260 260 * <pre>
261 261 * nr = new SocketPermission("www.catalog.com", "connect");
262 262 * nr = new SocketPermission("www.sun.com:80", "connect");
263 263 * nr = new SocketPermission("*.sun.com", "connect");
264 264 * nr = new SocketPermission("*.edu", "resolve");
265 265 * nr = new SocketPermission("204.160.241.0", "connect");
266 266 * nr = new SocketPermission("localhost:1024-65535", "listen");
267 267 * nr = new SocketPermission("204.160.241.0:1024-65535", "connect");
268 268 * </pre>
269 269 *
270 270 * @param host the hostname or IPaddress of the computer, optionally
271 271 * including a colon followed by a port or port range.
272 272 * @param action the action string.
273 273 */
274 274 public SocketPermission(String host, String action) {
275 275 super(getHost(host));
276 276 // name initialized to getHost(host); NPE detected in getHost()
277 277 init(getName(), getMask(action));
278 278 }
279 279
280 280
281 281 SocketPermission(String host, int mask) {
282 282 super(getHost(host));
283 283 // name initialized to getHost(host); NPE detected in getHost()
284 284 init(getName(), mask);
285 285 }
286 286
287 287 private void setDeny() {
288 288 defaultDeny = true;
289 289 }
290 290
291 291 private static String getHost(String host)
292 292 {
293 293 if (host.equals("")) {
294 294 return "localhost";
295 295 } else {
296 296 /* IPv6 literal address used in this context should follow
297 297 * the format specified in RFC 2732;
298 298 * if not, we try to solve the unambiguous case
299 299 */
300 300 int ind;
301 301 if (host.charAt(0) != '[') {
302 302 if ((ind = host.indexOf(':')) != host.lastIndexOf(':')) {
303 303 /* More than one ":", meaning IPv6 address is not
304 304 * in RFC 2732 format;
305 305 * We will rectify user errors for all unambiguious cases
306 306 */
307 307 StringTokenizer st = new StringTokenizer(host, ":");
308 308 int tokens = st.countTokens();
309 309 if (tokens == 9) {
310 310 // IPv6 address followed by port
311 311 ind = host.lastIndexOf(':');
312 312 host = "[" + host.substring(0, ind) + "]" +
313 313 host.substring(ind);
314 314 } else if (tokens == 8 && host.indexOf("::") == -1) {
315 315 // IPv6 address only, not followed by port
316 316 host = "[" + host + "]";
317 317 } else {
318 318 // could be ambiguous
319 319 throw new IllegalArgumentException("Ambiguous"+
320 320 " hostport part");
321 321 }
322 322 }
323 323 }
324 324 return host;
325 325 }
326 326 }
327 327
328 328 private int[] parsePort(String port)
329 329 throws Exception
330 330 {
331 331
332 332 if (port == null || port.equals("") || port.equals("*")) {
333 333 return new int[] {PORT_MIN, PORT_MAX};
334 334 }
335 335
336 336 int dash = port.indexOf('-');
337 337
338 338 if (dash == -1) {
339 339 int p = Integer.parseInt(port);
340 340 return new int[] {p, p};
341 341 } else {
342 342 String low = port.substring(0, dash);
343 343 String high = port.substring(dash+1);
344 344 int l,h;
345 345
346 346 if (low.equals("")) {
347 347 l = PORT_MIN;
348 348 } else {
349 349 l = Integer.parseInt(low);
350 350 }
351 351
352 352 if (high.equals("")) {
353 353 h = PORT_MAX;
354 354 } else {
355 355 h = Integer.parseInt(high);
356 356 }
357 357 if (l < 0 || h < 0 || h<l)
358 358 throw new IllegalArgumentException("invalid port range");
359 359
360 360 return new int[] {l, h};
361 361 }
362 362 }
363 363
364 364 /**
365 365 * Initialize the SocketPermission object. We don't do any DNS lookups
366 366 * as this point, instead we hold off until the implies method is
367 367 * called.
368 368 */
369 369 private void init(String host, int mask) {
370 370 // Set the integer mask that represents the actions
371 371
372 372 if ((mask & ALL) != mask)
373 373 throw new IllegalArgumentException("invalid actions mask");
374 374
375 375 // always OR in RESOLVE if we allow any of the others
376 376 this.mask = mask | RESOLVE;
377 377
378 378 // Parse the host name. A name has up to three components, the
379 379 // hostname, a port number, or two numbers representing a port
380 380 // range. "www.sun.com:8080-9090" is a valid host name.
381 381
382 382 // With IPv6 an address can be 2010:836B:4179::836B:4179
383 383 // An IPv6 address needs to be enclose in []
384 384 // For ex: [2010:836B:4179::836B:4179]:8080-9090
385 385 // Refer to RFC 2732 for more information.
386 386
387 387 int rb = 0 ;
388 388 int start = 0, end = 0;
389 389 int sep = -1;
390 390 String hostport = host;
391 391 if (host.charAt(0) == '[') {
392 392 start = 1;
393 393 rb = host.indexOf(']');
394 394 if (rb != -1) {
395 395 host = host.substring(start, rb);
396 396 } else {
397 397 throw new
398 398 IllegalArgumentException("invalid host/port: "+host);
399 399 }
400 400 sep = hostport.indexOf(':', rb+1);
401 401 } else {
402 402 start = 0;
403 403 sep = host.indexOf(':', rb);
404 404 end = sep;
405 405 if (sep != -1) {
406 406 host = host.substring(start, end);
407 407 }
408 408 }
409 409
410 410 if (sep != -1) {
411 411 String port = hostport.substring(sep+1);
412 412 try {
413 413 portrange = parsePort(port);
414 414 } catch (Exception e) {
415 415 throw new
416 416 IllegalArgumentException("invalid port range: "+port);
417 417 }
418 418 } else {
419 419 portrange = new int[] { PORT_MIN, PORT_MAX };
420 420 }
421 421
422 422 hostname = host;
423 423
424 424 // is this a domain wildcard specification
425 425 if (host.lastIndexOf('*') > 0) {
426 426 throw new
427 427 IllegalArgumentException("invalid host wildcard specification");
428 428 } else if (host.startsWith("*")) {
429 429 wildcard = true;
430 430 if (host.equals("*")) {
431 431 cname = "";
432 432 } else if (host.startsWith("*.")) {
433 433 cname = host.substring(1).toLowerCase();
434 434 } else {
435 435 throw new
436 436 IllegalArgumentException("invalid host wildcard specification");
437 437 }
438 438 return;
439 439 } else {
440 440 if (host.length() > 0) {
441 441 // see if we are being initialized with an IP address.
442 442 char ch = host.charAt(0);
443 443 if (ch == ':' || Character.digit(ch, 16) != -1) {
444 444 byte ip[] = IPAddressUtil.textToNumericFormatV4(host);
445 445 if (ip == null) {
446 446 ip = IPAddressUtil.textToNumericFormatV6(host);
447 447 }
448 448 if (ip != null) {
449 449 try {
450 450 addresses =
451 451 new InetAddress[]
452 452 {InetAddress.getByAddress(ip) };
453 453 init_with_ip = true;
454 454 } catch (UnknownHostException uhe) {
455 455 // this shouldn't happen
456 456 invalid = true;
457 457 }
458 458 }
459 459 }
460 460 }
461 461 }
462 462 }
463 463
464 464 /**
465 465 * Convert an action string to an integer actions mask.
466 466 *
467 467 * @param action the action string
468 468 * @return the action mask
469 469 */
470 470 private static int getMask(String action) {
471 471
472 472 if (action == null) {
473 473 throw new NullPointerException("action can't be null");
474 474 }
475 475
476 476 if (action.equals("")) {
477 477 throw new IllegalArgumentException("action can't be empty");
478 478 }
479 479
480 480 int mask = NONE;
481 481
482 482 // Check against use of constants (used heavily within the JDK)
483 483 if (action == SecurityConstants.SOCKET_RESOLVE_ACTION) {
484 484 return RESOLVE;
485 485 } else if (action == SecurityConstants.SOCKET_CONNECT_ACTION) {
486 486 return CONNECT;
487 487 } else if (action == SecurityConstants.SOCKET_LISTEN_ACTION) {
488 488 return LISTEN;
489 489 } else if (action == SecurityConstants.SOCKET_ACCEPT_ACTION) {
490 490 return ACCEPT;
491 491 } else if (action == SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION) {
492 492 return CONNECT|ACCEPT;
493 493 }
494 494
495 495 char[] a = action.toCharArray();
496 496
497 497 int i = a.length - 1;
498 498 if (i < 0)
499 499 return mask;
500 500
501 501 while (i != -1) {
502 502 char c;
503 503
504 504 // skip whitespace
505 505 while ((i!=-1) && ((c = a[i]) == ' ' ||
506 506 c == '\r' ||
507 507 c == '\n' ||
508 508 c == '\f' ||
509 509 c == '\t'))
510 510 i--;
511 511
512 512 // check for the known strings
513 513 int matchlen;
514 514
515 515 if (i >= 6 && (a[i-6] == 'c' || a[i-6] == 'C') &&
516 516 (a[i-5] == 'o' || a[i-5] == 'O') &&
517 517 (a[i-4] == 'n' || a[i-4] == 'N') &&
518 518 (a[i-3] == 'n' || a[i-3] == 'N') &&
519 519 (a[i-2] == 'e' || a[i-2] == 'E') &&
520 520 (a[i-1] == 'c' || a[i-1] == 'C') &&
521 521 (a[i] == 't' || a[i] == 'T'))
522 522 {
523 523 matchlen = 7;
524 524 mask |= CONNECT;
525 525
526 526 } else if (i >= 6 && (a[i-6] == 'r' || a[i-6] == 'R') &&
527 527 (a[i-5] == 'e' || a[i-5] == 'E') &&
528 528 (a[i-4] == 's' || a[i-4] == 'S') &&
529 529 (a[i-3] == 'o' || a[i-3] == 'O') &&
530 530 (a[i-2] == 'l' || a[i-2] == 'L') &&
531 531 (a[i-1] == 'v' || a[i-1] == 'V') &&
532 532 (a[i] == 'e' || a[i] == 'E'))
533 533 {
534 534 matchlen = 7;
535 535 mask |= RESOLVE;
536 536
537 537 } else if (i >= 5 && (a[i-5] == 'l' || a[i-5] == 'L') &&
538 538 (a[i-4] == 'i' || a[i-4] == 'I') &&
539 539 (a[i-3] == 's' || a[i-3] == 'S') &&
540 540 (a[i-2] == 't' || a[i-2] == 'T') &&
541 541 (a[i-1] == 'e' || a[i-1] == 'E') &&
542 542 (a[i] == 'n' || a[i] == 'N'))
543 543 {
544 544 matchlen = 6;
545 545 mask |= LISTEN;
546 546
547 547 } else if (i >= 5 && (a[i-5] == 'a' || a[i-5] == 'A') &&
548 548 (a[i-4] == 'c' || a[i-4] == 'C') &&
549 549 (a[i-3] == 'c' || a[i-3] == 'C') &&
550 550 (a[i-2] == 'e' || a[i-2] == 'E') &&
551 551 (a[i-1] == 'p' || a[i-1] == 'P') &&
552 552 (a[i] == 't' || a[i] == 'T'))
553 553 {
554 554 matchlen = 6;
555 555 mask |= ACCEPT;
556 556
557 557 } else {
558 558 // parse error
559 559 throw new IllegalArgumentException(
560 560 "invalid permission: " + action);
561 561 }
562 562
563 563 // make sure we didn't just match the tail of a word
564 564 // like "ackbarfaccept". Also, skip to the comma.
565 565 boolean seencomma = false;
566 566 while (i >= matchlen && !seencomma) {
567 567 switch(a[i-matchlen]) {
568 568 case ',':
569 569 seencomma = true;
570 570 /*FALLTHROUGH*/
571 571 case ' ': case '\r': case '\n':
572 572 case '\f': case '\t':
573 573 break;
574 574 default:
575 575 throw new IllegalArgumentException(
576 576 "invalid permission: " + action);
577 577 }
578 578 i--;
579 579 }
580 580
581 581 // point i at the location of the comma minus one (or -1).
582 582 i -= matchlen;
583 583 }
584 584
585 585 return mask;
586 586 }
587 587
588 588 private boolean isUntrusted()
589 589 throws UnknownHostException
590 590 {
591 591 if (trusted) return false;
592 592 if (invalid || untrusted) return true;
593 593 try {
594 594 if (!trustNameService && (defaultDeny ||
595 595 sun.net.www.URLConnection.isProxiedHost(hostname))) {
596 596 if (this.cname == null) {
597 597 this.getCanonName();
598 598 }
599 599 if (!match(cname, hostname)) {
600 600 // Last chance
601 601 if (!authorized(hostname, addresses[0].getAddress())) {
602 602 untrusted = true;
603 603 Debug debug = getDebug();
604 604 if (debug != null && Debug.isOn("failure")) {
605 605 debug.println("socket access restriction: proxied host " + "(" + addresses[0] + ")" + " does not match " + cname + " from reverse lookup");
606 606 }
607 607 return true;
608 608 }
609 609 }
610 610 trusted = true;
611 611 }
612 612 } catch (UnknownHostException uhe) {
613 613 invalid = true;
614 614 throw uhe;
615 615 }
616 616 return false;
617 617 }
618 618
619 619 /**
620 620 * attempt to get the fully qualified domain name
621 621 *
622 622 */
623 623 void getCanonName()
624 624 throws UnknownHostException
625 625 {
626 626 if (cname != null || invalid || untrusted) return;
627 627
628 628 // attempt to get the canonical name
629 629
630 630 try {
631 631 // first get the IP addresses if we don't have them yet
632 632 // this is because we need the IP address to then get
633 633 // FQDN.
634 634 if (addresses == null) {
635 635 getIP();
636 636 }
637 637
638 638 // we have to do this check, otherwise we might not
639 639 // get the fully qualified domain name
640 640 if (init_with_ip) {
641 641 cname = addresses[0].getHostName(false).toLowerCase();
642 642 } else {
643 643 cname = InetAddress.getByName(addresses[0].getHostAddress()).
644 644 getHostName(false).toLowerCase();
645 645 }
646 646 } catch (UnknownHostException uhe) {
647 647 invalid = true;
648 648 throw uhe;
649 649 }
650 650 }
651 651
652 652 private transient String cdomain, hdomain;
653 653
654 654 private boolean match(String cname, String hname) {
655 655 String a = cname.toLowerCase();
656 656 String b = hname.toLowerCase();
657 657 if (a.startsWith(b) &&
658 658 ((a.length() == b.length()) || (a.charAt(b.length()) == '.')))
659 659 return true;
660 660 if (cdomain == null) {
661 661 cdomain = RegisteredDomain.getRegisteredDomain(a);
662 662 }
663 663 if (hdomain == null) {
664 664 hdomain = RegisteredDomain.getRegisteredDomain(b);
665 665 }
666 666
667 667 return cdomain.length() != 0 && hdomain.length() != 0
668 668 && cdomain.equals(hdomain);
669 669 }
670 670
671 671 private boolean authorized(String cname, byte[] addr) {
672 672 if (addr.length == 4)
673 673 return authorizedIPv4(cname, addr);
674 674 else if (addr.length == 16)
675 675 return authorizedIPv6(cname, addr);
676 676 else
677 677 return false;
678 678 }
679 679
680 680 private boolean authorizedIPv4(String cname, byte[] addr) {
681 681 String authHost = "";
682 682 InetAddress auth;
683 683
684 684 try {
685 685 authHost = "auth." +
686 686 (addr[3] & 0xff) + "." + (addr[2] & 0xff) + "." +
687 687 (addr[1] & 0xff) + "." + (addr[0] & 0xff) +
688 688 ".in-addr.arpa";
689 689 // Following check seems unnecessary
690 690 // auth = InetAddress.getAllByName0(authHost, false)[0];
691 691 authHost = hostname + '.' + authHost;
692 692 auth = InetAddress.getAllByName0(authHost, false)[0];
693 693 if (auth.equals(InetAddress.getByAddress(addr))) {
694 694 return true;
695 695 }
696 696 Debug debug = getDebug();
697 697 if (debug != null && Debug.isOn("failure")) {
698 698 debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr));
699 699 }
700 700 } catch (UnknownHostException uhe) {
701 701 Debug debug = getDebug();
702 702 if (debug != null && Debug.isOn("failure")) {
703 703 debug.println("socket access restriction: forward lookup failed for " + authHost);
704 704 }
705 705 }
706 706 return false;
707 707 }
708 708
709 709 private boolean authorizedIPv6(String cname, byte[] addr) {
710 710 String authHost = "";
711 711 InetAddress auth;
712 712
713 713 try {
714 714 StringBuffer sb = new StringBuffer(39);
715 715
716 716 for (int i = 15; i >= 0; i--) {
717 717 sb.append(Integer.toHexString(((addr[i]) & 0x0f)));
718 718 sb.append('.');
719 719 sb.append(Integer.toHexString(((addr[i] >> 4) & 0x0f)));
720 720 sb.append('.');
721 721 }
722 722 authHost = "auth." + sb.toString() + "IP6.ARPA";
723 723 //auth = InetAddress.getAllByName0(authHost, false)[0];
724 724 authHost = hostname + '.' + authHost;
725 725 auth = InetAddress.getAllByName0(authHost, false)[0];
726 726 if (auth.equals(InetAddress.getByAddress(addr)))
727 727 return true;
728 728 Debug debug = getDebug();
729 729 if (debug != null && Debug.isOn("failure")) {
730 730 debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr));
731 731 }
732 732 } catch (UnknownHostException uhe) {
733 733 Debug debug = getDebug();
734 734 if (debug != null && Debug.isOn("failure")) {
735 735 debug.println("socket access restriction: forward lookup failed for " + authHost);
736 736 }
737 737 }
738 738 return false;
739 739 }
740 740
741 741
742 742 /**
743 743 * get IP addresses. Sets invalid to true if we can't get them.
744 744 *
745 745 */
746 746 void getIP()
747 747 throws UnknownHostException
748 748 {
749 749 if (addresses != null || wildcard || invalid) return;
750 750
751 751 try {
752 752 // now get all the IP addresses
753 753 String host;
754 754 if (getName().charAt(0) == '[') {
755 755 // Literal IPv6 address
756 756 host = getName().substring(1, getName().indexOf(']'));
757 757 } else {
758 758 int i = getName().indexOf(":");
759 759 if (i == -1)
760 760 host = getName();
761 761 else {
762 762 host = getName().substring(0,i);
763 763 }
764 764 }
765 765
766 766 addresses =
767 767 new InetAddress[] {InetAddress.getAllByName0(host, false)[0]};
768 768
769 769 } catch (UnknownHostException uhe) {
770 770 invalid = true;
771 771 throw uhe;
772 772 } catch (IndexOutOfBoundsException iobe) {
773 773 invalid = true;
774 774 throw new UnknownHostException(getName());
775 775 }
776 776 }
777 777
778 778 /**
779 779 * Checks if this socket permission object "implies" the
780 780 * specified permission.
781 781 * <P>
782 782 * More specifically, this method first ensures that all of the following
783 783 * are true (and returns false if any of them are not):<p>
784 784 * <ul>
785 785 * <li> <i>p</i> is an instanceof SocketPermission,<p>
786 786 * <li> <i>p</i>'s actions are a proper subset of this
787 787 * object's actions, and<p>
788 788 * <li> <i>p</i>'s port range is included in this port range. Note:
789 789 * port range is ignored when p only contains the action, 'resolve'.<p>
790 790 * </ul>
791 791 *
792 792 * Then <code>implies</code> checks each of the following, in order,
793 793 * and for each returns true if the stated condition is true:<p>
794 794 * <ul>
795 795 * <li> If this object was initialized with a single IP address and one of <i>p</i>'s
796 796 * IP addresses is equal to this object's IP address.<p>
797 797 * <li>If this object is a wildcard domain (such as *.sun.com), and
798 798 * <i>p</i>'s canonical name (the name without any preceding *)
799 799 * ends with this object's canonical host name. For example, *.sun.com
800 800 * implies *.eng.sun.com..<p>
801 801 * <li>If this object was not initialized with a single IP address, and one of this
802 802 * object's IP addresses equals one of <i>p</i>'s IP addresses.<p>
803 803 * <li>If this canonical name equals <i>p</i>'s canonical name.<p>
804 804 * </ul>
805 805 *
806 806 * If none of the above are true, <code>implies</code> returns false.
807 807 * @param p the permission to check against.
808 808 *
809 809 * @return true if the specified permission is implied by this object,
810 810 * false if not.
811 811 */
812 812
813 813 public boolean implies(Permission p) {
814 814 int i,j;
815 815
816 816 if (!(p instanceof SocketPermission))
817 817 return false;
818 818
819 819 if (p == this)
820 820 return true;
821 821
822 822 SocketPermission that = (SocketPermission) p;
823 823
824 824 return ((this.mask & that.mask) == that.mask) &&
825 825 impliesIgnoreMask(that);
826 826 }
827 827
828 828 /**
829 829 * Checks if the incoming Permission's action are a proper subset of
830 830 * the this object's actions.
831 831 * <P>
832 832 * Check, in the following order:
833 833 * <ul>
834 834 * <li> Checks that "p" is an instanceof a SocketPermission
835 835 * <li> Checks that "p"'s actions are a proper subset of the
836 836 * current object's actions.
837 837 * <li> Checks that "p"'s port range is included in this port range
838 838 * <li> If this object was initialized with an IP address, checks that
839 839 * one of "p"'s IP addresses is equal to this object's IP address.
840 840 * <li> If either object is a wildcard domain (i.e., "*.sun.com"),
841 841 * attempt to match based on the wildcard.
842 842 * <li> If this object was not initialized with an IP address, attempt
843 843 * to find a match based on the IP addresses in both objects.
844 844 * <li> Attempt to match on the canonical hostnames of both objects.
845 845 * </ul>
846 846 * @param p the incoming permission request
847 847 *
848 848 * @return true if "permission" is a proper subset of the current object,
849 849 * false if not.
850 850 */
851 851
852 852 boolean impliesIgnoreMask(SocketPermission that) {
853 853 int i,j;
854 854
855 855 if ((that.mask & RESOLVE) != that.mask) {
856 856 // check port range
857 857 if ((that.portrange[0] < this.portrange[0]) ||
858 858 (that.portrange[1] > this.portrange[1])) {
859 859 return false;
860 860 }
861 861 }
862 862
863 863 // allow a "*" wildcard to always match anything
864 864 if (this.wildcard && "".equals(this.cname))
865 865 return true;
866 866
867 867 // return if either one of these NetPerm objects are invalid...
868 868 if (this.invalid || that.invalid) {
869 869 return compareHostnames(that);
870 870 }
871 871
872 872 try {
873 873 if (this.init_with_ip) { // we only check IP addresses
874 874 if (that.wildcard)
875 875 return false;
876 876
877 877 if (that.init_with_ip) {
878 878 return (this.addresses[0].equals(that.addresses[0]));
879 879 } else {
880 880 if (that.addresses == null) {
881 881 that.getIP();
882 882 }
883 883 for (i=0; i < that.addresses.length; i++) {
884 884 if (this.addresses[0].equals(that.addresses[i]))
885 885 return true;
886 886 }
887 887 }
888 888 // since "this" was initialized with an IP address, we
889 889 // don't check any other cases
890 890 return false;
891 891 }
892 892
893 893 // check and see if we have any wildcards...
894 894 if (this.wildcard || that.wildcard) {
895 895 // if they are both wildcards, return true iff
896 896 // that's cname ends with this cname (i.e., *.sun.com
897 897 // implies *.eng.sun.com)
898 898 if (this.wildcard && that.wildcard)
899 899 return (that.cname.endsWith(this.cname));
900 900
901 901 // a non-wildcard can't imply a wildcard
902 902 if (that.wildcard)
903 903 return false;
904 904
905 905 // this is a wildcard, lets see if that's cname ends with
906 906 // it...
907 907 if (that.cname == null) {
908 908 that.getCanonName();
909 909 }
910 910 return (that.cname.endsWith(this.cname));
911 911 }
912 912
913 913 // comapare IP addresses
914 914 if (this.addresses == null) {
915 915 this.getIP();
916 916 }
917 917
918 918 if (that.addresses == null) {
919 919 that.getIP();
920 920 }
921 921
922 922 if (!(that.init_with_ip && this.isUntrusted())) {
923 923 for (j = 0; j < this.addresses.length; j++) {
924 924 for (i=0; i < that.addresses.length; i++) {
925 925 if (this.addresses[j].equals(that.addresses[i]))
926 926 return true;
927 927 }
928 928 }
929 929
930 930 // XXX: if all else fails, compare hostnames?
931 931 // Do we really want this?
932 932 if (this.cname == null) {
933 933 this.getCanonName();
934 934 }
935 935
936 936 if (that.cname == null) {
937 937 that.getCanonName();
938 938 }
939 939
940 940 return (this.cname.equalsIgnoreCase(that.cname));
941 941 }
942 942
943 943 } catch (UnknownHostException uhe) {
944 944 return compareHostnames(that);
945 945 }
946 946
947 947 // make sure the first thing that is done here is to return
948 948 // false. If not, uncomment the return false in the above catch.
↓ open down ↓ |
948 lines elided |
↑ open up ↑ |
949 949
950 950 return false;
951 951 }
952 952
953 953 private boolean compareHostnames(SocketPermission that) {
954 954 // we see if the original names/IPs passed in were equal.
955 955
956 956 String thisHost = hostname;
957 957 String thatHost = that.hostname;
958 958
959 - if (thisHost == null)
959 + if (thisHost == null) {
960 960 return false;
961 - else
961 + } else if (this.wildcard) {
962 + final int cnameLength = this.cname.length();
963 + return thatHost.regionMatches(true,
964 + (thatHost.length() - cnameLength),
965 + this.cname, 0, cnameLength);
966 + } else {
962 967 return thisHost.equalsIgnoreCase(thatHost);
968 + }
963 969 }
964 970
965 971 /**
966 972 * Checks two SocketPermission objects for equality.
967 973 * <P>
968 974 * @param obj the object to test for equality with this object.
969 975 *
970 976 * @return true if <i>obj</i> is a SocketPermission, and has the
971 977 * same hostname, port range, and actions as this
972 978 * SocketPermission object. However, port range will be ignored
973 979 * in the comparison if <i>obj</i> only contains the action, 'resolve'.
974 980 */
975 981 public boolean equals(Object obj) {
976 982 if (obj == this)
977 983 return true;
978 984
979 985 if (! (obj instanceof SocketPermission))
980 986 return false;
981 987
982 988 SocketPermission that = (SocketPermission) obj;
983 989
984 990 //this is (overly?) complex!!!
985 991
986 992 // check the mask first
987 993 if (this.mask != that.mask) return false;
988 994
989 995 if ((that.mask & RESOLVE) != that.mask) {
990 996 // now check the port range...
991 997 if ((this.portrange[0] != that.portrange[0]) ||
992 998 (this.portrange[1] != that.portrange[1])) {
993 999 return false;
994 1000 }
995 1001 }
996 1002
997 1003 // short cut. This catches:
998 1004 // "crypto" equal to "crypto", or
999 1005 // "1.2.3.4" equal to "1.2.3.4.", or
1000 1006 // "*.edu" equal to "*.edu", but it
1001 1007 // does not catch "crypto" equal to
1002 1008 // "crypto.eng.sun.com".
1003 1009
1004 1010 if (this.getName().equalsIgnoreCase(that.getName())) {
1005 1011 return true;
1006 1012 }
1007 1013
1008 1014 // we now attempt to get the Canonical (FQDN) name and
1009 1015 // compare that. If this fails, about all we can do is return
1010 1016 // false.
1011 1017
1012 1018 try {
1013 1019 this.getCanonName();
1014 1020 that.getCanonName();
1015 1021 } catch (UnknownHostException uhe) {
1016 1022 return false;
1017 1023 }
1018 1024
1019 1025 if (this.invalid || that.invalid)
1020 1026 return false;
1021 1027
1022 1028 if (this.cname != null) {
1023 1029 return this.cname.equalsIgnoreCase(that.cname);
1024 1030 }
1025 1031
1026 1032 return false;
1027 1033 }
1028 1034
1029 1035 /**
1030 1036 * Returns the hash code value for this object.
1031 1037 *
1032 1038 * @return a hash code value for this object.
1033 1039 */
1034 1040
1035 1041 public int hashCode() {
1036 1042 /*
1037 1043 * If this SocketPermission was initialized with an IP address
1038 1044 * or a wildcard, use getName().hashCode(), otherwise use
1039 1045 * the hashCode() of the host name returned from
1040 1046 * java.net.InetAddress.getHostName method.
1041 1047 */
1042 1048
1043 1049 if (init_with_ip || wildcard) {
1044 1050 return this.getName().hashCode();
1045 1051 }
1046 1052
1047 1053 try {
1048 1054 getCanonName();
1049 1055 } catch (UnknownHostException uhe) {
1050 1056
1051 1057 }
1052 1058
1053 1059 if (invalid || cname == null)
1054 1060 return this.getName().hashCode();
1055 1061 else
1056 1062 return this.cname.hashCode();
1057 1063 }
1058 1064
1059 1065 /**
1060 1066 * Return the current action mask.
1061 1067 *
1062 1068 * @return the actions mask.
1063 1069 */
1064 1070
1065 1071 int getMask() {
1066 1072 return mask;
1067 1073 }
1068 1074
1069 1075 /**
1070 1076 * Returns the "canonical string representation" of the actions in the
1071 1077 * specified mask.
1072 1078 * Always returns present actions in the following order:
1073 1079 * connect, listen, accept, resolve.
1074 1080 *
1075 1081 * @param mask a specific integer action mask to translate into a string
1076 1082 * @return the canonical string representation of the actions
1077 1083 */
1078 1084 private static String getActions(int mask)
1079 1085 {
1080 1086 StringBuilder sb = new StringBuilder();
1081 1087 boolean comma = false;
1082 1088
1083 1089 if ((mask & CONNECT) == CONNECT) {
1084 1090 comma = true;
1085 1091 sb.append("connect");
1086 1092 }
1087 1093
1088 1094 if ((mask & LISTEN) == LISTEN) {
1089 1095 if (comma) sb.append(',');
1090 1096 else comma = true;
1091 1097 sb.append("listen");
1092 1098 }
1093 1099
1094 1100 if ((mask & ACCEPT) == ACCEPT) {
1095 1101 if (comma) sb.append(',');
1096 1102 else comma = true;
1097 1103 sb.append("accept");
1098 1104 }
1099 1105
1100 1106
1101 1107 if ((mask & RESOLVE) == RESOLVE) {
1102 1108 if (comma) sb.append(',');
1103 1109 else comma = true;
1104 1110 sb.append("resolve");
1105 1111 }
1106 1112
1107 1113 return sb.toString();
1108 1114 }
1109 1115
1110 1116 /**
1111 1117 * Returns the canonical string representation of the actions.
1112 1118 * Always returns present actions in the following order:
1113 1119 * connect, listen, accept, resolve.
1114 1120 *
1115 1121 * @return the canonical string representation of the actions.
1116 1122 */
1117 1123 public String getActions()
1118 1124 {
1119 1125 if (actions == null)
1120 1126 actions = getActions(this.mask);
1121 1127
1122 1128 return actions;
1123 1129 }
1124 1130
1125 1131 /**
1126 1132 * Returns a new PermissionCollection object for storing SocketPermission
1127 1133 * objects.
1128 1134 * <p>
1129 1135 * SocketPermission objects must be stored in a manner that allows them
1130 1136 * to be inserted into the collection in any order, but that also enables the
1131 1137 * PermissionCollection <code>implies</code>
1132 1138 * method to be implemented in an efficient (and consistent) manner.
1133 1139 *
1134 1140 * @return a new PermissionCollection object suitable for storing SocketPermissions.
1135 1141 */
1136 1142
1137 1143 public PermissionCollection newPermissionCollection() {
1138 1144 return new SocketPermissionCollection();
1139 1145 }
1140 1146
1141 1147 /**
1142 1148 * WriteObject is called to save the state of the SocketPermission
1143 1149 * to a stream. The actions are serialized, and the superclass
1144 1150 * takes care of the name.
1145 1151 */
1146 1152 private synchronized void writeObject(java.io.ObjectOutputStream s)
1147 1153 throws IOException
1148 1154 {
1149 1155 // Write out the actions. The superclass takes care of the name
1150 1156 // call getActions to make sure actions field is initialized
1151 1157 if (actions == null)
1152 1158 getActions();
1153 1159 s.defaultWriteObject();
1154 1160 }
1155 1161
1156 1162 /**
1157 1163 * readObject is called to restore the state of the SocketPermission from
1158 1164 * a stream.
1159 1165 */
1160 1166 private synchronized void readObject(java.io.ObjectInputStream s)
1161 1167 throws IOException, ClassNotFoundException
1162 1168 {
1163 1169 // Read in the action, then initialize the rest
1164 1170 s.defaultReadObject();
1165 1171 init(getName(),getMask(actions));
1166 1172 }
1167 1173
1168 1174 /*
1169 1175 public String toString()
1170 1176 {
1171 1177 StringBuffer s = new StringBuffer(super.toString() + "\n" +
1172 1178 "cname = " + cname + "\n" +
1173 1179 "wildcard = " + wildcard + "\n" +
1174 1180 "invalid = " + invalid + "\n" +
1175 1181 "portrange = " + portrange[0] + "," + portrange[1] + "\n");
1176 1182 if (addresses != null) for (int i=0; i<addresses.length; i++) {
1177 1183 s.append( addresses[i].getHostAddress());
1178 1184 s.append("\n");
1179 1185 } else {
1180 1186 s.append("(no addresses)\n");
1181 1187 }
1182 1188
1183 1189 return s.toString();
1184 1190 }
1185 1191
1186 1192 public static void main(String args[]) throws Exception {
1187 1193 SocketPermission this_ = new SocketPermission(args[0], "connect");
1188 1194 SocketPermission that_ = new SocketPermission(args[1], "connect");
1189 1195 System.out.println("-----\n");
1190 1196 System.out.println("this.implies(that) = " + this_.implies(that_));
1191 1197 System.out.println("-----\n");
1192 1198 System.out.println("this = "+this_);
1193 1199 System.out.println("-----\n");
1194 1200 System.out.println("that = "+that_);
1195 1201 System.out.println("-----\n");
1196 1202
1197 1203 SocketPermissionCollection nps = new SocketPermissionCollection();
1198 1204 nps.add(this_);
1199 1205 nps.add(new SocketPermission("www-leland.stanford.edu","connect"));
1200 1206 nps.add(new SocketPermission("www-sun.com","connect"));
1201 1207 System.out.println("nps.implies(that) = " + nps.implies(that_));
1202 1208 System.out.println("-----\n");
1203 1209 }
1204 1210 */
1205 1211 }
1206 1212
1207 1213 /**
1208 1214
1209 1215 if (init'd with IP, key is IP as string)
1210 1216 if wildcard, its the wild card
1211 1217 else its the cname?
1212 1218
1213 1219 *
1214 1220 * @see java.security.Permission
1215 1221 * @see java.security.Permissions
1216 1222 * @see java.security.PermissionCollection
1217 1223 *
1218 1224 *
1219 1225 * @author Roland Schemers
1220 1226 *
1221 1227 * @serial include
1222 1228 */
1223 1229
1224 1230 final class SocketPermissionCollection extends PermissionCollection
1225 1231 implements Serializable
1226 1232 {
1227 1233 // Not serialized; see serialization section at end of class
1228 1234 private transient List perms;
1229 1235
1230 1236 /**
1231 1237 * Create an empty SocketPermissions object.
1232 1238 *
1233 1239 */
1234 1240
1235 1241 public SocketPermissionCollection() {
1236 1242 perms = new ArrayList();
1237 1243 }
1238 1244
1239 1245 /**
1240 1246 * Adds a permission to the SocketPermissions. The key for the hash is
1241 1247 * the name in the case of wildcards, or all the IP addresses.
1242 1248 *
1243 1249 * @param permission the Permission object to add.
1244 1250 *
1245 1251 * @exception IllegalArgumentException - if the permission is not a
1246 1252 * SocketPermission
1247 1253 *
1248 1254 * @exception SecurityException - if this SocketPermissionCollection object
1249 1255 * has been marked readonly
1250 1256 */
1251 1257
1252 1258 public void add(Permission permission)
1253 1259 {
1254 1260 if (! (permission instanceof SocketPermission))
1255 1261 throw new IllegalArgumentException("invalid permission: "+
1256 1262 permission);
1257 1263 if (isReadOnly())
1258 1264 throw new SecurityException(
1259 1265 "attempt to add a Permission to a readonly PermissionCollection");
1260 1266
1261 1267 // optimization to ensure perms most likely to be tested
1262 1268 // show up early (4301064)
1263 1269 synchronized (this) {
1264 1270 perms.add(0, permission);
1265 1271 }
1266 1272 }
1267 1273
1268 1274 /**
1269 1275 * Check and see if this collection of permissions implies the permissions
1270 1276 * expressed in "permission".
1271 1277 *
1272 1278 * @param p the Permission object to compare
1273 1279 *
1274 1280 * @return true if "permission" is a proper subset of a permission in
1275 1281 * the collection, false if not.
1276 1282 */
1277 1283
1278 1284 public boolean implies(Permission permission)
1279 1285 {
1280 1286 if (! (permission instanceof SocketPermission))
1281 1287 return false;
1282 1288
1283 1289 SocketPermission np = (SocketPermission) permission;
1284 1290
1285 1291 int desired = np.getMask();
1286 1292 int effective = 0;
1287 1293 int needed = desired;
1288 1294
1289 1295 synchronized (this) {
1290 1296 int len = perms.size();
1291 1297 //System.out.println("implies "+np);
1292 1298 for (int i = 0; i < len; i++) {
1293 1299 SocketPermission x = (SocketPermission) perms.get(i);
1294 1300 //System.out.println(" trying "+x);
1295 1301 if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) {
1296 1302 effective |= x.getMask();
1297 1303 if ((effective & desired) == desired)
1298 1304 return true;
1299 1305 needed = (desired ^ effective);
1300 1306 }
1301 1307 }
1302 1308 }
1303 1309 return false;
1304 1310 }
1305 1311
1306 1312 /**
1307 1313 * Returns an enumeration of all the SocketPermission objects in the
1308 1314 * container.
1309 1315 *
1310 1316 * @return an enumeration of all the SocketPermission objects.
1311 1317 */
1312 1318
1313 1319 public Enumeration elements() {
1314 1320 // Convert Iterator into Enumeration
1315 1321 synchronized (this) {
1316 1322 return Collections.enumeration(perms);
1317 1323 }
1318 1324 }
1319 1325
1320 1326 private static final long serialVersionUID = 2787186408602843674L;
1321 1327
1322 1328 // Need to maintain serialization interoperability with earlier releases,
1323 1329 // which had the serializable field:
1324 1330
1325 1331 //
1326 1332 // The SocketPermissions for this set.
1327 1333 // @serial
1328 1334 //
1329 1335 // private Vector permissions;
1330 1336
1331 1337 /**
1332 1338 * @serialField permissions java.util.Vector
1333 1339 * A list of the SocketPermissions for this set.
1334 1340 */
1335 1341 private static final ObjectStreamField[] serialPersistentFields = {
1336 1342 new ObjectStreamField("permissions", Vector.class),
1337 1343 };
1338 1344
1339 1345 /**
1340 1346 * @serialData "permissions" field (a Vector containing the SocketPermissions).
1341 1347 */
1342 1348 /*
1343 1349 * Writes the contents of the perms field out as a Vector for
1344 1350 * serialization compatibility with earlier releases.
1345 1351 */
1346 1352 private void writeObject(ObjectOutputStream out) throws IOException {
1347 1353 // Don't call out.defaultWriteObject()
1348 1354
1349 1355 // Write out Vector
1350 1356 Vector permissions = new Vector(perms.size());
1351 1357
1352 1358 synchronized (this) {
1353 1359 permissions.addAll(perms);
1354 1360 }
1355 1361
1356 1362 ObjectOutputStream.PutField pfields = out.putFields();
1357 1363 pfields.put("permissions", permissions);
1358 1364 out.writeFields();
1359 1365 }
1360 1366
1361 1367 /*
1362 1368 * Reads in a Vector of SocketPermissions and saves them in the perms field.
1363 1369 */
1364 1370 private void readObject(ObjectInputStream in) throws IOException,
1365 1371 ClassNotFoundException {
1366 1372 // Don't call in.defaultReadObject()
1367 1373
1368 1374 // Read in serialized fields
1369 1375 ObjectInputStream.GetField gfields = in.readFields();
1370 1376
1371 1377 // Get the one we want
1372 1378 Vector permissions = (Vector)gfields.get("permissions", null);
1373 1379 perms = new ArrayList(permissions.size());
1374 1380 perms.addAll(permissions);
1375 1381 }
1376 1382 }
↓ open down ↓ |
404 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX