diff -urN xar/include/xar.h.in xar.hash/include/xar.h.in --- xar/include/xar.h.in 2006-03-19 20:57:56.000000000 -0800 +++ xar.hash/include/xar.h.in 2006-03-19 20:58:35.000000000 -0800 @@ -38,6 +38,7 @@ #include #include +#include struct xar_header { uint32_t magic; @@ -71,7 +72,8 @@ #define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */ #define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */ -#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ +#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ +#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */ #define XAR_OPT_VAL_NONE "none" #define XAR_OPT_VAL_SHA1 "sha1" #define XAR_OPT_VAL_MD5 "md5" diff -urN xar/lib/Makefile.inc.in xar.hash/lib/Makefile.inc.in --- xar/lib/Makefile.inc.in 2006-03-19 20:57:56.000000000 -0800 +++ xar.hash/lib/Makefile.inc.in 2006-03-19 20:58:35.000000000 -0800 @@ -16,7 +16,7 @@ # Sources. LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c err.c -LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c md5.c stat.c +LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c hash.c stat.c LIBXAR_SRCS += subdoc.c util.c zxar.c script.c macho.c LIBXAR_SRCS := $(patsubst %, @srcroot@lib/%, $(LIBXAR_SRCS)) diff -urN xar/lib/hash.c xar.hash/lib/hash.c --- xar/lib/hash.c 1969-12-31 16:00:00.000000000 -0800 +++ xar.hash/lib/hash.c 2006-03-19 20:58:51.000000000 -0800 @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" + + +struct _hash_context{ + EVP_MD_CTX src_ctx; + EVP_MD_CTX dst_ctx; + uint8_t src; + uint8_t dst; +}; + +#define CONTEXT(x) ((struct _hash_context *)(*x)) + +static char* xar_format_hash(const unsigned char* m,unsigned int len); + +int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + const char *opt; + char *tmpstr; + const EVP_MD *md; + + if(!context) + return 0; + + asprintf(&tmpstr, "%s/extracted-checksum", attr); + opt = xar_attr_get(f, tmpstr, "style"); + free(tmpstr); + + if( !opt ) + opt = xar_opt_get(x, XAR_OPT_FILECKSUM); + + if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) + return 0; + + if(!CONTEXT(context)){ + *context = calloc(1,sizeof(struct _hash_context)); + OpenSSL_add_all_digests(); + } + + if( !CONTEXT(context)->src ){ + md = EVP_get_digestbyname(opt); + if( md == NULL ) return -1; + EVP_DigestInit(&(CONTEXT(context)->src_ctx), md); + CONTEXT(context)->src = 1; + } + + if( *inlen == 0 ) + return 0; + + EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen); + return 0; +} + +int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) { + const char *opt; + const EVP_MD *md; + char *tmpstr; + + if(!context) + return 0; + + asprintf(&tmpstr, "%s/archived-checksum", attr); + opt = xar_attr_get(f, tmpstr, "style"); + free(tmpstr); + + if( !opt ) + opt = xar_opt_get(x, XAR_OPT_FILECKSUM); + + if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) + return 0; + + if(!CONTEXT(context)){ + *context = calloc(1,sizeof(struct _hash_context)); + OpenSSL_add_all_digests(); + } + + if ( !CONTEXT(context)->dst ){ + md = EVP_get_digestbyname(opt); + if( md == NULL ) return -1; + EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md); + CONTEXT(context)->dst = 1; + } + + if( inlen == 0 ) + return 0; + + EVP_DigestUpdate(&(CONTEXT(context)->dst_ctx), in, inlen); + return 0; +} + +int32_t xar_hash_done(xar_t x, xar_file_t f, const char *attr, void **context) { + unsigned char hashstr[EVP_MAX_MD_SIZE]; + char *str, *tmpstr; + unsigned int len; + + if(!CONTEXT(context)) + return 0; + + if( CONTEXT(context)->src ){ + EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx; + const EVP_MD *md = EVP_MD_CTX_md(ctx); + const char *type = EVP_MD_name(md); + + memset(hashstr, 0, sizeof(hashstr)); + EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len); + str = xar_format_hash(hashstr,len); + asprintf(&tmpstr, "%s/extracted-checksum", attr); + if( f ) { + xar_prop_set(f, tmpstr, str); + xar_attr_set(f, tmpstr, "style", type); + } + free(tmpstr); + free(str); + } + + if( CONTEXT(context)->dst ){ + EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx; + const EVP_MD *md = EVP_MD_CTX_md(ctx); + const char *type = EVP_MD_name(md); + + memset(hashstr, 0, sizeof(hashstr)); + EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len); + str = xar_format_hash(hashstr,len); + asprintf(&tmpstr, "%s/archived-checksum", attr); + if( f ) { + xar_prop_set(f, tmpstr, str); + xar_attr_set(f, tmpstr, "style", type); + } + free(tmpstr); + free(str); + } + + if(*context){ + free(*context); + *context = NULL; + } + + return 0; +} + +static char* xar_format_hash(const unsigned char* m,unsigned int len) { + char* result = malloc((2*len)+1); + char hexValue[3]; + unsigned int itr = 0; + + result[0] = '\0'; + + for(itr = 0;itr < len;itr++){ + sprintf(hexValue,"%02x",m[itr]); + strncat(result,hexValue,2); + } + + return result; +} + +int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *attr, void **context) { + const char *uncomp, *uncompstyle; + unsigned char hashstr[EVP_MAX_MD_SIZE]; + unsigned int len; + char *tmpstr; + const EVP_MD *md; + + if(!CONTEXT(context)) + return 0; + + if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){ + return 0; + } + + asprintf(&tmpstr, "%s/extracted-checksum", attr); + xar_prop_get(f, tmpstr, &uncomp); + uncompstyle = xar_attr_get(f, tmpstr, "style"); + free(tmpstr); + + md = EVP_get_digestbyname(uncompstyle); + + if( uncomp && uncompstyle && md && CONTEXT(context)->dst ) { + char *str; + memset(hashstr, 0, sizeof(hashstr)); + EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len); + str = xar_format_hash(hashstr,len); + if(strcmp(uncomp, str) != 0) { + xar_err_new(x); + xar_err_set_file(x, f); + asprintf(&tmpstr, "extracted-checksum %s's do not match",uncompstyle); + xar_err_set_string(x, tmpstr); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + free(str); + } + + if( CONTEXT(context)->src ) + EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len); + + if(*context){ + free(*context); + *context = NULL; + } + + return 0; +} diff -urN xar/lib/hash.h xar.hash/lib/hash.h --- xar/lib/hash.h 1969-12-31 16:00:00.000000000 -0800 +++ xar.hash/lib/hash.h 2006-03-19 20:58:35.000000000 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + +#ifndef _XAR_HASH_H_ +#define _XAR_HASH_H_ + +int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context); +int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); +int32_t xar_hash_done(xar_t x, xar_file_t f, const char *, void **context); +int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *, void **context); + +#endif /* _XAR_HASH_H_ */ diff -urN xar/lib/io.c xar.hash/lib/io.c --- xar/lib/io.c 2006-03-19 20:58:13.000000000 -0800 +++ xar.hash/lib/io.c 2006-03-19 20:58:35.000000000 -0800 @@ -54,7 +54,7 @@ #include "io.h" #include "zxar.h" #include "bzxar.h" -#include "md5.h" +#include "hash.h" #include "script.h" #include "macho.h" @@ -68,11 +68,11 @@ struct datamod xar_datamods[] = { { (fromheap_in)NULL, - xar_md5_compressed, - xar_md5out_done, - xar_md5_uncompressed, - xar_md5_compressed, - xar_md5_done + xar_hash_compressed, + xar_hash_out_done, + xar_hash_uncompressed, + xar_hash_compressed, + xar_hash_done }, { (fromheap_in)NULL, (fromheap_out)NULL, diff -urN xar/lib/md5.c xar.hash/lib/md5.c --- xar/lib/md5.c 2006-03-19 20:58:13.000000000 -0800 +++ xar.hash/lib/md5.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,179 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "config.h" -#ifndef HAVE_ASPRINTF -#include "asprintf.h" -#endif -#include "xar.h" - -struct _md5_context{ - EVP_MD_CTX src_ctx; - EVP_MD_CTX dst_ctx; - uint8_t src; - uint8_t dst; -}; - -#define CONTEXT(x) ((struct _md5_context *)(*x)) - -static char* xar_format_md5(const unsigned char* m); - -int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { - const EVP_MD *md; - - if(!context) - return 0; - - if(!CONTEXT(context)){ - *context = calloc(1,sizeof(struct _md5_context)); - OpenSSL_add_all_digests(); - } - - if( !CONTEXT(context)->src ){ - md = EVP_get_digestbyname("md5"); - if( md == NULL ) return -1; - EVP_DigestInit(&(CONTEXT(context)->src_ctx), md); - CONTEXT(context)->src = 1; - } - - if( *inlen == 0 ) - return 0; - - EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen); - return 0; -} - -int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) { - const EVP_MD *md; - - if(!context) - return 0; - - if(!CONTEXT(context)){ - *context = calloc(1,sizeof(struct _md5_context)); - OpenSSL_add_all_digests(); - } - - if( !CONTEXT(context)->dst ){ - md = EVP_get_digestbyname("md5"); - if( md == NULL ) return -1; - EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md); - CONTEXT(context)->dst = 1; - } - - if( inlen == 0 ) - return 0; - - EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), in, inlen); - return 0; -} - -int32_t xar_md5_done(xar_t x, xar_file_t f, const char *attr, void **context) { - unsigned char md5str[EVP_MAX_MD_SIZE]; - char *str, *tmpstr; - unsigned int len; - - if(!CONTEXT(context)) - return 0; - - if( CONTEXT(context)->src ){ - EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx; - const EVP_MD *md = EVP_MD_CTX_md(ctx); - - memset(md5str, 0, sizeof(md5str)); - EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); - str = xar_format_md5(md5str); - asprintf(&tmpstr, "%s/extracted-checksum", attr); - if( f ) { - xar_prop_set(f, tmpstr, str); - xar_attr_set(f, tmpstr, "style", "md5"); - } - free(tmpstr); - free(str); - } - - if( CONTEXT(context)->dst ){ - EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx; - const EVP_MD *md = EVP_MD_CTX_md(ctx); - - memset(md5str, 0, sizeof(md5str)); - EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); - str = xar_format_md5(md5str); - asprintf(&tmpstr, "%s/archived-checksum", attr); - if( f ) { - xar_prop_set(f, tmpstr, str); - xar_attr_set(f, tmpstr, "style", "md5"); - } - free(tmpstr); - free(str); - } - - if(*context){ - free(*context); - *context = NULL; - } - - return 0; -} - -static char* xar_format_md5(const unsigned char* m) { - char* result = NULL; - asprintf(&result, - "%02x%02x%02x%02x" - "%02x%02x%02x%02x" - "%02x%02x%02x%02x" - "%02x%02x%02x%02x", - m[0], m[1], m[2], m[3], - m[4], m[5], m[6], m[7], - m[8], m[9], m[10], m[11], - m[12], m[13], m[14], m[15]); - return result; -} - -int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *attr, void **context) { - const char *uncomp, *uncompstyle; - unsigned char md5str[EVP_MAX_MD_SIZE]; - unsigned int len; - char *tmpstr; - - if(!CONTEXT(context)) - return 0; - - if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){ - return 0; - } - - asprintf(&tmpstr, "%s/extracted-checksum", attr); - xar_prop_get(f, tmpstr, &uncomp); - uncompstyle = xar_attr_get(f, tmpstr, "style"); - free(tmpstr); - - if( uncomp && uncompstyle && CONTEXT(context)->dst ) { - char *str; - memset(md5str, 0, sizeof(md5str)); - EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); - str = xar_format_md5(md5str); - if(strcmp(uncomp, str) != 0) { - xar_err_new(x); - xar_err_set_file(x, f); - asprintf(&tmpstr, "extracted-checksum MD5's do not match"); - xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); - } - free(str); - } - - if( CONTEXT(context)->src ) - EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); - - if(*context){ - free(*context); - *context = NULL; - } - - return 0; - -} diff -urN xar/lib/md5.h xar.hash/lib/md5.h --- xar/lib/md5.h 2006-03-19 20:58:13.000000000 -0800 +++ xar.hash/lib/md5.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2005 Rob Braun - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Rob Braun nor the names of his contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * 03-Apr-2005 - * DRI: Rob Braun - */ - -#ifndef _XAR_MD5_H_ -#define _XAR_MD5_H_ - -int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context); -int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); -int32_t xar_md5_done(xar_t x, xar_file_t f, const char *, void **context); -int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *, void **context); - -#endif /* _XAR_MD5_H_ */