void write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size) { struct zip_lfh lfh = { 0x04034b50, 0x0a, 0x0, 0x0, zip_info->time, zip_info->date, 0x0, 0x0, 0x0, filelen, 0x0, }; struct zip_cd cd = { 0x02014b50, 0x17, 0x00, 0x0a, 0x00, 0x0000, 0x0, zip_info->time, zip_info->date, 0x0, 0x0, 0x0, filelen, 0x0000, 0x0000, 0x0000, 0x0000, 0x0, zip_info->offset, }; struct zip_cd_ext cd_ext = { 0x1, 0x8, zip_info->offset, }; #ifdef HAVE_LIBCRYPTO struct zip_enc enc = { 0x9901, 0x7, 0x2, 'A','E', 0x1, 0x0, }; unsigned char salt[8], key[34], verify[2], mac[10]; #endif char *filename; int crc=0,len,comp_size=data_size; uLongf destlen=data_size+data_size/500+12; char *compbuffer; compbuffer = malloc(destlen); if (!compbuffer) { fprintf(stderr, "No more memory.\n"); exit (1); } #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { RAND_bytes(salt, sizeof(salt)); PKCS5_PBKDF2_HMAC_SHA1(zip_info->passwd, strlen(zip_info->passwd), salt, sizeof(salt), 1000, sizeof(key), key); verify[0]=key[32]; verify[1]=key[33]; } else { #endif crc=crc32(0, NULL, 0); crc=crc32(crc, (unsigned char *)data, data_size); #ifdef HAVE_LIBCRYPTO } #endif lfh.zipmthd=zip_info->compression_level ? 8:0; #ifdef HAVE_ZLIB if (zip_info->compression_level) { int error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level); if (error == Z_OK) { if (destlen < data_size) { data=compbuffer; comp_size=destlen; } else lfh.zipmthd=0; } else { fprintf(stderr,"compress2 returned %d\n", error); } } #endif lfh.zipcrc=crc; lfh.zipsize=comp_size; lfh.zipuncmp=data_size; #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { enc.compress_method=lfh.zipmthd; lfh.zipmthd=99; lfh.zipxtraln+=sizeof(enc); lfh.zipgenfld|=1; lfh.zipsize+=sizeof(salt)+sizeof(verify)+sizeof(mac); } #endif cd.zipccrc=crc; cd.zipcsiz=lfh.zipsize; cd.zipcunc=data_size; cd.zipcmthd=lfh.zipmthd; if (zip_info->zip64) { cd.zipofst=0xffffffff; cd.zipcxtl+=sizeof(cd_ext); } #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { cd.zipcmthd=99; cd.zipcxtl+=sizeof(enc); cd.zipcflg|=1; } #endif filename=g_alloca(filelen+1); strcpy(filename, name); len=strlen(filename); while (len < filelen) { filename[len++]='_'; } filename[filelen]='\0'; zip_write(zip_info, &lfh, sizeof(lfh)); zip_write(zip_info, filename, filelen); zip_info->offset+=sizeof(lfh)+filelen; #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { unsigned char counter[16], xor[16], *datap=(unsigned char *)data; int size=comp_size; AES_KEY aeskey; zip_write(zip_info, &enc, sizeof(enc)); zip_write(zip_info, salt, sizeof(salt)); zip_write(zip_info, verify, sizeof(verify)); zip_info->offset+=sizeof(enc)+sizeof(salt)+sizeof(verify); AES_set_encrypt_key(key, 128, &aeskey); memset(counter, 0, sizeof(counter)); while (size > 0) { int i,curr_size,idx=0; do { counter[idx]++; } while (!counter[idx++]); AES_encrypt(counter, xor, &aeskey); curr_size=size; if (curr_size > sizeof(xor)) curr_size=sizeof(xor); for (i = 0 ; i < curr_size ; i++) *datap++^=xor[i]; size-=curr_size; } } #endif zip_write(zip_info, data, comp_size); zip_info->offset+=comp_size; #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { unsigned int maclen=sizeof(mac); unsigned char mactmp[maclen*2]; HMAC(EVP_sha1(), key+16, 16, (unsigned char *)data, comp_size, mactmp, &maclen); zip_write(zip_info, mactmp, sizeof(mac)); zip_info->offset+=sizeof(mac); } #endif fwrite(&cd, sizeof(cd), 1, zip_info->dir); fwrite(filename, filelen, 1, zip_info->dir); zip_info->dir_size+=sizeof(cd)+filelen; if (zip_info->zip64) { fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir); zip_info->dir_size+=sizeof(cd_ext); } #ifdef HAVE_LIBCRYPTO if (zip_info->passwd) { fwrite(&enc, sizeof(enc), 1, zip_info->dir); zip_info->dir_size+=sizeof(enc); } #endif free(compbuffer); }
void write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size) { struct zip_lfh lfh = { 0x04034b50, 0x0a, 0x0, 0x0, zip_info->time, zip_info->date, 0x0, 0x0, 0x0, filelen, 0x0, }; struct zip_cd cd = { 0x02014b50, 0x17, 0x00, 0x0a, 0x00, 0x0000, 0x0, zip_info->time, zip_info->date, 0x0, 0x0, 0x0, filelen, 0x0000, 0x0000, 0x0000, 0x0000, 0x0, zip_info->offset, }; struct zip_cd_ext cd_ext = { 0x1, 0x8, zip_info->offset, }; char filename[filelen+1]; int error,crc,len,comp_size=data_size; uLongf destlen=data_size+data_size/500+12; char *compbuffer; compbuffer = malloc(destlen); if (!compbuffer) { fprintf(stderr, "No more memory.\n"); exit (1); } crc=crc32(0, NULL, 0); crc=crc32(crc, (unsigned char *)data, data_size); #ifdef HAVE_ZLIB if (zip_info->compression_level) { error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level); if (error == Z_OK) { if (destlen < data_size) { data=compbuffer; comp_size=destlen; } } else { fprintf(stderr,"compress2 returned %d\n", error); } } #endif lfh.zipcrc=crc; lfh.zipsize=comp_size; lfh.zipuncmp=data_size; lfh.zipmthd=zip_info->compression_level ? 8:0; cd.zipccrc=crc; cd.zipcsiz=comp_size; cd.zipcunc=data_size; cd.zipcmthd=zip_info->compression_level ? 8:0; if (zip_info->zip64) { cd.zipofst=0xffffffff; cd.zipcxtl=sizeof(cd_ext); } strcpy(filename, name); len=strlen(filename); while (len < filelen) { filename[len++]='_'; } filename[filelen]='\0'; fwrite(&lfh, sizeof(lfh), 1, zip_info->res); fwrite(filename, filelen, 1, zip_info->res); fwrite(data, comp_size, 1, zip_info->res); zip_info->offset+=sizeof(lfh)+filelen+comp_size; fwrite(&cd, sizeof(cd), 1, zip_info->dir); fwrite(filename, filelen, 1, zip_info->dir); zip_info->dir_size+=sizeof(cd)+filelen; if (zip_info->zip64) { fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir); zip_info->dir_size+=sizeof(cd_ext); } free(compbuffer); }