source: trunk/gcc/libjava/java/security/CodeSource.java

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 11.9 KB
Line 
1/* CodeSource.java -- Code location and certifcates
2 Copyright (C) 1998, 2002 Free Software Foundation, Inc.
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38
39package java.security;
40
41import java.io.ByteArrayInputStream;
42import java.io.IOException;
43import java.io.ObjectInputStream;
44import java.io.ObjectOutputStream;
45import java.io.Serializable;
46import java.net.URL;
47import java.net.SocketPermission;
48// Note that this overrides Certificate in this package.
49import java.security.cert.Certificate;
50import java.security.cert.CertificateFactory;
51import java.security.cert.CertificateEncodingException;
52import java.security.cert.CertificateException;
53import java.util.Arrays;
54import java.util.HashSet;
55import java.util.Iterator;
56
57/**
58 * This class represents a location from which code is loaded (as
59 * represented by a URL), and the list of certificates that are used to
60 * check the signatures of signed code loaded from this source.
61 *
62 * @author Aaron M. Renn <arenn@urbanophile.com>
63 * @author Eric Blake <ebb9@email.byu.edu>
64 * @since 1.1
65 * @status updated to 1.4
66 */
67public class CodeSource implements Serializable
68{
69 /**
70 * Compatible with JDK 1.1+.
71 */
72 private static final long serialVersionUID = 4977541819976013951L;
73
74 /**
75 * This is the URL that represents the code base from which code will
76 * be loaded.
77 *
78 * @serial the code location
79 */
80 private final URL location;
81
82 /** The set of certificates for this code base. */
83 private transient HashSet certs;
84
85 /**
86 * This creates a new instance of <code>CodeSource</code> that loads code
87 * from the specified URL location and which uses the specified certificates
88 * for verifying signatures.
89 *
90 * @param location the location from which code will be loaded
91 * @param certs the list of certificates
92 */
93 public CodeSource(URL location, Certificate[] certs)
94 {
95 this.location = location;
96 if (certs != null)
97 this.certs = new HashSet(Arrays.asList(certs));
98 }
99
100 /**
101 * This method returns a hash value for this object.
102 *
103 * @return a hash value for this object
104 */
105 public int hashCode()
106 {
107 return (location == null ? 0 : location.hashCode())
108 ^ (certs == null ? 0 : certs.hashCode());
109 }
110
111 /**
112 * This method tests the specified <code>Object</code> for equality with
113 * this object. This will be true if and only if the locations are equal
114 * and the certificate sets are identical (ignoring order).
115 *
116 * @param obj the <code>Object</code> to test against
117 * @return true if the specified object is equal to this one
118 */
119 public boolean equals(Object obj)
120 {
121 if (! (obj instanceof CodeSource))
122 return false;
123 CodeSource cs = (CodeSource) obj;
124 return (certs == null ? cs.certs == null : certs.equals(cs.certs))
125 && (location == null ? cs.location == null
126 : location.equals(cs.location));
127 }
128
129 /**
130 * This method returns the URL specifying the location from which code
131 * will be loaded under this <code>CodeSource</code>.
132 *
133 * @return the code location for this <code>CodeSource</code>
134 */
135 public final URL getLocation()
136 {
137 return location;
138 }
139
140 /**
141 * This method returns the list of digital certificates that can be used
142 * to verify the signatures of code loaded under this
143 * <code>CodeSource</code>.
144 *
145 * @return the certifcate list for this <code>CodeSource</code>
146 */
147 public final Certificate[] getCertificates()
148 {
149 if (certs == null)
150 return null;
151 Certificate[] c = new Certificate[certs.size()];
152 certs.toArray(c);
153 return c;
154 }
155
156 /**
157 * This method tests to see if a specified <code>CodeSource</code> is
158 * implied by this object. Effectively, to meet this test, the specified
159 * object must have all the certifcates this object has (but may have more),
160 * and must have a location that is a subset of this object's. In order
161 * for this object to imply the specified object, the following must be
162 * true:<ol>
163 * <li><em>codesource</em> must not be <code>null</code>.</li>
164 * <li>If <em>codesource</em> has a certificate list, all of it's
165 * certificates must be present in the certificate list of this
166 * code source.</li>
167 * <li>If this object does not have a <code>null</code> location, then
168 * the following addtional tests must be passed.<ol>
169 * <li><em>codesource</em> must not have a <code>null</code>
170 * location.</li>
171 * <li><em>codesource</em>'s location must be equal to this object's
172 * location, or<br><ul>
173 * <li><em>codesource</em>'s location protocol, port, and ref (aka,
174 * anchor) must equal this objects</li>
175 * <li><em>codesource</em>'s location host must imply this object's
176 * location host, as determined by contructing
177 * <code>SocketPermission</code> objects from each with no
178 * action list and using that classes's <code>implies</code>
179 * method</li>
180 * <li>If this object's location file ends with a '/', then the
181 * specified object's location file must start with this
182 * object's location file. Otherwise, the specified object's
183 * location file must start with this object's location file
184 * with the '/' character appended to it.</li>
185 * </ul></li>
186 * </ol>
187 * </ol>
188 *
189 * <p>For example, each of these locations imply the location
190 * "http://java.sun.com/classes/foo.jar":<ul>
191 * <pre>
192 * http:
193 * http://*.sun.com/classes/*
194 * http://java.sun.com/classes/-
195 * http://java.sun.com/classes/foo.jar
196 * </pre>
197 * Note that the code source with null location and null certificates implies
198 * all other code sources.
199 *
200 * @param cs the <code>CodeSource</code> to test against this object
201 * @return true if this specified <code>CodeSource</code> is implied
202 */
203 public boolean implies(CodeSource cs)
204 {
205 if (cs == null)
206 return false;
207 // First check the certificate list.
208 if (certs != null && (cs.certs == null || ! certs.containsAll(cs.certs)))
209 return false;
210 // Next check the location.
211 if (location == null)
212 return true;
213 if (cs.location == null
214 || ! location.getProtocol().equals(cs.location.getProtocol())
215 || (location.getPort() != -1
216 && location.getPort() != cs.location.getPort())
217 || (location.getRef() != null
218 && ! location.getRef().equals(cs.location.getRef())))
219 return false;
220 if (location.getHost() != null)
221 {
222 String their_host = cs.location.getHost();
223 if (their_host == null)
224 return false;
225 SocketPermission our_sockperm =
226 new SocketPermission(location.getHost(), "accept");
227 SocketPermission their_sockperm =
228 new SocketPermission(their_host, "accept");
229 if (! our_sockperm.implies(their_sockperm))
230 return false;
231 }
232 String our_file = location.getFile();
233 if (our_file != null)
234 {
235 if (! our_file.endsWith("/"))
236 our_file += "/";
237 String their_file = cs.location.getFile();
238 if (their_file == null
239 || ! their_file.startsWith(our_file))
240 return false;
241 }
242 return true;
243 }
244
245 /**
246 * This method returns a <code>String</code> that represents this object.
247 * The result is in the format <code>"(" + getLocation()</code> followed
248 * by a space separated list of certificates (or "<no certificates>"),
249 * followed by <code>")"</code>.
250 *
251 * @return a <code>String</code> for this object
252 */
253 public String toString()
254 {
255 StringBuffer sb = new StringBuffer("(").append(location);
256 if (certs == null || certs.isEmpty())
257 sb.append(" <no certificates>");
258 else
259 {
260 Iterator iter = certs.iterator();
261 for (int i = certs.size(); --i >= 0; )
262 sb.append(' ').append(iter.next());
263 }
264 return sb.append(")").toString();
265 }
266
267 /**
268 * Reads this object from a serialization stream.
269 *
270 * @param s the input stream
271 * @throws IOException if reading fails
272 * @throws ClassNotFoundException if deserialization fails
273 * @serialData this reads the location, then expects an int indicating the
274 * number of certificates. Each certificate is a String type
275 * followed by an int encoding length, then a byte[] encoding
276 */
277 private void readObject(ObjectInputStream s)
278 throws IOException, ClassNotFoundException
279 {
280 s.defaultReadObject();
281 int count = s.readInt();
282 certs = new HashSet();
283 while (--count >= 0)
284 {
285 String type = (String) s.readObject();
286 int bytes = s.readInt();
287 byte[] encoded = new byte[bytes];
288 for (int i = 0; i < bytes; i++)
289 encoded[i] = s.readByte();
290 ByteArrayInputStream stream = new ByteArrayInputStream(encoded);
291 try
292 {
293 CertificateFactory factory = CertificateFactory.getInstance(type);
294 certs.add(factory.generateCertificate(stream));
295 }
296 catch (CertificateException e)
297 {
298 // XXX Should we ignore this certificate?
299 }
300 }
301 }
302
303 /**
304 * Writes this object to a serialization stream.
305 *
306 * @param s the output stream
307 * @throws IOException if writing fails
308 * @serialData this writes the location, then writes an int indicating the
309 * number of certificates. Each certificate is a String type
310 * followed by an int encoding length, then a byte[] encoding
311 */
312 private void writeObject(ObjectOutputStream s) throws IOException
313 {
314 s.defaultWriteObject();
315 if (certs == null)
316 s.writeInt(0);
317 else
318 {
319 int count = certs.size();
320 s.writeInt(count);
321 Iterator iter = certs.iterator();
322 while (--count >= 0)
323 {
324 Certificate c = (Certificate) iter.next();
325 s.writeObject(c.getType());
326 byte[] encoded;
327 try
328 {
329 encoded = c.getEncoded();
330 }
331 catch (CertificateEncodingException e)
332 {
333 // XXX Should we ignore this certificate?
334 encoded = null;
335 }
336 if (encoded == null)
337 s.writeInt(0);
338 else
339 {
340 s.writeInt(encoded.length);
341 for (int i = 0; i < encoded.length; i++)
342 s.writeByte(encoded[i]);
343 }
344 }
345 }
346 }
347} // class CodeSource
Note: See TracBrowser for help on using the repository browser.