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

Java Source Code / Java Documentation
1. JDK Core
2. JDK Modules
3. JDK Modules com.sun
4. JDK Modules com.sun.java
5. JDK Modules Platform
6. JDK Modules sun
7. Open Source Build
8. Open Source Graphic Library
9. Open Source IDE Eclipse
10. Open Source J2EE
11. Open Source JDBC Driver
12. Open Source Library
13. Open Source Library Database
14. Open Source Net
15. Open Source Script
16. Science
17. Security
18. Sevlet Container
19. SUN GlassFish
20. Swing Library
21. Web Services apache cxf 2.0.1
22. Web Services AXIS2
23. XML
Microsoft Office Word 2007 Tutorial
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java Source Code / Java Documentation » 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:        }
w__w_w_.___j_a_v___a__2__s__._c___o_m_ | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.