65 /* cache of CodeSigner objects */
66 private ArrayList<CodeSigner[]> signerCache;
67
68 /* Are we parsing a block? */
69 private boolean parsingBlockOrSF = false;
70
71 /* Are we done parsing META-INF entries? */
72 private boolean parsingMeta = true;
73
74 /* Are there are files to verify? */
75 private boolean anyToVerify = true;
76
77 /* The output stream to use when keeping track of files we are interested
78 in */
79 private ByteArrayOutputStream baos;
80
81 /** The ManifestDigester object */
82 private volatile ManifestDigester manDig;
83
84 /** the bytes for the manDig object */
85 byte manifestRawBytes[] = null;
86
87 /** controls eager signature validation */
88 boolean eagerValidation;
89
90 /** makes code source singleton instances unique to us */
91 private Object csdomain = new Object();
92
93 /** collect -DIGEST-MANIFEST values for blacklist */
94 private List<Object> manifestDigests;
95
96 public JarVerifier(byte rawBytes[]) {
97 manifestRawBytes = rawBytes;
98 sigFileSigners = new Hashtable<>();
99 verifiedSigners = new Hashtable<>();
100 sigFileData = new Hashtable<>(11);
101 pendingBlocks = new ArrayList<>();
102 baos = new ByteArrayOutputStream();
103 manifestDigests = new ArrayList<>();
104 }
105
106 /**
107 * This method scans to see which entry we're parsing and
108 * keeps various state information depending on what type of
109 * file is being parsed.
110 */
111 public void beginEntry(JarEntry je, ManifestEntryVerifier mev)
112 throws IOException
113 {
114 if (je == null)
115 return;
116
240 if (!parsingBlockOrSF) {
241 JarEntry je = mev.getEntry();
242 if ((je != null) && (je.signers == null)) {
243 je.signers = mev.verify(verifiedSigners, sigFileSigners);
244 je.certs = mapSignersToCertArray(je.signers);
245 }
246 } else {
247
248 try {
249 parsingBlockOrSF = false;
250
251 if (debug != null) {
252 debug.println("processEntry: processing block");
253 }
254
255 String uname = mev.getEntry().getName()
256 .toUpperCase(Locale.ENGLISH);
257
258 if (uname.endsWith(".SF")) {
259 String key = uname.substring(0, uname.length()-3);
260 byte bytes[] = baos.toByteArray();
261 // add to sigFileData in case future blocks need it
262 sigFileData.put(key, bytes);
263 // check pending blocks, we can now process
264 // anyone waiting for this .SF file
265 for (SignatureFileVerifier sfv : pendingBlocks) {
266 if (sfv.needSignatureFile(key)) {
267 if (debug != null) {
268 debug.println(
269 "processEntry: processing pending block");
270 }
271
272 sfv.setSignatureFile(bytes);
273 sfv.process(sigFileSigners, manifestDigests);
274 }
275 }
276 return;
277 }
278
279 // now we are parsing a signature block file
280
444 this.numLeft = je.getSize();
445 if (this.numLeft == 0)
446 this.jv.update(-1, this.mev);
447 }
448
449 public int read() throws IOException
450 {
451 ensureOpen();
452 if (numLeft > 0) {
453 int b = is.read();
454 jv.update(b, mev);
455 numLeft--;
456 if (numLeft == 0)
457 jv.update(-1, mev);
458 return b;
459 } else {
460 return -1;
461 }
462 }
463
464 public int read(byte b[], int off, int len) throws IOException {
465 ensureOpen();
466 if ((numLeft > 0) && (numLeft < len)) {
467 len = (int)numLeft;
468 }
469
470 if (numLeft > 0) {
471 int n = is.read(b, off, len);
472 jv.update(n, b, off, len, mev);
473 numLeft -= n;
474 if (numLeft == 0)
475 jv.update(-1, b, off, len, mev);
476 return n;
477 } else {
478 return -1;
479 }
480 }
481
482 public void close()
483 throws IOException
484 {
|
65 /* cache of CodeSigner objects */
66 private ArrayList<CodeSigner[]> signerCache;
67
68 /* Are we parsing a block? */
69 private boolean parsingBlockOrSF = false;
70
71 /* Are we done parsing META-INF entries? */
72 private boolean parsingMeta = true;
73
74 /* Are there are files to verify? */
75 private boolean anyToVerify = true;
76
77 /* The output stream to use when keeping track of files we are interested
78 in */
79 private ByteArrayOutputStream baos;
80
81 /** The ManifestDigester object */
82 private volatile ManifestDigester manDig;
83
84 /** the bytes for the manDig object */
85 byte[] manifestRawBytes = null;
86
87 /** controls eager signature validation */
88 boolean eagerValidation;
89
90 /** makes code source singleton instances unique to us */
91 private Object csdomain = new Object();
92
93 /** collect -DIGEST-MANIFEST values for blacklist */
94 private List<Object> manifestDigests;
95
96 public JarVerifier(byte[] rawBytes) {
97 manifestRawBytes = rawBytes;
98 sigFileSigners = new Hashtable<>();
99 verifiedSigners = new Hashtable<>();
100 sigFileData = new Hashtable<>(11);
101 pendingBlocks = new ArrayList<>();
102 baos = new ByteArrayOutputStream();
103 manifestDigests = new ArrayList<>();
104 }
105
106 /**
107 * This method scans to see which entry we're parsing and
108 * keeps various state information depending on what type of
109 * file is being parsed.
110 */
111 public void beginEntry(JarEntry je, ManifestEntryVerifier mev)
112 throws IOException
113 {
114 if (je == null)
115 return;
116
240 if (!parsingBlockOrSF) {
241 JarEntry je = mev.getEntry();
242 if ((je != null) && (je.signers == null)) {
243 je.signers = mev.verify(verifiedSigners, sigFileSigners);
244 je.certs = mapSignersToCertArray(je.signers);
245 }
246 } else {
247
248 try {
249 parsingBlockOrSF = false;
250
251 if (debug != null) {
252 debug.println("processEntry: processing block");
253 }
254
255 String uname = mev.getEntry().getName()
256 .toUpperCase(Locale.ENGLISH);
257
258 if (uname.endsWith(".SF")) {
259 String key = uname.substring(0, uname.length()-3);
260 byte[] bytes = baos.toByteArray();
261 // add to sigFileData in case future blocks need it
262 sigFileData.put(key, bytes);
263 // check pending blocks, we can now process
264 // anyone waiting for this .SF file
265 for (SignatureFileVerifier sfv : pendingBlocks) {
266 if (sfv.needSignatureFile(key)) {
267 if (debug != null) {
268 debug.println(
269 "processEntry: processing pending block");
270 }
271
272 sfv.setSignatureFile(bytes);
273 sfv.process(sigFileSigners, manifestDigests);
274 }
275 }
276 return;
277 }
278
279 // now we are parsing a signature block file
280
444 this.numLeft = je.getSize();
445 if (this.numLeft == 0)
446 this.jv.update(-1, this.mev);
447 }
448
449 public int read() throws IOException
450 {
451 ensureOpen();
452 if (numLeft > 0) {
453 int b = is.read();
454 jv.update(b, mev);
455 numLeft--;
456 if (numLeft == 0)
457 jv.update(-1, mev);
458 return b;
459 } else {
460 return -1;
461 }
462 }
463
464 public int read(byte[] b, int off, int len) throws IOException {
465 ensureOpen();
466 if ((numLeft > 0) && (numLeft < len)) {
467 len = (int)numLeft;
468 }
469
470 if (numLeft > 0) {
471 int n = is.read(b, off, len);
472 jv.update(n, b, off, len, mev);
473 numLeft -= n;
474 if (numLeft == 0)
475 jv.update(-1, b, off, len, mev);
476 return n;
477 } else {
478 return -1;
479 }
480 }
481
482 public void close()
483 throws IOException
484 {
|