Source Code Cross Referenced for CodeSource.java in  » 6.0-JDK-Core » security » java » security » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » security » java.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.security;
027
028        import java.net.URL;
029        import java.net.SocketPermission;
030        import java.util.ArrayList;
031        import java.util.List;
032        import java.util.Hashtable;
033        import java.io.ByteArrayInputStream;
034        import java.io.IOException;
035        import java.security.cert.*;
036
037        /**
038         *
039         * <p>This class extends the concept of a codebase to
040         * encapsulate not only the location (URL) but also the certificate chains 
041         * that were used to verify signed code originating from that location.
042         *
043         * @version 	1.48, 05/05/07
044         * @author Li Gong
045         * @author Roland Schemers
046         */
047
048        public class CodeSource implements  java.io.Serializable {
049
050            private static final long serialVersionUID = 4977541819976013951L;
051
052            /**
053             * The code location.
054             *
055             * @serial
056             */
057            private URL location;
058
059            /*
060             * The code signers.
061             */
062            private transient CodeSigner[] signers = null;
063
064            /*
065             * The code signers. Certificate chains are concatenated.
066             */
067            private transient java.security.cert.Certificate certs[] = null;
068
069            // cached SocketPermission used for matchLocation
070            private transient SocketPermission sp;
071
072            // for generating cert paths
073            private transient CertificateFactory factory = null;
074
075            /**
076             * Constructs a CodeSource and associates it with the specified 
077             * location and set of certificates.
078             * 
079             * @param url the location (URL).
080             * 
081             * @param certs the certificate(s). It may be null. The contents of the 
082             * array are copied to protect against subsequent modification.
083             */
084            public CodeSource(URL url, java.security.cert.Certificate certs[]) {
085                this .location = url;
086
087                // Copy the supplied certs
088                if (certs != null) {
089                    this .certs = (java.security.cert.Certificate[]) certs
090                            .clone();
091                }
092            }
093
094            /**
095             * Constructs a CodeSource and associates it with the specified 
096             * location and set of code signers.
097             * 
098             * @param url the location (URL).
099             * @param signers the code signers. It may be null. The contents of the 
100             * array are copied to protect against subsequent modification.
101             *
102             * @since 1.5
103             */
104            public CodeSource(URL url, CodeSigner[] signers) {
105                this .location = url;
106
107                // Copy the supplied signers
108                if (signers != null) {
109                    this .signers = (CodeSigner[]) signers.clone();
110                }
111            }
112
113            /**
114             * Returns the hash code value for this object.
115             *
116             * @return a hash code value for this object.
117             */
118
119            public int hashCode() {
120                if (location != null)
121                    return location.hashCode();
122                else
123                    return 0;
124            }
125
126            /**
127             * Tests for equality between the specified object and this
128             * object. Two CodeSource objects are considered equal if their 
129             * locations are of identical value and if their signer certificate
130             * chains are of identical value. It is not required that
131             * the certificate chains be in the same order.
132             * 
133             * @param obj the object to test for equality with this object.
134             * 
135             * @return true if the objects are considered equal, false otherwise.
136             */
137            public boolean equals(Object obj) {
138                if (obj == this )
139                    return true;
140
141                // objects types must be equal
142                if (!(obj instanceof  CodeSource))
143                    return false;
144
145                CodeSource cs = (CodeSource) obj;
146
147                // URLs must match
148                if (location == null) {
149                    // if location is null, then cs.location must be null as well
150                    if (cs.location != null)
151                        return false;
152                } else {
153                    // if location is not null, then it must equal cs.location
154                    if (!location.equals(cs.location))
155                        return false;
156                }
157
158                // certs must match
159                return matchCerts(cs, true);
160            }
161
162            /**
163             * Returns the location associated with this CodeSource.
164             * 
165             * @return the location (URL).
166             */
167            public final URL getLocation() {
168                /* since URL is practically immutable, returning itself is not
169                       a security problem */
170                return this .location;
171            }
172
173            /**
174             * Returns the certificates associated with this CodeSource.
175             * <p>
176             * If this CodeSource object was created using the
177             * {@link #CodeSource(URL url, CodeSigner[] signers)}
178             * constructor then its certificate chains are extracted and used to 
179             * create an array of Certificate objects. Each signer certificate is 
180             * followed by its supporting certificate chain (which may be empty). 
181             * Each signer certificate and its supporting certificate chain is ordered 
182             * bottom-to-top (i.e., with the signer certificate first and the (root) 
183             * certificate authority last).
184             * 
185             * @return A copy of the certificates array, or null if there is none. 
186             */
187            public final java.security.cert.Certificate[] getCertificates() {
188                if (certs != null) {
189                    return (java.security.cert.Certificate[]) certs.clone();
190
191                } else if (signers != null) {
192                    // Convert the code signers to certs
193                    ArrayList<java.security.cert.Certificate> certChains = new ArrayList<java.security.cert.Certificate>();
194                    for (int i = 0; i < signers.length; i++) {
195                        certChains.addAll(signers[i].getSignerCertPath()
196                                .getCertificates());
197                    }
198                    certs = certChains
199                            .toArray(new java.security.cert.Certificate[certChains
200                                    .size()]);
201                    return certs.clone();
202
203                } else {
204                    return null;
205                }
206            }
207
208            /**
209             * Returns the code signers associated with this CodeSource.
210             * <p>
211             * If this CodeSource object was created using the
212             * {@link #CodeSource(URL url, Certificate[] certs)}
213             * constructor then its certificate chains are extracted and used to 
214             * create an array of CodeSigner objects. Note that only X.509 certificates
215             * are examined - all other certificate types are ignored.
216             *
217             * @return A copy of the code signer array, or null if there is none.
218             *
219             * @since 1.5
220             */
221            public final CodeSigner[] getCodeSigners() {
222                if (signers != null) {
223                    return (CodeSigner[]) signers.clone();
224
225                } else if (certs != null) {
226                    // Convert the certs to code signers
227                    signers = convertCertArrayToSignerArray(certs);
228                    return (CodeSigner[]) signers.clone();
229
230                } else {
231                    return null;
232                }
233            }
234
235            /**
236             * Returns true if this CodeSource object "implies" the specified CodeSource.
237             * <P>
238             * More specifically, this method makes the following checks, in order. 
239             * If any fail, it returns false. If they all succeed, it returns true.<p>
240             * <ol>
241             * <li> <i>codesource</i> must not be null.
242             * <li> If this object's certificates are not null, then all
243             * of this object's certificates must be present in <i>codesource</i>'s 
244             * certificates.
245             * <li> If this object's location (getLocation()) is not null, then the 
246             * following checks are made against this object's location and 
247             * <i>codesource</i>'s:<p>
248             *   <ol>
249             *     <li>  <i>codesource</i>'s location must not be null.
250             *
251             *     <li>  If this object's location 
252             *           equals <i>codesource</i>'s location, then return true.
253             *
254             *     <li>  This object's protocol (getLocation().getProtocol()) must be
255             *           equal to <i>codesource</i>'s protocol.
256             *
257             *     <li>  If this object's host (getLocation().getHost()) is not null,  
258             *           then the SocketPermission
259             *           constructed with this object's host must imply the
260             *           SocketPermission constructed with <i>codesource</i>'s host.
261             *
262             *     <li>  If this object's port (getLocation().getPort()) is not 
263             *           equal to -1 (that is, if a port is specified), it must equal 
264             *           <i>codesource</i>'s port.
265             *
266             *     <li>  If this object's file (getLocation().getFile()) doesn't equal
267             *           <i>codesource</i>'s file, then the following checks are made:
268             *           If this object's file ends with "/-",
269             *           then <i>codesource</i>'s file must start with this object's
270             *           file (exclusive the trailing "-").
271             *           If this object's file ends with a "/*",
272             *           then <i>codesource</i>'s file must start with this object's
273             *           file and must not have any further "/" separators.
274             *           If this object's file doesn't end with a "/", 
275             *           then <i>codesource</i>'s file must match this object's 
276             *           file with a '/' appended.
277             *
278             *     <li>  If this object's reference (getLocation().getRef()) is 
279             *           not null, it must equal <i>codesource</i>'s reference.
280             *
281             *   </ol>
282             * </ol>
283             * <p>
284             * For example, the codesource objects with the following locations
285             * and null certificates all imply
286             * the codesource with the location "http://java.sun.com/classes/foo.jar"
287             * and null certificates:
288             * <pre>
289             *     http:
290             *     http://*.sun.com/classes/*
291             *     http://java.sun.com/classes/-
292             *     http://java.sun.com/classes/foo.jar
293             * </pre>
294             * 
295             * Note that if this CodeSource has a null location and a null
296             * certificate chain, then it implies every other CodeSource.
297             *
298             * @param codesource CodeSource to compare against.
299             *
300             * @return true if the specified codesource is implied by this codesource,
301             * false if not.  
302             */
303
304            public boolean implies(CodeSource codesource) {
305                if (codesource == null)
306                    return false;
307
308                return matchCerts(codesource, false)
309                        && matchLocation(codesource);
310            }
311
312            /**
313             * Returns true if all the certs in this
314             * CodeSource are also in <i>that</i>.
315             * 
316             * @param that the CodeSource to check against.
317             * @param strict If true then a strict equality match is performed.
318             *               Otherwise a subset match is performed.
319             */
320            private boolean matchCerts(CodeSource that, boolean strict) {
321                boolean match;
322
323                // match any key
324                if (certs == null && signers == null) {
325                    if (strict) {
326                        return (that.certs == null && that.signers == null);
327                    } else {
328                        return true;
329                    }
330                    // both have signers
331                } else if (signers != null && that.signers != null) {
332                    if (strict && signers.length != that.signers.length) {
333                        return false;
334                    }
335                    for (int i = 0; i < signers.length; i++) {
336                        match = false;
337                        for (int j = 0; j < that.signers.length; j++) {
338                            if (signers[i].equals(that.signers[j])) {
339                                match = true;
340                                break;
341                            }
342                        }
343                        if (!match)
344                            return false;
345                    }
346                    return true;
347
348                    // both have certs
349                } else if (certs != null && that.certs != null) {
350                    if (strict && certs.length != that.certs.length) {
351                        return false;
352                    }
353                    for (int i = 0; i < certs.length; i++) {
354                        match = false;
355                        for (int j = 0; j < that.certs.length; j++) {
356                            if (certs[i].equals(that.certs[j])) {
357                                match = true;
358                                break;
359                            }
360                        }
361                        if (!match)
362                            return false;
363                    }
364                    return true;
365                }
366
367                return false;
368            }
369
370            /**
371             * Returns true if two CodeSource's have the "same" location.
372             * 
373             * @param that CodeSource to compare against
374             */
375            private boolean matchLocation(CodeSource that) {
376                if (location == null) {
377                    return true;
378                }
379
380                if ((that == null) || (that.location == null))
381                    return false;
382
383                if (location.equals(that.location))
384                    return true;
385
386                if (!location.getProtocol().equals(that.location.getProtocol()))
387                    return false;
388
389                String this Host = location.getHost();
390                String thatHost = that.location.getHost();
391
392                if (this Host != null) {
393                    if (("".equals(this Host) || "localhost".equals(this Host))
394                            && ("".equals(thatHost) || "localhost"
395                                    .equals(thatHost))) {
396                        // ok
397                    } else if (!this Host.equals(thatHost)) {
398                        if (thatHost == null) {
399                            return false;
400                        }
401                        if (this .sp == null) {
402                            this .sp = new SocketPermission(this Host, "resolve");
403                        }
404                        if (that.sp == null) {
405                            that.sp = new SocketPermission(thatHost, "resolve");
406                        }
407                        if (!this .sp.implies(that.sp)) {
408                            return false;
409                        }
410                    }
411                }
412
413                if (location.getPort() != -1) {
414                    if (location.getPort() != that.location.getPort())
415                        return false;
416                }
417
418                if (location.getFile().endsWith("/-")) {
419                    // Matches the directory and (recursively) all files
420                    // and subdirectories contained in that directory.
421                    // For example, "/a/b/-" implies anything that starts with
422                    // "/a/b/"
423                    String this Path = location.getFile().substring(0,
424                            location.getFile().length() - 1);
425                    if (!that.location.getFile().startsWith(this Path))
426                        return false;
427                } else if (location.getFile().endsWith("/*")) {
428                    // Matches the directory and all the files contained in that
429                    // directory.
430                    // For example, "/a/b/*" implies anything that starts with
431                    // "/a/b/" but has no further slashes
432                    int last = that.location.getFile().lastIndexOf('/');
433                    if (last == -1)
434                        return false;
435                    String this Path = location.getFile().substring(0,
436                            location.getFile().length() - 1);
437                    String thatPath = that.location.getFile().substring(0,
438                            last + 1);
439                    if (!thatPath.equals(this Path))
440                        return false;
441                } else {
442                    // Exact matches only.
443                    // For example, "/a/b" and "/a/b/" both imply "/a/b/" 
444                    if ((!that.location.getFile().equals(location.getFile()))
445                            && (!that.location.getFile().equals(
446                                    location.getFile() + "/"))) {
447                        return false;
448                    }
449                }
450
451                if (location.getRef() == null)
452                    return true;
453                else
454                    return location.getRef().equals(that.location.getRef());
455            }
456
457            /**
458             * Returns a string describing this CodeSource, telling its
459             * URL and certificates.
460             * 
461             * @return information about this CodeSource.
462             */
463            public String toString() {
464                StringBuilder sb = new StringBuilder();
465                sb.append("(");
466                sb.append(this .location);
467
468                if (this .certs != null && this .certs.length > 0) {
469                    for (int i = 0; i < this .certs.length; i++) {
470                        sb.append(" " + this .certs[i]);
471                    }
472
473                } else if (this .signers != null && this .signers.length > 0) {
474                    for (int i = 0; i < this .signers.length; i++) {
475                        sb.append(" " + this .signers[i]);
476                    }
477                } else {
478                    sb.append(" <no signer certificates>");
479                }
480                sb.append(")");
481                return sb.toString();
482            }
483
484            /**
485             * Writes this object out to a stream (i.e., serializes it).
486             *
487             * @serialData An initial <code>URL</code> is followed by an
488             * <code>int</code> indicating the number of certificates to follow 
489             * (a value of "zero" denotes that there are no certificates associated
490             * with this object).
491             * Each certificate is written out starting with a <code>String</code>
492             * denoting the certificate type, followed by an
493             * <code>int</code> specifying the length of the certificate encoding,
494             * followed by the certificate encoding itself which is written out as an
495             * array of bytes. Finally, if any code signers are present then the array 
496             * of code signers is serialized and written out too.
497             */
498            private void writeObject(java.io.ObjectOutputStream oos)
499                    throws IOException {
500                oos.defaultWriteObject(); // location
501
502                // Serialize the array of certs
503                if (certs == null || certs.length == 0) {
504                    oos.writeInt(0);
505                } else {
506                    // write out the total number of certs
507                    oos.writeInt(certs.length);
508                    // write out each cert, including its type
509                    for (int i = 0; i < certs.length; i++) {
510                        java.security.cert.Certificate cert = certs[i];
511                        try {
512                            oos.writeUTF(cert.getType());
513                            byte[] encoded = cert.getEncoded();
514                            oos.writeInt(encoded.length);
515                            oos.write(encoded);
516                        } catch (CertificateEncodingException cee) {
517                            throw new IOException(cee.getMessage());
518                        }
519                    }
520                }
521
522                // Serialize the array of code signers (if any)
523                if (signers != null && signers.length > 0) {
524                    oos.writeObject(signers);
525                }
526            }
527
528            /**
529             * Restores this object from a stream (i.e., deserializes it).
530             */
531            private void readObject(java.io.ObjectInputStream ois)
532                    throws IOException, ClassNotFoundException {
533                CertificateFactory cf;
534                Hashtable<String, CertificateFactory> cfs = null;
535
536                ois.defaultReadObject(); // location
537
538                // process any new-style certs in the stream (if present)
539                int size = ois.readInt();
540                if (size > 0) {
541                    // we know of 3 different cert types: X.509, PGP, SDSI, which
542                    // could all be present in the stream at the same time
543                    cfs = new Hashtable<String, CertificateFactory>(3);
544                    this .certs = new java.security.cert.Certificate[size];
545                }
546
547                for (int i = 0; i < size; i++) {
548                    // read the certificate type, and instantiate a certificate
549                    // factory of that type (reuse existing factory if possible)
550                    String certType = ois.readUTF();
551                    if (cfs.containsKey(certType)) {
552                        // reuse certificate factory
553                        cf = cfs.get(certType);
554                    } else {
555                        // create new certificate factory
556                        try {
557                            cf = CertificateFactory.getInstance(certType);
558                        } catch (CertificateException ce) {
559                            throw new ClassNotFoundException(
560                                    "Certificate factory for " + certType
561                                            + " not found");
562                        }
563                        // store the certificate factory so we can reuse it later
564                        cfs.put(certType, cf);
565                    }
566                    // parse the certificate
567                    byte[] encoded = null;
568                    try {
569                        encoded = new byte[ois.readInt()];
570                    } catch (OutOfMemoryError oome) {
571                        throw new IOException("Certificate too big");
572                    }
573                    ois.readFully(encoded);
574                    ByteArrayInputStream bais = new ByteArrayInputStream(
575                            encoded);
576                    try {
577                        this .certs[i] = cf.generateCertificate(bais);
578                    } catch (CertificateException ce) {
579                        throw new IOException(ce.getMessage());
580                    }
581                    bais.close();
582                }
583
584                // Deserialize array of code signers (if any)
585                try {
586                    this .signers = (CodeSigner[]) ois.readObject();
587                } catch (IOException ioe) {
588                    // no signers present
589                }
590            }
591
592            /*
593             * Convert an array of certificates to an array of code signers.
594             * The array of certificates is a concatenation of certificate chains
595             * where the initial certificate in each chain is the end-entity cert.
596             *
597             * @return An array of code signers or null if none are generated.
598             */
599            private CodeSigner[] convertCertArrayToSignerArray(
600                    java.security.cert.Certificate[] certs) {
601
602                if (certs == null) {
603                    return null;
604                }
605
606                try {
607                    // Initialize certificate factory 
608                    if (factory == null) {
609                        factory = CertificateFactory.getInstance("X.509");
610                    }
611
612                    // Iterate through all the certificates
613                    int i = 0;
614                    List<CodeSigner> signers = new ArrayList<CodeSigner>();
615                    while (i < certs.length) {
616                        List<java.security.cert.Certificate> certChain = new ArrayList<java.security.cert.Certificate>();
617                        certChain.add(certs[i++]); // first cert is an end-entity cert
618                        int j = i;
619
620                        // Extract chain of certificates 
621                        // (loop while certs are not end-entity certs)
622                        while (j < certs.length
623                                && certs[j] instanceof  X509Certificate
624                                && ((X509Certificate) certs[j])
625                                        .getBasicConstraints() != -1) {
626                            certChain.add(certs[j]);
627                            j++;
628                        }
629                        i = j;
630                        CertPath certPath = factory.generateCertPath(certChain);
631                        signers.add(new CodeSigner(certPath, null));
632                    }
633
634                    if (signers.isEmpty()) {
635                        return null;
636                    } else {
637                        return signers.toArray(new CodeSigner[signers.size()]);
638                    }
639
640                } catch (CertificateException e) {
641                    return null; //TODO - may be better to throw an ex. here
642                }
643            }
644        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.