~ubuntu-branches/ubuntu/precise/classpath/precise

« back to all changes in this revision

Viewing changes to java/net/SocketPermission.java

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2006-05-27 16:11:15 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060527161115-h6e39eposdt5snb6
Tags: 2:0.91-3
* Install header files to /usr/include/classpath.
* debian/control: classpath: Conflict with jamvm < 1.4.3 and
  cacao < 0.96 (Closes: #368172).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* SocketPermission.java -- Class modeling permissions for socket operations
2
 
   Copyright (C) 1998, 2000, 2001, 2002, 2004  Free Software Foundation, Inc.
 
2
   Copyright (C) 1998, 2000, 2001, 2002, 2004, 2006 Free Software
 
3
   Foundation, Inc.
3
4
 
4
5
This file is part of GNU Classpath.
5
6
 
37
38
 
38
39
package java.net;
39
40
 
 
41
import java.io.IOException;
 
42
import java.io.ObjectInputStream;
 
43
import java.io.ObjectOutputStream;
40
44
import java.io.Serializable;
41
45
import java.security.Permission;
42
46
import java.security.PermissionCollection;
 
47
import java.util.StringTokenizer;
43
48
 
44
49
 
45
50
/**
104
109
 *
105
110
 * @since 1.2
106
111
 *
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)
108
114
 */
109
115
public final class SocketPermission extends Permission implements Serializable
110
116
{
111
117
  static final long serialVersionUID = -7204263841984476862L;
112
118
 
113
 
// FIXME: Needs serialization work, including readObject/writeObject methods.
114
 
 
115
 
  /**
116
 
   * A hostname/port combination as described above
117
 
   */
118
 
  private transient String hostport;
119
 
 
120
 
  /**
121
 
   * A comma separated list of actions for which we have permission
 
119
  /**
 
120
   * A hostname (possibly wildcarded) or IP address (IPv4 or IPv6).
 
121
   */
 
122
  private transient String host;
 
123
 
 
124
  /**
 
125
   * A range of ports.
 
126
   */
 
127
  private transient int minport;
 
128
  private transient int maxport;
 
129
 
 
130
  /**
 
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.
 
135
   */
 
136
  private static final int MIN_PORT = 0;
 
137
  private static final int MAX_PORT = Integer.MAX_VALUE;
 
138
 
 
139
  /**
 
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
 
143
   * actionmask.
122
144
   */
123
145
  private String actions;
124
146
 
125
147
  /**
 
148
   * A bitmask representing the actions for which we have permission.
 
149
   */
 
150
  private transient int actionmask;
 
151
 
 
152
  /**
 
153
   * The available actions, in the canonical order required for getActions().
 
154
   */
 
155
  private static final String[] ACTIONS = new String[] {
 
156
    "connect", "listen", "accept", "resolve"};
 
157
 
 
158
  /**
126
159
   * Initializes a new instance of <code>SocketPermission</code> with the
127
160
   * specified host/port combination and actions string.
128
161
   *
133
166
  {
134
167
    super(hostport);
135
168
 
136
 
    this.hostport = hostport;
137
 
    this.actions = actions;
 
169
    setHostPort(hostport);
 
170
    setActions(actions);
 
171
  }
 
172
 
 
173
  /**
 
174
   * Parse the hostport argument to the constructor.
 
175
   */
 
176
  private void setHostPort(String hostport)
 
177
  {
 
178
    // Split into host and ports
 
179
    String ports;
 
180
    if (hostport.length() == 0)
 
181
      {
 
182
        host = ports = "";
 
183
      }
 
184
    else if (hostport.charAt(0) == '[')
 
185
      {
 
186
        // host is a bracketed IPv6 address
 
187
        int end = hostport.indexOf("]");
 
188
        if (end == -1)
 
189
          throw new IllegalArgumentException("Unmatched '['");
 
190
        host = hostport.substring(1, end);
 
191
 
 
192
        if (end == hostport.length() - 1)
 
193
          ports = "";
 
194
        else if (hostport.charAt(end + 1) == ':')
 
195
          ports = hostport.substring(end + 2);
 
196
        else
 
197
          throw new IllegalArgumentException("Bad character after ']'");
 
198
      }
 
199
    else
 
200
      {
 
201
        // host is a hostname or IPv4 address
 
202
        int sep = hostport.indexOf(":");
 
203
        if (sep == -1)
 
204
          {
 
205
            host = hostport;
 
206
            ports = "";
 
207
          }
 
208
        else
 
209
          {
 
210
            host = hostport.substring(0, sep);
 
211
            ports = hostport.substring(sep + 1);
 
212
          }
 
213
      }
 
214
    if (ports.indexOf(":") != -1)
 
215
      throw new IllegalArgumentException("Unexpected ':'");
 
216
 
 
217
    // Parse and validate the ports
 
218
    if (ports.length() == 0)
 
219
      {
 
220
        minport = MIN_PORT;
 
221
        maxport = MAX_PORT;
 
222
      }
 
223
    else
 
224
      {
 
225
        int sep = ports.indexOf("-");
 
226
        if (sep == -1)
 
227
          {
 
228
            // a single port
 
229
            minport = maxport = Integer.parseInt(ports);
 
230
          }
 
231
        else
 
232
          {
 
233
            if (ports.indexOf("-", sep + 1) != -1)
 
234
              throw new IllegalArgumentException("Unexpected '-'");
 
235
 
 
236
            if (sep == 0)
 
237
              {
 
238
                // an upper bound
 
239
                minport = MIN_PORT;
 
240
                maxport = Integer.parseInt(ports.substring(1));
 
241
              }
 
242
            else if (sep == ports.length() - 1)
 
243
              {
 
244
                // a lower bound
 
245
                minport =
 
246
                  Integer.parseInt(ports.substring(0, ports.length() - 1));
 
247
                maxport = MAX_PORT;
 
248
              }
 
249
            else
 
250
              {
 
251
                // a range with two bounds
 
252
                minport = Integer.parseInt(ports.substring(0, sep));
 
253
                maxport = Integer.parseInt(ports.substring(sep + 1));
 
254
              }
 
255
          }
 
256
      }
 
257
  }
 
258
  
 
259
  /**
 
260
   * Parse the actions argument to the constructor.
 
261
   */
 
262
  private void setActions(String actionstring)
 
263
  {
 
264
    actionmask = 0;
 
265
 
 
266
    boolean resolve_needed = false;
 
267
    boolean resolve_present = false;
 
268
    
 
269
    StringTokenizer t = new StringTokenizer(actionstring, ",");
 
270
    while (t.hasMoreTokens())
 
271
      {
 
272
        String action = t.nextToken();
 
273
        action = action.trim().toLowerCase();
 
274
        setAction(action);
 
275
 
 
276
        if (action.equals("resolve"))
 
277
          resolve_present = true;
 
278
        else
 
279
          resolve_needed = true;
 
280
      }
 
281
 
 
282
    if (resolve_needed && !resolve_present)
 
283
      setAction("resolve");
 
284
  }
 
285
 
 
286
  /**
 
287
   * Parse one element of the actions argument to the constructor.
 
288
   */
 
289
  private void setAction(String action)
 
290
  {
 
291
    for (int i = 0; i < ACTIONS.length; i++)
 
292
      {
 
293
        if (action.equals(ACTIONS[i]))
 
294
          {
 
295
            actionmask |= 1 << i;
 
296
            return;
 
297
          }
 
298
      }
 
299
    throw new IllegalArgumentException("Unknown action " + action);
138
300
  }
139
301
 
140
302
  /**
150
312
   */
151
313
  public boolean equals(Object obj)
152
314
  {
153
 
    if (! (obj instanceof SocketPermission))
 
315
    SocketPermission p;
 
316
 
 
317
    if (obj instanceof SocketPermission)
 
318
      p = (SocketPermission) obj;
 
319
    else
154
320
      return false;
155
321
 
156
 
    if (((SocketPermission) obj).hostport.equals(hostport))
157
 
      if (((SocketPermission) obj).actions.equals(actions))
158
 
        return true;
159
 
 
160
 
    return false;
 
322
    return p.actionmask == actionmask &&
 
323
      p.minport == minport &&
 
324
      p.maxport == maxport &&
 
325
      p.host.equals(host);
161
326
  }
162
327
 
163
328
  /**
168
333
   */
169
334
  public int hashCode()
170
335
  {
171
 
    int hash = 100;
172
 
    if (hostport != null)
173
 
      hash += hostport.hashCode();
174
 
    if (actions != null)
175
 
      hash += actions.hashCode();
176
 
    return hash;
 
336
    return actionmask + minport + maxport + host.hashCode();
177
337
  }
178
338
 
179
339
  /**
184
344
   */
185
345
  public String getActions()
186
346
  {
187
 
    boolean found = false;
188
347
    StringBuffer sb = new StringBuffer("");
189
348
 
190
 
    if (actions.indexOf("connect") != -1)
 
349
    for (int i = 0; i < ACTIONS.length; i++)
191
350
      {
192
 
        sb.append("connect");
193
 
        found = true;
 
351
        if ((actionmask & (1 << i)) != 0)
 
352
          {
 
353
            if (sb.length() != 0)
 
354
              sb.append(",");
 
355
            sb.append(ACTIONS[i]);
 
356
          }
194
357
      }
195
358
 
196
 
    if (actions.indexOf("listen") != -1)
197
 
      if (found)
198
 
        sb.append(",listen");
199
 
      else
200
 
        {
201
 
          sb.append("listen");
202
 
          found = true;
203
 
        }
204
 
 
205
 
    if (actions.indexOf("accept") != -1)
206
 
      if (found)
207
 
        sb.append(",accept");
208
 
      else
209
 
        {
210
 
          sb.append("accept");
211
 
          found = true;
212
 
        }
213
 
 
214
 
    if (found)
215
 
      sb.append(",resolve");
216
 
    else if (actions.indexOf("resolve") != -1)
217
 
      sb.append("resolve");
218
 
 
219
359
    return sb.toString();
220
360
  }
221
361
 
268
408
      return false;
269
409
 
270
410
    // Next check the actions
271
 
    String ourlist = getActions();
272
 
    String theirlist = p.getActions();
273
 
 
274
 
    if (! ourlist.startsWith(theirlist))
275
 
      return false;
276
 
 
277
 
    // Now check ports
278
 
    int ourfirstport = 0;
279
 
 
280
 
    // Now check ports
281
 
    int ourlastport = 0;
282
 
 
283
 
    // Now check ports
284
 
    int theirfirstport = 0;
285
 
 
286
 
    // Now check ports
287
 
    int theirlastport = 0;
288
 
 
289
 
    // Get ours
290
 
    if (hostport.indexOf(":") == -1)
291
 
      {
292
 
        ourfirstport = 0;
293
 
        ourlastport = 65535;
294
 
      }
295
 
    else
296
 
      {
297
 
        // FIXME:  Needs bulletproofing.
298
 
        // This will dump if hostport if all sorts of bad data was passed to
299
 
        // the constructor
300
 
        String range = hostport.substring(hostport.indexOf(":") + 1);
301
 
        if (range.startsWith("-"))
302
 
          ourfirstport = 0;
303
 
        else if (range.indexOf("-") == -1)
304
 
          ourfirstport = Integer.parseInt(range);
305
 
        else
306
 
          ourfirstport =
307
 
            Integer.parseInt(range.substring(0, range.indexOf("-")));
308
 
 
309
 
        if (range.endsWith("-"))
310
 
          ourlastport = 65535;
311
 
        else if (range.indexOf("-") == -1)
312
 
          ourlastport = Integer.parseInt(range);
313
 
        else
314
 
          ourlastport =
315
 
            Integer.parseInt(range.substring(range.indexOf("-") + 1,
316
 
                                             range.length()));
317
 
      }
318
 
 
319
 
    // Get theirs
320
 
    if (p.hostport.indexOf(":") == -1)
321
 
      {
322
 
        theirfirstport = 0;
323
 
        ourlastport = 65535;
324
 
      }
325
 
    else
326
 
      {
327
 
        // This will dump if hostport if all sorts of bad data was passed to
328
 
        // the constructor
329
 
        String range = p.hostport.substring(hostport.indexOf(":") + 1);
330
 
        if (range.startsWith("-"))
331
 
          theirfirstport = 0;
332
 
        else if (range.indexOf("-") == -1)
333
 
          theirfirstport = Integer.parseInt(range);
334
 
        else
335
 
          theirfirstport =
336
 
            Integer.parseInt(range.substring(0, range.indexOf("-")));
337
 
 
338
 
        if (range.endsWith("-"))
339
 
          theirlastport = 65535;
340
 
        else if (range.indexOf("-") == -1)
341
 
          theirlastport = Integer.parseInt(range);
342
 
        else
343
 
          theirlastport =
344
 
            Integer.parseInt(range.substring(range.indexOf("-") + 1,
345
 
                                             range.length()));
346
 
      }
347
 
 
348
 
    // Now check them
349
 
    if ((theirfirstport < ourfirstport) || (theirlastport > ourlastport))
350
 
      return false;
351
 
 
352
 
    // Finally we can check the hosts
353
 
    String ourhost;
354
 
 
355
 
    // Finally we can check the hosts
356
 
    String theirhost;
357
 
 
358
 
    // Get ours
359
 
    if (hostport.indexOf(":") == -1)
360
 
      ourhost = hostport;
361
 
    else
362
 
      ourhost = hostport.substring(0, hostport.indexOf(":"));
363
 
 
364
 
    // Get theirs
365
 
    if (p.hostport.indexOf(":") == -1)
366
 
      theirhost = p.hostport;
367
 
    else
368
 
      theirhost = p.hostport.substring(0, p.hostport.indexOf(":"));
369
 
 
370
 
    // Are they equal?
371
 
    if (ourhost.equals(theirhost))
 
411
    if ((p.actionmask & actionmask) != p.actionmask)
 
412
        return false;
 
413
 
 
414
    // Then check the ports
 
415
    if ((p.minport < minport) || (p.maxport > maxport))
 
416
      return false;
 
417
 
 
418
    // Finally check the hosts
 
419
    if (host.equals(p.host))
372
420
      return true;
373
421
 
374
422
    // Try the canonical names
375
423
    String ourcanonical = null;
376
 
 
377
 
    // Try the canonical names
378
424
    String theircanonical = null;
379
425
    try
380
426
      {
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();
383
429
      }
384
430
    catch (UnknownHostException e)
385
431
      {
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;
 
435
          ourcanonical = host;
390
436
        if (theircanonical == null)
391
 
          theircanonical = theirhost;
 
437
          theircanonical = p.host;
392
438
      }
393
439
 
394
440
    if (ourcanonical.equals(theircanonical))
395
441
      return true;
396
442
 
397
443
    // Well, last chance.  Try for a wildcard
398
 
    if (ourhost.indexOf("*.") != -1)
 
444
    if (host.indexOf("*.") != -1)
399
445
      {
400
 
        String wild_domain = ourhost.substring(ourhost.indexOf("*" + 1));
 
446
        String wild_domain =
 
447
          host.substring(host.indexOf("*" + 1));
401
448
        if (theircanonical.endsWith(wild_domain))
402
449
          return true;
403
450
      }
405
452
    // Didn't make it
406
453
    return false;
407
454
  }
 
455
 
 
456
  /**
 
457
   * Deserializes a <code>SocketPermission</code> object from
 
458
   * an input stream.
 
459
   *
 
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.
 
464
   */
 
465
  private void readObject(ObjectInputStream input)
 
466
    throws IOException, ClassNotFoundException
 
467
  {
 
468
    input.defaultReadObject();
 
469
    setHostPort(getName());
 
470
    setActions(actions);
 
471
  }
 
472
 
 
473
  /**
 
474
   * Serializes a <code>SocketPermission</code> object to an
 
475
   * output stream.
 
476
   *
 
477
   * @param output the output stream.
 
478
   * @throws IOException if an I/O error occurs in the stream.
 
479
   */
 
480
  private void writeObject(ObjectOutputStream output)
 
481
    throws IOException
 
482
  {
 
483
    actions = getActions();
 
484
    output.defaultWriteObject();
 
485
  }
408
486
}