107
* @author Aaron M. Renn (arenn@urbanophile.com)
112
* @author Written by Aaron M. Renn (arenn@urbanophile.com)
113
* @author Extensively modified by Gary Benson (gbenson@redhat.com)
109
115
public final class SocketPermission extends Permission implements Serializable
111
117
static final long serialVersionUID = -7204263841984476862L;
113
// FIXME: Needs serialization work, including readObject/writeObject methods.
116
* A hostname/port combination as described above
118
private transient String hostport;
121
* A comma separated list of actions for which we have permission
120
* A hostname (possibly wildcarded) or IP address (IPv4 or IPv6).
122
private transient String host;
127
private transient int minport;
128
private transient int maxport;
131
* Values used for minimum and maximum ports when one or both bounds
132
* are omitted. This class is essentially independent of the
133
* networking code it describes, so we do not limit ports to the
134
* usual network limits of 1 and 65535.
136
private static final int MIN_PORT = 0;
137
private static final int MAX_PORT = Integer.MAX_VALUE;
140
* The actions for which we have permission. This field is present
141
* to make the serialized form correct and should not be used by
142
* anything other than writeObject: everything else should use
123
145
private String actions;
148
* A bitmask representing the actions for which we have permission.
150
private transient int actionmask;
153
* The available actions, in the canonical order required for getActions().
155
private static final String[] ACTIONS = new String[] {
156
"connect", "listen", "accept", "resolve"};
126
159
* Initializes a new instance of <code>SocketPermission</code> with the
127
160
* specified host/port combination and actions string.
136
this.hostport = hostport;
137
this.actions = actions;
169
setHostPort(hostport);
174
* Parse the hostport argument to the constructor.
176
private void setHostPort(String hostport)
178
// Split into host and ports
180
if (hostport.length() == 0)
184
else if (hostport.charAt(0) == '[')
186
// host is a bracketed IPv6 address
187
int end = hostport.indexOf("]");
189
throw new IllegalArgumentException("Unmatched '['");
190
host = hostport.substring(1, end);
192
if (end == hostport.length() - 1)
194
else if (hostport.charAt(end + 1) == ':')
195
ports = hostport.substring(end + 2);
197
throw new IllegalArgumentException("Bad character after ']'");
201
// host is a hostname or IPv4 address
202
int sep = hostport.indexOf(":");
210
host = hostport.substring(0, sep);
211
ports = hostport.substring(sep + 1);
214
if (ports.indexOf(":") != -1)
215
throw new IllegalArgumentException("Unexpected ':'");
217
// Parse and validate the ports
218
if (ports.length() == 0)
225
int sep = ports.indexOf("-");
229
minport = maxport = Integer.parseInt(ports);
233
if (ports.indexOf("-", sep + 1) != -1)
234
throw new IllegalArgumentException("Unexpected '-'");
240
maxport = Integer.parseInt(ports.substring(1));
242
else if (sep == ports.length() - 1)
246
Integer.parseInt(ports.substring(0, ports.length() - 1));
251
// a range with two bounds
252
minport = Integer.parseInt(ports.substring(0, sep));
253
maxport = Integer.parseInt(ports.substring(sep + 1));
260
* Parse the actions argument to the constructor.
262
private void setActions(String actionstring)
266
boolean resolve_needed = false;
267
boolean resolve_present = false;
269
StringTokenizer t = new StringTokenizer(actionstring, ",");
270
while (t.hasMoreTokens())
272
String action = t.nextToken();
273
action = action.trim().toLowerCase();
276
if (action.equals("resolve"))
277
resolve_present = true;
279
resolve_needed = true;
282
if (resolve_needed && !resolve_present)
283
setAction("resolve");
287
* Parse one element of the actions argument to the constructor.
289
private void setAction(String action)
291
for (int i = 0; i < ACTIONS.length; i++)
293
if (action.equals(ACTIONS[i]))
295
actionmask |= 1 << i;
299
throw new IllegalArgumentException("Unknown action " + action);
270
410
// Next check the actions
271
String ourlist = getActions();
272
String theirlist = p.getActions();
274
if (! ourlist.startsWith(theirlist))
278
int ourfirstport = 0;
284
int theirfirstport = 0;
287
int theirlastport = 0;
290
if (hostport.indexOf(":") == -1)
297
// FIXME: Needs bulletproofing.
298
// This will dump if hostport if all sorts of bad data was passed to
300
String range = hostport.substring(hostport.indexOf(":") + 1);
301
if (range.startsWith("-"))
303
else if (range.indexOf("-") == -1)
304
ourfirstport = Integer.parseInt(range);
307
Integer.parseInt(range.substring(0, range.indexOf("-")));
309
if (range.endsWith("-"))
311
else if (range.indexOf("-") == -1)
312
ourlastport = Integer.parseInt(range);
315
Integer.parseInt(range.substring(range.indexOf("-") + 1,
320
if (p.hostport.indexOf(":") == -1)
327
// This will dump if hostport if all sorts of bad data was passed to
329
String range = p.hostport.substring(hostport.indexOf(":") + 1);
330
if (range.startsWith("-"))
332
else if (range.indexOf("-") == -1)
333
theirfirstport = Integer.parseInt(range);
336
Integer.parseInt(range.substring(0, range.indexOf("-")));
338
if (range.endsWith("-"))
339
theirlastport = 65535;
340
else if (range.indexOf("-") == -1)
341
theirlastport = Integer.parseInt(range);
344
Integer.parseInt(range.substring(range.indexOf("-") + 1,
349
if ((theirfirstport < ourfirstport) || (theirlastport > ourlastport))
352
// Finally we can check the hosts
355
// Finally we can check the hosts
359
if (hostport.indexOf(":") == -1)
362
ourhost = hostport.substring(0, hostport.indexOf(":"));
365
if (p.hostport.indexOf(":") == -1)
366
theirhost = p.hostport;
368
theirhost = p.hostport.substring(0, p.hostport.indexOf(":"));
371
if (ourhost.equals(theirhost))
411
if ((p.actionmask & actionmask) != p.actionmask)
414
// Then check the ports
415
if ((p.minport < minport) || (p.maxport > maxport))
418
// Finally check the hosts
419
if (host.equals(p.host))
374
422
// Try the canonical names
375
423
String ourcanonical = null;
377
// Try the canonical names
378
424
String theircanonical = null;
381
ourcanonical = InetAddress.getByName(ourhost).getHostName();
382
theircanonical = InetAddress.getByName(theirhost).getHostName();
427
ourcanonical = InetAddress.getByName(host).getHostName();
428
theircanonical = InetAddress.getByName(p.host).getHostName();
384
430
catch (UnknownHostException e)
386
432
// Who didn't resolve? Just assume current address is canonical enough
387
433
// Is this ok to do?
388
434
if (ourcanonical == null)
389
ourcanonical = ourhost;
390
436
if (theircanonical == null)
391
theircanonical = theirhost;
437
theircanonical = p.host;
394
440
if (ourcanonical.equals(theircanonical))
397
443
// Well, last chance. Try for a wildcard
398
if (ourhost.indexOf("*.") != -1)
444
if (host.indexOf("*.") != -1)
400
String wild_domain = ourhost.substring(ourhost.indexOf("*" + 1));
447
host.substring(host.indexOf("*" + 1));
401
448
if (theircanonical.endsWith(wild_domain))
405
452
// Didn't make it
457
* Deserializes a <code>SocketPermission</code> object from
460
* @param input the input stream.
461
* @throws IOException if an I/O error occurs in the stream.
462
* @throws ClassNotFoundException if the class of the
463
* serialized object could not be found.
465
private void readObject(ObjectInputStream input)
466
throws IOException, ClassNotFoundException
468
input.defaultReadObject();
469
setHostPort(getName());
474
* Serializes a <code>SocketPermission</code> object to an
477
* @param output the output stream.
478
* @throws IOException if an I/O error occurs in the stream.
480
private void writeObject(ObjectOutputStream output)
483
actions = getActions();
484
output.defaultWriteObject();