1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <fcntl.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include "jli_util.h" 33 34 #include <zlib.h> 35 #include "manifest_info.h" 36 37 static char *manifest; 38 39 static const char *manifest_name = "META-INF/MANIFEST.MF"; 40 41 /* 42 * Inflate the manifest file (or any file for that matter). 43 * 44 * fd: File descriptor of the jar file. 45 * entry: Contains the information necessary to perform the inflation 46 * (the compressed and uncompressed sizes and the offset in 47 * the file where the compressed data is located). 48 * size_out: Returns the size of the inflated file. 49 * 50 * Upon success, it returns a pointer to a NUL-terminated malloc'd buffer 51 * containing the inflated manifest file. When the caller is done with it, 52 * this buffer should be released by a call to free(). Upon failure, 53 * returns NULL. 54 */ 55 static char * 56 inflate_file(int fd, zentry *entry, int *size_out) 57 { 58 char *in; 59 char *out; 60 z_stream zs; 61 62 if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 ) 63 return (NULL); 64 if (JLI_Lseek(fd, entry->offset, SEEK_SET) < (jlong)0) 65 return (NULL); 66 if ((in = malloc(entry->csize + 1)) == NULL) 67 return (NULL); 68 if ((size_t)(read(fd, in, (unsigned int)entry->csize)) != entry->csize) { 69 free(in); 70 return (NULL); 71 } 72 if (entry->how == STORED) { 73 *(char *)((size_t)in + entry->csize) = '\0'; 74 if (size_out) { 75 *size_out = (int)entry->csize; 76 } 77 return (in); 78 } else if (entry->how == DEFLATED) { 79 zs.zalloc = (alloc_func)Z_NULL; 80 zs.zfree = (free_func)Z_NULL; 81 zs.opaque = (voidpf)Z_NULL; 82 zs.next_in = (Byte*)in; 83 zs.avail_in = (uInt)entry->csize; 84 if (inflateInit2(&zs, -MAX_WBITS) < 0) { 85 free(in); 86 return (NULL); 87 } 88 if ((out = malloc(entry->isize + 1)) == NULL) { 89 free(in); 90 return (NULL); 91 } 92 zs.next_out = (Byte*)out; 93 zs.avail_out = (uInt)entry->isize; 94 if (inflate(&zs, Z_PARTIAL_FLUSH) < 0) { 95 free(in); 96 free(out); 97 return (NULL); 98 } 99 *(char *)((size_t)out + entry->isize) = '\0'; 100 free(in); 101 if (inflateEnd(&zs) < 0) { 102 free(out); 103 return (NULL); 104 } 105 if (size_out) { 106 *size_out = (int)entry->isize; 107 } 108 return (out); 109 } 110 free(in); 111 return (NULL); 112 } 113 114 static jboolean zip64_present = JNI_FALSE; 115 116 /* 117 * Checks to see if we have ZIP64 archive, and save 118 * the check for later use 119 */ 120 static int 121 haveZIP64(Byte *p) { 122 jlong cenlen, cenoff, centot; 123 cenlen = ENDSIZ(p); 124 cenoff = ENDOFF(p); 125 centot = ENDTOT(p); 126 zip64_present = (cenlen == ZIP64_MAGICVAL || 127 cenoff == ZIP64_MAGICVAL || 128 centot == ZIP64_MAGICCOUNT); 129 return zip64_present; 130 } 131 132 static jlong 133 find_end64(int fd, Byte *ep, jlong pos) 134 { 135 jlong end64pos; 136 jlong bytes; 137 if ((end64pos = JLI_Lseek(fd, pos - ZIP64_LOCHDR, SEEK_SET)) < (jlong)0) 138 return -1; 139 if ((bytes = read(fd, ep, ZIP64_LOCHDR)) < 0) 140 return -1; 141 if (GETSIG(ep) == ZIP64_LOCSIG) 142 return end64pos; 143 return -1; 144 } 145 146 /* 147 * A very little used routine to handle the case that zip file has 148 * a comment at the end. Believe it or not, the only way to find the 149 * END record is to walk backwards, byte by bloody byte looking for 150 * the END record signature. 151 * 152 * fd: File descriptor of the jar file. 153 * eb: Pointer to a buffer to receive a copy of the END header. 154 * 155 * Returns the offset of the END record in the file on success, 156 * -1 on failure. 157 */ 158 static jlong 159 find_end(int fd, Byte *eb) 160 { 161 jlong len; 162 jlong pos; 163 jlong flen; 164 int bytes; 165 Byte *cp; 166 Byte *endpos; 167 Byte *buffer; 168 169 /* 170 * 99.44% (or more) of the time, there will be no comment at the 171 * end of the zip file. Try reading just enough to read the END 172 * record from the end of the file, at this time we should also 173 * check to see if we have a ZIP64 archive. 174 */ 175 if ((pos = JLI_Lseek(fd, -ENDHDR, SEEK_END)) < (jlong)0) 176 return (-1); 177 if ((bytes = read(fd, eb, ENDHDR)) < 0) 178 return (-1); 179 if (GETSIG(eb) == ENDSIG) { 180 return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; 181 } 182 183 /* 184 * Shucky-Darn,... There is a comment at the end of the zip file. 185 * 186 * Allocate and fill a buffer with enough of the zip file 187 * to meet the specification for a maximal comment length. 188 */ 189 if ((flen = JLI_Lseek(fd, 0, SEEK_END)) < (jlong)0) 190 return (-1); 191 len = (flen < END_MAXLEN) ? flen : END_MAXLEN; 192 if (JLI_Lseek(fd, -len, SEEK_END) < (jlong)0) 193 return (-1); 194 if ((buffer = malloc(END_MAXLEN)) == NULL) 195 return (-1); 196 if ((bytes = read(fd, buffer, len)) < 0) { 197 free(buffer); 198 return (-1); 199 } 200 201 /* 202 * Search backwards from the end of file stopping when the END header 203 * signature is found. (The first condition of the "if" is just a 204 * fast fail, because the GETSIG macro isn't always cheap. The 205 * final condition protects against false positives.) 206 */ 207 endpos = &buffer[bytes]; 208 for (cp = &buffer[bytes - ENDHDR]; cp >= &buffer[0]; cp--) 209 if ((*cp == (ENDSIG & 0xFF)) && (GETSIG(cp) == ENDSIG) && 210 (cp + ENDHDR + ENDCOM(cp) == endpos)) { 211 (void) memcpy(eb, cp, ENDHDR); 212 free(buffer); 213 pos = flen - (endpos - cp); 214 return haveZIP64(eb) ? find_end64(fd, eb, pos) : pos; 215 } 216 free(buffer); 217 return (-1); 218 } 219 220 #define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ) 221 #define MINREAD 1024 222 223 /* 224 * Computes and positions at the start of the CEN header, ie. the central 225 * directory, this will also return the offset if there is a zip file comment 226 * at the end of the archive, for most cases this would be 0. 227 */ 228 static jlong 229 compute_cen(int fd, Byte *bp) 230 { 231 int bytes; 232 Byte *p; 233 jlong base_offset; 234 jlong offset; 235 char buffer[MINREAD]; 236 p = (Byte*) buffer; 237 /* 238 * Read the END Header, which is the starting point for ZIP files. 239 * (Clearly designed to make writing a zip file easier than reading 240 * one. Now isn't that precious...) 241 */ 242 if ((base_offset = find_end(fd, bp)) == -1) { 243 return (-1); 244 } 245 p = bp; 246 /* 247 * There is a historical, but undocumented, ability to allow for 248 * additional "stuff" to be prepended to the zip/jar file. It seems 249 * that this has been used to prepend an actual java launcher 250 * executable to the jar on Windows. Although this is just another 251 * form of statically linking a small piece of the JVM to the 252 * application, we choose to continue to support it. Note that no 253 * guarantees have been made (or should be made) to the customer that 254 * this will continue to work. 255 * 256 * Therefore, calculate the base offset of the zip file (within the 257 * expanded file) by assuming that the central directory is followed 258 * immediately by the end record. 259 */ 260 if (zip64_present) { 261 if ((offset = ZIP64_LOCOFF(p)) < (jlong)0) { 262 return -1; 263 } 264 if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong) 0) { 265 return (-1); 266 } 267 if ((bytes = read(fd, buffer, MINREAD)) < 0) { 268 return (-1); 269 } 270 if (GETSIG(buffer) != ZIP64_ENDSIG) { 271 return -1; 272 } 273 if ((offset = ZIP64_ENDOFF(buffer)) < (jlong)0) { 274 return -1; 275 } 276 if (JLI_Lseek(fd, offset, SEEK_SET) < (jlong)0) { 277 return (-1); 278 } 279 p = (Byte*) buffer; 280 base_offset = base_offset - ZIP64_ENDSIZ(p) - ZIP64_ENDOFF(p) - ZIP64_ENDHDR; 281 } else { 282 base_offset = base_offset - ENDSIZ(p) - ENDOFF(p); 283 /* 284 * The END Header indicates the start of the Central Directory 285 * Headers. Remember that the desired Central Directory Header (CEN) 286 * will almost always be the second one and the first one is a small 287 * directory entry ("META-INF/"). Keep the code optimized for 288 * that case. 289 * 290 * Seek to the beginning of the Central Directory. 291 */ 292 if (JLI_Lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (jlong) 0) { 293 return (-1); 294 } 295 } 296 return base_offset; 297 } 298 299 /* 300 * Locate the manifest file with the zip/jar file. 301 * 302 * fd: File descriptor of the jar file. 303 * entry: To be populated with the information necessary to perform 304 * the inflation (the compressed and uncompressed sizes and 305 * the offset in the file where the compressed data is located). 306 * 307 * Returns zero upon success. Returns a negative value upon failure. 308 * 309 * The buffer for reading the Central Directory if the zip/jar file needs 310 * to be large enough to accommodate the largest possible single record 311 * and the signature of the next record which is: 312 * 313 * 3*2**16 + CENHDR + SIGSIZ 314 * 315 * Each of the three variable sized fields (name, comment and extension) 316 * has a maximum possible size of 64k. 317 * 318 * Typically, only a small bit of this buffer is used with bytes shuffled 319 * down to the beginning of the buffer. It is one thing to allocate such 320 * a large buffer and another thing to actually start faulting it in. 321 * 322 * In most cases, all that needs to be read are the first two entries in 323 * a typical jar file (META-INF and META-INF/MANIFEST.MF). Keep this factoid 324 * in mind when optimizing this code. 325 */ 326 static int 327 find_file(int fd, zentry *entry, const char *file_name) 328 { 329 int bytes; 330 int res; 331 int entry_size; 332 int read_size; 333 jlong base_offset; 334 Byte *p; 335 Byte *bp; 336 Byte *buffer; 337 Byte locbuf[LOCHDR]; 338 339 if ((buffer = (Byte*)malloc(BUFSIZE)) == NULL) { 340 return(-1); 341 } 342 343 bp = buffer; 344 base_offset = compute_cen(fd, bp); 345 if (base_offset == -1) { 346 free(buffer); 347 return -1; 348 } 349 350 if ((bytes = read(fd, bp, MINREAD)) < 0) { 351 free(buffer); 352 return (-1); 353 } 354 p = bp; 355 /* 356 * Loop through the Central Directory Headers. Note that a valid zip/jar 357 * must have an ENDHDR (with ENDSIG) after the Central Directory. 358 */ 359 while (GETSIG(p) == CENSIG) { 360 361 /* 362 * If a complete header isn't in the buffer, shift the contents 363 * of the buffer down and refill the buffer. Note that the check 364 * for "bytes < CENHDR" must be made before the test for the entire 365 * size of the header, because if bytes is less than CENHDR, the 366 * actual size of the header can't be determined. The addition of 367 * SIGSIZ guarantees that the next signature is also in the buffer 368 * for proper loop termination. 369 */ 370 if (bytes < CENHDR) { 371 p = memmove(bp, p, bytes); 372 if ((res = read(fd, bp + bytes, MINREAD)) <= 0) { 373 free(buffer); 374 return (-1); 375 } 376 bytes += res; 377 } 378 entry_size = CENHDR + CENNAM(p) + CENEXT(p) + CENCOM(p); 379 if (bytes < entry_size + SIGSIZ) { 380 if (p != bp) 381 p = memmove(bp, p, bytes); 382 read_size = entry_size - bytes + SIGSIZ; 383 read_size = (read_size < MINREAD) ? MINREAD : read_size; 384 if ((res = read(fd, bp + bytes, read_size)) <= 0) { 385 free(buffer); 386 return (-1); 387 } 388 bytes += res; 389 } 390 391 /* 392 * Check if the name is the droid we are looking for; the jar file 393 * manifest. If so, build the entry record from the data found in 394 * the header located and return success. 395 */ 396 if ((size_t)CENNAM(p) == JLI_StrLen(file_name) && 397 memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) { 398 if (JLI_Lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (jlong)0) { 399 free(buffer); 400 return (-1); 401 } 402 if (read(fd, locbuf, LOCHDR) < 0) { 403 free(buffer); 404 return (-1); 405 } 406 if (GETSIG(locbuf) != LOCSIG) { 407 free(buffer); 408 return (-1); 409 } 410 entry->isize = CENLEN(p); 411 entry->csize = CENSIZ(p); 412 entry->offset = base_offset + CENOFF(p) + LOCHDR + 413 LOCNAM(locbuf) + LOCEXT(locbuf); 414 entry->how = CENHOW(p); 415 free(buffer); 416 return (0); 417 } 418 419 /* 420 * Point to the next entry and decrement the count of valid remaining 421 * bytes. 422 */ 423 bytes -= entry_size; 424 p += entry_size; 425 } 426 free(buffer); 427 return (-1); /* Fell off the end the loop without a Manifest */ 428 } 429 430 /* 431 * Parse a Manifest file header entry into a distinct "name" and "value". 432 * Continuation lines are joined into a single "value". The documented 433 * syntax for a header entry is: 434 * 435 * header: name ":" value 436 * 437 * name: alphanum *headerchar 438 * 439 * value: SPACE *otherchar newline *continuation 440 * 441 * continuation: SPACE *otherchar newline 442 * 443 * newline: CR LF | LF | CR (not followed by LF) 444 * 445 * alphanum: {"A"-"Z"} | {"a"-"z"} | {"0"-"9"} 446 * 447 * headerchar: alphanum | "-" | "_" 448 * 449 * otherchar: any UTF-8 character except NUL, CR and LF 450 * 451 * Note that a manifest file may be composed of multiple sections, 452 * each of which may contain multiple headers. 453 * 454 * section: *header +newline 455 * 456 * nonempty-section: +header +newline 457 * 458 * (Note that the point of "nonempty-section" is unclear, because it isn't 459 * referenced elsewhere in the full specification for the Manifest file.) 460 * 461 * Arguments: 462 * lp pointer to a character pointer which points to the start 463 * of a valid header. 464 * name pointer to a character pointer which will be set to point 465 * to the name portion of the header (nul terminated). 466 * value pointer to a character pointer which will be set to point 467 * to the value portion of the header (nul terminated). 468 * 469 * Returns: 470 * 1 Successful parsing of an NV pair. lp is updated to point to the 471 * next character after the terminating newline in the string 472 * representing the Manifest file. name and value are updated to 473 * point to the strings parsed. 474 * 0 A valid end of section indicator was encountered. lp, name, and 475 * value are not modified. 476 * -1 lp does not point to a valid header. Upon return, the values of 477 * lp, name, and value are undefined. 478 */ 479 static int 480 parse_nv_pair(char **lp, char **name, char **value) 481 { 482 char *nl; 483 char *cp; 484 485 /* 486 * End of the section - return 0. The end of section condition is 487 * indicated by either encountering a blank line or the end of the 488 * Manifest "string" (EOF). 489 */ 490 if (**lp == '\0' || **lp == '\n' || **lp == '\r') 491 return (0); 492 493 /* 494 * Getting to here, indicates that *lp points to an "otherchar". 495 * Turn the "header" into a string on its own. 496 */ 497 nl = JLI_StrPBrk(*lp, "\n\r"); 498 if (nl == NULL) { 499 nl = JLI_StrChr(*lp, (int)'\0'); 500 } else { 501 cp = nl; /* For merging continuation lines */ 502 if (*nl == '\r' && *(nl+1) == '\n') 503 *nl++ = '\0'; 504 *nl++ = '\0'; 505 506 /* 507 * Process any "continuation" line(s), by making them part of the 508 * "header" line. Yes, I know that we are "undoing" the NULs we 509 * just placed here, but continuation lines are the fairly rare 510 * case, so we shouldn't unnecessarily complicate the code above. 511 * 512 * Note that an entire continuation line is processed each iteration 513 * through the outer while loop. 514 */ 515 while (*nl == ' ') { 516 nl++; /* First character to be moved */ 517 while (*nl != '\n' && *nl != '\r' && *nl != '\0') 518 *cp++ = *nl++; /* Shift string */ 519 if (*nl == '\0') 520 return (-1); /* Error: newline required */ 521 *cp = '\0'; 522 if (*nl == '\r' && *(nl+1) == '\n') 523 *nl++ = '\0'; 524 *nl++ = '\0'; 525 } 526 } 527 528 /* 529 * Separate the name from the value; 530 */ 531 cp = JLI_StrChr(*lp, (int)':'); 532 if (cp == NULL) 533 return (-1); 534 *cp++ = '\0'; /* The colon terminates the name */ 535 if (*cp != ' ') 536 return (-1); 537 *cp++ = '\0'; /* Eat the required space */ 538 *name = *lp; 539 *value = cp; 540 *lp = nl; 541 return (1); 542 } 543 544 /* 545 * Read the manifest from the specified jar file and fill in the manifest_info 546 * structure with the information found within. 547 * 548 * Error returns are as follows: 549 * 0 Success 550 * -1 Unable to open jarfile 551 * -2 Error accessing the manifest from within the jarfile (most likely 552 * a manifest is not present, or this isn't a valid zip/jar file). 553 */ 554 int 555 JLI_ParseManifest(char *jarfile, manifest_info *info) 556 { 557 int fd; 558 zentry entry; 559 char *lp; 560 char *name; 561 char *value; 562 int rc; 563 char *splashscreen_name = NULL; 564 565 if ((fd = open(jarfile, O_RDONLY 566 #ifdef O_LARGEFILE 567 | O_LARGEFILE /* large file mode */ 568 #endif 569 #ifdef O_BINARY 570 | O_BINARY /* use binary mode on windows */ 571 #endif 572 )) == -1) { 573 return (-1); 574 } 575 info->manifest_version = NULL; 576 info->main_class = NULL; 577 info->jre_version = NULL; 578 info->jre_restrict_search = 0; 579 info->splashscreen_image_file_name = NULL; 580 if (rc = find_file(fd, &entry, manifest_name) != 0) { 581 close(fd); 582 return (-2); 583 } 584 manifest = inflate_file(fd, &entry, NULL); 585 if (manifest == NULL) { 586 close(fd); 587 return (-2); 588 } 589 lp = manifest; 590 while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) { 591 if (JLI_StrCaseCmp(name, "Manifest-Version") == 0) 592 info->manifest_version = value; 593 else if (JLI_StrCaseCmp(name, "Main-Class") == 0) 594 info->main_class = value; 595 else if (JLI_StrCaseCmp(name, "JRE-Version") == 0) 596 info->jre_version = value; 597 else if (JLI_StrCaseCmp(name, "JRE-Restrict-Search") == 0) { 598 if (JLI_StrCaseCmp(value, "true") == 0) 599 info->jre_restrict_search = 1; 600 } else if (JLI_StrCaseCmp(name, "Splashscreen-Image") == 0) { 601 info->splashscreen_image_file_name = value; 602 } 603 } 604 close(fd); 605 if (rc == 0) 606 return (0); 607 else 608 return (-2); 609 } 610 611 /* 612 * Opens the jar file and unpacks the specified file from its contents. 613 * Returns NULL on failure. 614 */ 615 void * 616 JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { 617 int fd; 618 zentry entry; 619 void *data = NULL; 620 621 if ((fd = open(jarfile, O_RDONLY 622 #ifdef O_LARGEFILE 623 | O_LARGEFILE /* large file mode */ 624 #endif 625 #ifdef O_BINARY 626 | O_BINARY /* use binary mode on windows */ 627 #endif 628 )) == -1) { 629 return NULL; 630 } 631 if (find_file(fd, &entry, filename) == 0) { 632 data = inflate_file(fd, &entry, size); 633 } 634 close(fd); 635 return (data); 636 } 637 638 /* 639 * Specialized "free" function. 640 */ 641 void 642 JLI_FreeManifest() 643 { 644 if (manifest) 645 free(manifest); 646 } 647 648 /* 649 * Iterate over the manifest of the specified jar file and invoke the provided 650 * closure function for each attribute encountered. 651 * 652 * Error returns are as follows: 653 * 0 Success 654 * -1 Unable to open jarfile 655 * -2 Error accessing the manifest from within the jarfile (most likely 656 * this means a manifest is not present, or it isn't a valid zip/jar file). 657 */ 658 int 659 JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) 660 { 661 int fd; 662 zentry entry; 663 char *mp; /* manifest pointer */ 664 char *lp; /* pointer into manifest, updated during iteration */ 665 char *name; 666 char *value; 667 int rc; 668 669 if ((fd = open(jarfile, O_RDONLY 670 #ifdef O_LARGEFILE 671 | O_LARGEFILE /* large file mode */ 672 #endif 673 #ifdef O_BINARY 674 | O_BINARY /* use binary mode on windows */ 675 #endif 676 )) == -1) { 677 return (-1); 678 } 679 680 if (rc = find_file(fd, &entry, manifest_name) != 0) { 681 close(fd); 682 return (-2); 683 } 684 685 mp = inflate_file(fd, &entry, NULL); 686 if (mp == NULL) { 687 close(fd); 688 return (-2); 689 } 690 691 lp = mp; 692 while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) { 693 (*ac)(name, value, user_data); 694 } 695 free(mp); 696 close(fd); 697 return (rc == 0) ? 0 : -2; 698 }