static PyObject *affile_get_seg(affile *self, PyObject *args, PyObject *kwds) { PyObject *retdata; char *buf; size_t buflen=0; char *segname=NULL; static char *kwlist[] = {"segname", NULL}; if(!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &segname)) return NULL; // first get the size if(af_get_seg(self->af, segname, 0, 0, &buflen) != 0) { return PyErr_Format(PyExc_IOError, "error reading libaff segment\n"); } // allocate a string to return data in retdata = PyString_FromStringAndSize(NULL, buflen); buf = PyString_AsString(retdata); if(af_get_seg(self->af, segname, 0, (unsigned char *)buf, &buflen) != 0) { Py_DECREF(retdata); return PyErr_Format(PyExc_IOError, "error reading libaff segment\n"); } return retdata; }
/* * afm_get_seg: * If it is a page segment, satisfy it from the splitraw, * otherwise from the aff file. */ static int afm_get_seg(AFFILE *af,const char *name,uint32_t *arg,unsigned char *data,size_t *datalen) { struct afm_private *ap = AFM_PRIVATE(af); int64_t page_num = af_segname_page_number(name); if(page_num>=0) return af_get_seg(ap->sr,name,arg,data,datalen); return af_get_seg(ap->aff,name,arg,data,datalen); }
void affstats(const char *fname) { AFFILE *af = af_open(fname,O_RDONLY,0); if(!af) af_err(1,"af_open(%s)",fname); printf("%s\t",fname); uint32_t segsize=0; int64_t imagesize=0; int64_t blanksectors=0; int64_t badsectors=0; af_get_segq(af,AF_IMAGESIZE,&imagesize); if(af_get_seg(af,AF_PAGESIZE,&segsize,0,0)){ af_get_seg(af,AF_SEGSIZE_D,&segsize,0,0); // check for oldstype } af_get_segq(af,AF_BADSECTORS,&badsectors); af_get_segq(af,AF_BLANKSECTORS,&blanksectors); print_size(imagesize); printf("\t"); fflush(stdout); int64_t compressed_bytes = 0; int64_t uncompressed_bytes = 0; /* Now read through all of the segments and count the number of * data segments. We know the uncompressed size... */ af_rewind_seg(af); char segname[AF_MAX_NAME_LEN+1]; size_t datalen; while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){ int64_t page_num = af_segname_page_number(segname); if(page_num>=0){ compressed_bytes += datalen; uncompressed_bytes += segsize; } } if(uncompressed_bytes > imagesize) uncompressed_bytes = imagesize; print_size(compressed_bytes); printf("\t"); print_size(uncompressed_bytes); printf(" %" I64d " %" I64d,blanksectors,badsectors); putchar('\n'); }
/* get_seg needs to figure out which of the individual EVF files * has the requested segment and call it. */ static int evd_get_seg(AFFILE *af,const char *name,unsigned long *arg,unsigned char *data, size_t *datalen) { AFFILE *af2 = evd_file_with_seg(af,name); if(af2){ return af_get_seg(af2,name,arg,data,datalen); // use this one } return -1; // not found }
int af_get_page_raw(AFFILE *af,int64_t pagenum,unsigned long *arg, unsigned char *data,size_t *bytes) { char segname[AF_MAX_NAME_LEN]; memset(segname,0,sizeof(segname)); sprintf(segname,AF_PAGE,pagenum); int r = af_get_seg(af,segname,arg,data,bytes); if(r!=0){ /* Couldn't read with AF_PAGE; try AF_SEG_D. * This is legacy for the old AFF files. Perhaps we should delete it. */ sprintf(segname,AF_SEG_D,pagenum); r = af_get_seg(af,segname,arg,data,bytes); } /* Update the counters */ if(r==0 && bytes && *bytes>0) af->pages_read++; // note that we read a page return r; }
/* af_read_sizes: * Get the page sizes if they are set in the file. */ void af_read_sizes(AFFILE *af) { af_get_seg(af,AF_SECTORSIZE,&af->image_sectorsize,0,0); if(af->image_sectorsize==0) af->image_sectorsize = 512; // reasonable default if(af_get_seg(af,AF_PAGESIZE,&af->image_pagesize,0,0)){ af_get_seg(af,AF_SEGSIZE_D,&af->image_pagesize,0,0); // try old name } /* Read the badflag if it is present */ size_t sectorsize = af->image_sectorsize; if(af->badflag==0) af->badflag = (unsigned char *)malloc(sectorsize); if(af_get_seg(af,AF_BADFLAG,0,af->badflag,(size_t *)§orsize)==0){ af->badflag_set = 1; } /* Read the image file segment if it is present. * If it isn't, scan through the disk image to figure out the size of the disk image. */ if(af_get_segq(af,AF_IMAGESIZE,(int64_t *)&af->image_size)){ /* Calculate the imagesize by scanning all of the pages that are in * the disk image and finding the highest page number. * Then read that page to find the last allocated byte. */ char segname[AF_MAX_NAME_LEN]; size_t datalen = 0; af_rewind_seg(af); // start at the beginning int64_t highest_page_number = 0; while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){ if(segname[0]==0) continue; // ignore sector int64_t pagenum = af_segname_page_number(segname); if(pagenum > highest_page_number) highest_page_number = pagenum; } size_t highest_page_len = 0; if(af_get_page(af,highest_page_number,0,&highest_page_len)==0){ af->image_size = af->image_pagesize * highest_page_number + highest_page_len; } } af->image_size_in_file = af->image_size; }
static AFFILE *evd_file_with_seg(AFFILE *af,const char *name) { struct evd_private *ap = EVD_PRIVATE(af); for(unsigned int i=0;i<ap->num_evfs;i++){ if(af_get_seg(ap->evfs[i],name,0,0,0)==0){ return ap->evfs[i]; } } errno = ENOTDIR; // get ready for error return return 0; }
/* * make the IMAGE_GID segment if it doesn't exist * Returns -1 if an error, 0 if the GID exists, and 1 if one is made. */ int af_make_gid(AFFILE *af) { int ret = 0; AF_WRLOCK(af); if(af_get_seg(af,AF_IMAGE_GID,0,0,0)!=0){ unsigned char bit128[16]; RAND_pseudo_bytes(bit128,sizeof(bit128)); int r = af_update_seg(af,AF_IMAGE_GID,0,bit128,sizeof(bit128)); if(r<0) ret = -1; else ret = 1; } AF_UNLOCK(af); return ret; }
int af_get_segq(AFFILE *af,const char *name,int64_t *aff_quad) { unsigned char buf[8]; size_t bufsize = sizeof(buf); if(af_get_seg(af,name,0,(unsigned char *)&buf,&bufsize)){ return -1; // couldn't get it... } if(bufsize!=sizeof(struct aff_quad)){ // make sure size is good. return -1; } *aff_quad = af_decode_q(buf); return 0; }
void xmlseg(BIO *bp,AFFILE *af,const char *segname) { BIO_printf(bp," <segment>\n"); BIO_printf(bp," <name>%s</name>\n",segname); /* Get the signature and base64 it (if we can) */ u_char sigbuf[1024]; size_t sigbuf_len = sizeof(sigbuf); char segname_sig[1024]; strlcpy(segname_sig,segname,sizeof(segname_sig)); strlcat(segname_sig,AF_SIG256_SUFFIX,sizeof(segname_sig)); if(af_get_seg(af,segname_sig,0,sigbuf,&sigbuf_len)==0){ char sigbuf48[2048]; int sigbuf48_len = b64_ntop(sigbuf,sigbuf_len,sigbuf48,sizeof(sigbuf48)); sigbuf48[sigbuf48_len] = 0; // null terminate BIO_printf(bp," <sig>%s</sig>\n",sigbuf48); } BIO_printf(bp," </segment>\n"); }
/* af_get_imagesize: * Return the byte # of last mapped byte in image, or size of device; * No locking is needed because individual elements of the af structure are not accessed. */ int64_t af_get_imagesize(AFFILE *af) { int64_t ret = -1; struct af_vnode_info vni; memset(&vni,0,sizeof(vni)); if(af_vstat(af,&vni)==0){ /* If vni.imagesize is 0 and if there are encrypted segments and if there * is no imagesize segment but there is an encrypted one, then we can't read this encrypted file... */ if(vni.imagesize<=0 && vni.segment_count_encrypted>0){ if(af_get_seg(af,AF_IMAGESIZE,0,0,0)!=0){ errno = EPERM; goto done; } } ret = vni.imagesize; } done:; return ret; }
int af_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg, unsigned char *data,size_t *datalen) { size_t datalen_orig = datalen ? *datalen : 0; AF_READLOCK(af); if(af->v->get_next_seg==0){ errno = ENOTSUP; AF_UNLOCK(af); return -1; } int r = (*af->v->get_next_seg)(af,segname,segname_len,arg,data,datalen); #ifdef HAVE_AES_ENCRYPT if(AF_SEALING_VNODE(af) && ends_with(segname,AF_AES256_SUFFIX) && af->crypto->auto_decrypt){ segname[strlen(segname)-strlen(AF_AES256_SUFFIX)] = 0; /* An encrypted segment was retrieved. * If it fit, decrypt and return. * If it doesn't fit, try to get it again (which will use our adaptive blocksize) * * Normaly it will fit becuase the caller doesn't know how long the 'next' segment is, * so the caller normally leaves enough space. */ if(r==0){ af_aes_decrypt(af,segname,data,datalen); AF_UNLOCK(af); return 0; } if(r==AF_ERROR_DATASMALL && datalen && (*datalen % AES_BLOCK_SIZE !=0)){ *datalen = datalen_orig; AF_UNLOCK(af); return af_get_seg(af,segname,arg,data,datalen); } AF_UNLOCK(af); return r; // not sure why we got this error } #endif AF_UNLOCK(af); return r; }
/* afm_split_raw_setup: * Sets up the parameters of the split-raw by reading from the metadata file. * The advantage of doing it this way is that a new file can be opened, * the metadata parmeters set, and then an af_write() call made, and the values. * get copied. */ static int afm_split_raw_setup(AFFILE *af) { struct afm_private *ap = AFM_PRIVATE(af); if(ap->sr_initialized) return 0; // already setup /* The size of AF_PAGES_PER_RAW_IMAGE_FILE indicates whether the file is split. * If it is not present, or if it is 0-length, assume that the file is not split. */ uint64_t pages_per_file = 0; size_t len = 0; if (af_get_seg(ap->aff,AF_PAGES_PER_RAW_IMAGE_FILE,0,0,&len)) { /* Not in file; put it there based on maxsize and image_pagesize, * both of which better be set at this point */ if (af->image_pagesize < 1) { (*af->error_reporter)("afm_split_raw_setup: image_pagesize==0\n"); return -1; } if (af->maxsize % af->image_pagesize) { (*af->error_reporter)("afm_split_raw_setup: maxsize (%"I64d") " "not a multiple of image_pagesize (%d)\n", af->maxsize,af->image_pagesize); return -1; } pages_per_file = af->maxsize / af->image_pagesize; if (af_update_segq (af, AF_PAGES_PER_RAW_IMAGE_FILE, pages_per_file)) { (*af->error_reporter)("split_raw_read_write_setup: %s: failed to write %s\n", af_filename(af), AF_PAGES_PER_RAW_IMAGE_FILE); return -1; } } /* Now, read the segment (which might have just been put there) and set up the split_raw file */ if(af_get_segq(af,AF_PAGES_PER_RAW_IMAGE_FILE,(int64_t *)&pages_per_file)){ (*af->error_reporter)("split_raw_read_write_setup: %s: failed to write %s\n", af_filename(af), AF_PAGES_PER_RAW_IMAGE_FILE); return -1; } /* Verify that splitraw's notion of the rawfilesize is the same as the * metadata's notion if the AFF image_size has been set */ if (ap->aff->image_size && ap->aff->image_size != ap->sr->image_size) { (*af->error_reporter)("afm_split_raw_setup: internal error. " "AFF image_size %"I64d" != SR image_size %"I64d"\n", ap->aff->image_size,ap->sr->image_size); return -1; } /* Uses pages_per_file to set the maxsize of the split_raw if it hasn't been set yet*/ if(ap->sr->maxsize==0){ ap->sr->maxsize = pages_per_file * af->image_pagesize; } /* Verify that the parameters make sense */ if (ap->sr->maxsize != (pages_per_file * af->image_pagesize) && pages_per_file>0) { (*af->error_reporter)("afm_split_raw_setup: %s: per size indicated by metadata (%d * %d) " "doesn't match maxsize (%"I64d")\n", af_filename(af),pages_per_file,af->image_pagesize,ap->sr->maxsize); return -1; } /* Push down the image_pagesize from the AFM to the split_raw */ uint32_t image_pagesize = af->image_pagesize; // default to what's in memory af_get_seg(af,AF_PAGESIZE,&image_pagesize,0,0); // get from the AFF file if possible ap->sr->image_pagesize = af->image_pagesize; // overwrite the default with what the AFM file ap->sr_initialized = 1; return 0; }
static int afm_open(AFFILE *af) { af->vnodeprivate = (void *)calloc(sizeof(struct afm_private),1); struct afm_private *ap = AFM_PRIVATE(af); ap->aff = af_open_with(af_filename(af),af->openflags,af->openmode,&vnode_aff); if(ap->aff==0){ // open failed? afm_close(af); return -1; } ap->aff->parent = af; /* If this is a new file, write out the default split raw extension */ if(af->exists == 0){ if(afm_create(af)) return -1; } /* If this is an old file, read the image_pagesize */ if(af->exists){ af->image_pagesize = ap->aff->image_pagesize; } /* Read the split raw extension */ char raw_file_extension[4]; size_t len=3; // don't overwrite the NUL memset(raw_file_extension,0,sizeof(raw_file_extension)); if (af_get_seg(ap->aff,AF_RAW_IMAGE_FILE_EXTENSION,0,(unsigned char *)raw_file_extension,&len)) { (*af->error_reporter)("afm_open: %s: %s segment missing or too large\n", af_filename(af),AF_RAW_IMAGE_FILE_EXTENSION); afm_close(af); return -1; } if(invalid_extension_char(raw_file_extension,len)){ (*af->error_reporter)("afm_open: file extension contains invalid character\n", af->fname, AF_RAW_IMAGE_FILE_EXTENSION); afm_close(af); return -1; } /* Now open the splitraw file */ char *sr_filename = strdup(af_filename(af)); char *ext = strrchr(sr_filename,'.'); if(!ext){ (*af->error_reporter)("afm_open: cannot find extension in '%s'",sr_filename); free(sr_filename); afm_close(af); return -1; } ext++; // skip past '.' if(strlen(ext) != strlen(raw_file_extension)){ (*af->error_reporter)("afm_open: file extension in '%s' too short",sr_filename); free(sr_filename); afm_close(af); return -1; } strcpy(ext,raw_file_extension); ap->sr = af_open_with(sr_filename,af->openflags,af->openmode,&vnode_split_raw); if(ap->sr==0){ (*af->error_reporter)("afm_open: could not open '%s'",sr_filename); free(sr_filename); afm_close(af); return -1; } ap->sr->parent = af; free(sr_filename); /* Additional setup will happen first time a data read/write call is made * by the function afm_read_write_setup(). * This allows a new file to be created with af_open() and then to have * the parameters set with af_update_seg() calls, yet the split_raw * implementation gets the proper settings */ return 0; }
static void aff_imgstat(TSK_IMG_INFO * img_info, FILE * hFile) { IMG_AFF_INFO *aff_info = (IMG_AFF_INFO *) img_info; unsigned char buf[512]; size_t buf_len = 512; tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n"); tsk_fprintf(hFile, "--------------------------------------------\n"); tsk_fprintf(hFile, "Image Type: "); switch (aff_info->type) { case AF_IDENTIFY_AFF: tsk_fprintf(hFile, "AFF\n"); break; case AF_IDENTIFY_AFD: tsk_fprintf(hFile, "AFD\n"); break; case AF_IDENTIFY_AFM: tsk_fprintf(hFile, "AFM\n"); break; default: tsk_fprintf(hFile, "AFFLIB (%d)\n", aff_info->type); break; } tsk_fprintf(hFile, "\nSize in bytes: %" PRIuOFF "\n", img_info->size); // we won't have the rest of the info for the non-AFF formats. if (img_info->itype == TSK_IMG_TYPE_AFF_ANY) return; tsk_fprintf(hFile, "\nMD5: "); if (af_get_seg(aff_info->af_file, AF_MD5, NULL, buf, &buf_len) == 0) { int i; for (i = 0; i < 16; i++) { tsk_fprintf(hFile, "%x", buf[i]); } tsk_fprintf(hFile, "\n"); } else { tsk_fprintf(hFile, "Segment not found\n"); } buf_len = 512; tsk_fprintf(hFile, "SHA1: "); if (af_get_seg(aff_info->af_file, AF_SHA1, NULL, buf, &buf_len) == 0) { int i; for (i = 0; i < 20; i++) { tsk_fprintf(hFile, "%x", buf[i]); } tsk_fprintf(hFile, "\n"); } else { tsk_fprintf(hFile, "Segment not found\n"); } /* Creator segment */ buf_len = 512; if (af_get_seg(aff_info->af_file, AF_CREATOR, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Creator: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_CASE_NUM, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Case Number: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_IMAGE_GID, NULL, buf, &buf_len) == 0) { unsigned int i; tsk_fprintf(hFile, "Image GID: "); for (i = 0; i < buf_len; i++) { tsk_fprintf(hFile, "%X", buf[i]); } tsk_fprintf(hFile, "\n"); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_ACQUISITION_DATE, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Acquisition Date: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_ACQUISITION_NOTES, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Acquisition Notes: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_ACQUISITION_DEVICE, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Acquisition Device: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_AFFLIB_VERSION, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "AFFLib Version: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_DEVICE_MANUFACTURER, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Device Manufacturer: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_DEVICE_MODEL, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Device Model: %s\n", buf); } buf_len = 512; if (af_get_seg(aff_info->af_file, AF_DEVICE_SN, NULL, buf, &buf_len) == 0) { buf[buf_len] = '\0'; tsk_fprintf(hFile, "Device SN: %s\n", buf); } return; }
int aestest() { unsigned char keyblock[32]; /* Make a key; doesn't need to be a good key; make it 256 bits */ for(int i=0;i<32;i++){ keyblock[i] = i; } AFFILE *af = af_open("crypto.aff",O_CREAT|O_RDWR|O_TRUNC,0666); if(!af) err(1,"af_open"); if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); af_set_pagesize(af,65536); /* Now, let's write some data of various sizes */ u_char test[1024],buf[1024],rbuf[1024]; size_t buflen = sizeof(buf); make_test_seg(test,0); for(u_int len=0;len<=strlen((const char *)test);len++){ if(af_update_seg(af,"page0",0,test,len)) err(1,"af_update_seg len=%d",len); /* Now try to read the segment */ memset(buf,0,sizeof(buf)); buflen = sizeof(buf); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)){ err(1,"Could not read encrypted segment with length %d.\n",len); } if(buflen!=len){ printf("size of returned segment = %zd ",buflen); printf("(should be %d) \n",len); exit(0); } if(memcmp(buf,test,len)!=0){ printf("does not match\n"); printf(" wanted: %s\n",test); printf(" got: %s\n",buf); exit(0); } } if(af_close(af)) err(1,"af_close"); /* Now re-open the file, do not set the encryption key, and see if we can read it */ int r; memset(buf,0,sizeof(buf)); af = af_open("crypto.aff",O_RDONLY,0666); buflen = sizeof(buf); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(r!=-1) { errx(1,"Error; attempt to read segment 'encrypted' succeded. It should have failed."); } /* Try to read 'encrypted/aes' */ r = af_get_seg(af,"encrypted/aes",0,(unsigned char *)buf,&buflen); if(memcmp(buf,test,buflen)==0){ errx(1,"Error: segment encrypted/aes wasn't actually encrypted."); } af_close(af); /* Now set the correct encryption key and see if we can read it */ af = af_open("crypto.aff",O_RDONLY,0666); if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); buflen = sizeof(buf); memset(buf,0,sizeof(buf)); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(buflen != strlen((const char *)test)){ errx(1,"Error: Could not read encrypted segment after re-opening file"); } if(memcmp(buf,test,buflen)!=0) errx(1,"Error: Re-read of file produces wrong data."); printf("encrypted data read and decrypted: '%s'\n",buf); /* Try to read a segment that doesn't eixst */ buflen = 0; if(af_get_seg(af,"encrypted2",0,0,&buflen)==0){ errx(1,"Error: Attempt to get size of non-existant segment 'encrypted2' got %zd\n",buflen); } af_close(af); /* Now set the wrong encryption key and see if we can read it */ memset(buf,0,sizeof(buf)); af = af_open("crypto.aff",O_RDONLY,0666); keyblock[3] = 42; if(af_set_aes_key(af,keyblock,256)) err(1,"af_set_aes_key"); buflen = sizeof(buf); r = af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen); if(memcmp(buf,test,buflen)==0) errx(1,"Error: Setting wrong key still produces correct data."); af_close(af); printf("Basic crypto checks. Now check passphrase....\n"); /* Write the data with a passphrase and try to read it back */ af = af_open("crypto_pass.aff",O_CREAT|O_RDWR|O_TRUNC,0666); if(!af) err(1,"af_open 3"); af_set_pagesize(af,65536); if(af_establish_aes_passphrase(af,"yummy")) err(1,"af_establish_aes_passphrase"); if(af_use_aes_passphrase(af,"yummy")) err(1,"af_use_aes_passphrase"); if(af_update_seg(af,"page0",0,(const u_char *)test,strlen((const char *)test))) err(1,"af_update_seg failed at 3"); if(af_close(af)) err(1,"af_close at 3"); /* Now try to read it back */ memset(rbuf,0,sizeof(rbuf)); size_t rbuflen = sizeof(rbuf); af = af_open("crypto_pass.aff",O_RDONLY,0666); if(!af) err(1,"af_open 4"); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)==0){ errx(1,"af_get_seg should have failed and didn't"); } if(af_use_aes_passphrase(af,"yummy")) err(1,"af_set_passphrase 2"); rbuflen=sizeof(rbuf); if(af_get_seg(af,"page0",0,(unsigned char *)rbuf,&rbuflen)){ errx(1,"af_get_seg failed"); } if(rbuflen!=strlen((const char *)test)) errx(1,"Reading encrypted data returned wrong size"); if(memcmp(rbuf,test,rbuflen)!=0) errx(1,"Error: wrong data"); printf("encrypted data read with passphrase 'yummy': %s\n",rbuf); af_close(af); /* Try to change the passphrase */ af = af_open("crypto_pass.aff",O_RDWR,0666); if(!af) err(1,"af_open 5"); if(af_change_aes_passphrase(af,"yummy","dummy")) err(1,"could not change passphrase"); af_close(af); /* Try to read with new passphrase */ af = af_open("crypto_pass.aff",O_RDONLY,0666); if(!af) err(1,"af_open 5"); memset(rbuf,0,sizeof(rbuf)); rbuflen = sizeof(rbuf); if(af_use_aes_passphrase(af,"dummy")) err(1,"af_set_passphrase 2"); rbuflen=sizeof(rbuf); if(af_get_seg(af,"page0",0,(unsigned char *)rbuf,&rbuflen)){ errx(1,"af_get_seg failed"); } if(rbuflen!=strlen((const char *)test)) errx(1,"Reading encrypted with new passphrase data returned wrong size"); if(memcmp(rbuf,test,rbuflen)!=0) errx(1,"Error: wrong data"); printf("encrypted data read with new passphrase 'dummy': %s\n",rbuf); af_close(af); exit(0); /* Now try to read with the wrong passphrase */ af = af_open("crypto.aff",O_RDONLY,0666); if(af_use_aes_passphrase(af,"yummy2")) err(1,"af_set_passphrase 3"); buflen=sizeof(buf); memset(buf,0,sizeof(buf)); if(af_get_seg(af,"page0",0,(unsigned char *)buf,&buflen)){ printf("Couldn't get data with wrong passphrase (that's good)\n"); } printf("data read with wrong passphrase: %s\n",buf); if(buflen>0 && memcmp(buf,test,buflen)==0){ errx(1,"Error: data fetched with wrong passphrase was not scrambled."); } af_close(af); exit(0); }
/* Add a file to the AFF system. * if fname==0, create a new one and copy over the relevant metadata... */ static int afd_add_file(AFFILE *af,const char *fname_) { struct afd_private *ap = AFD_PRIVATE(af); const char *segs_to_copy[] = {AF_BADFLAG, AF_CASE_NUM, AF_IMAGE_GID, AF_ACQUISITION_ISO_COUNTRY, AF_ACQUISITION_COMMAND_LINE, AF_ACQUISITION_DATE, AF_ACQUISITION_NOTES, AF_ACQUISITION_DEVICE, AF_ACQUISITION_TECHNICIAN, AF_DEVICE_MANUFACTURER, AF_DEVICE_MODEL, AF_DEVICE_SN, AF_DEVICE_FIRMWARE, AF_DEVICE_SOURCE, AF_CYLINDERS, AF_HEADS, AF_SECTORS_PER_TRACK, AF_LBA_SIZE, AF_HPA_PRESENT, AF_DCO_PRESENT, AF_LOCATION_IN_COMPUTER, AF_DEVICE_CAPABILITIES, 0}; char fname[MAXPATHLEN+1]; memset(fname,0,sizeof(fname)); if(fname_){ strlcpy(fname,fname_,sizeof(fname)); } else { aff_filename(af,fname,sizeof(fname),ap->num_afs); } int new_file = access(fname,F_OK)!=0; // Is this a new file? AFFILE *af2 = af_open(fname,af->openflags|AF_NO_CRYPTO,af->openmode); if(af2==0){ (*af->error_reporter)("open(%s,%d,%d) failed: %s\n", fname,af->openflags,af->openmode,strerror(errno)); return -1; // this is bad } ap->num_afs += 1; ap->afs = (AFFILE **)realloc(ap->afs,sizeof(AFFILE *) * ap->num_afs); ap->afs[ap->num_afs-1] = af2; if(new_file){ /* Copy over configuration from AFD vnode*/ af_enable_compression(af2,af->compression_type,af->compression_level); af_set_pagesize(af2,af->image_pagesize); // af_set_sectorsize(af2,af->image_sectorsize); af_update_seg(af,AF_AFF_FILE_TYPE,0,(const u_char *)"AFD",3); /* If this is the second file, copy over additional metadata from first... */ if(ap->num_afs>1){ AFFILE *af0 = ap->afs[0]; memcpy(af2->badflag,af0->badflag,af->image_sectorsize); af2->bytes_memcpy += af->image_sectorsize; for(const char **segname=segs_to_copy;*segname;segname++){ unsigned char data[65536]; // big enough for most metadata size_t datalen = sizeof(data); unsigned long arg=0; if(af_get_seg(af0,*segname,&arg,data,&datalen)==0){ int r = af_update_seg(af2,*segname,arg,data,datalen); if(r!=0){ (*af->error_reporter)("afd_add_file: could not update %s in %s (r=%d)", *segname,af_filename(af2),r); } } } } } return 0; }
int AffNode::addSegmentAttribute(Attributes* vmap, AFFILE* af, const char* segname) { #ifdef NEW_AFF_LIB uint32_t arg; #else unsigned long arg; #endif unsigned char *data = 0; if (segname[0] == 0) return (0); size_t data_len = 0; if(af_get_seg(af, segname, &arg, 0, &data_len)) { return (0); } data = (unsigned char *)malloc(data_len); if(af_get_seg(af, segname, 0, data, &data_len)) { free(data); return (0); } if(strcmp(segname, AF_ACQUISITION_SECONDS) == 0) { int hours = arg / 3600; int minutes = (arg / 60) % 60; int seconds = arg % 60; vtime* time = new vtime; time->hour = hours; time->minute = minutes; time->second = seconds; (*vmap)[std::string(segname)] = new Variant(time); free(data); return (1); } if(((arg == AF_SEG_QUADWORD) && (data_len==8)) || af_display_as_quad(segname)) { switch(data_len) { case 8: (*vmap)[segname] = new Variant(af_decode_q(data)); break; case 0: (*vmap)[segname] = new Variant(0); break; default: (*vmap)[segname] = new Variant(std::string("Cannot decode segment")); } free(data); return (1); } if (data_len == 0 && arg != 0) { (*vmap)[std::string(segname)] = new Variant((uint64_t)arg); free(data); return (1); } if(af_display_as_hex(segname) || (data_len == 16 && strstr(segname, "md5")) || (data_len == 20 && strstr(segname, "sha1"))) { char buf[80]; af_hexbuf(buf, sizeof(buf), data, data_len, AF_HEXBUF_NO_SPACES); (*vmap)[std::string(segname)] = new Variant(std::string(buf)); free(data); return (1); } else { (*vmap)[segname] = new Variant(std::string((char *)data)); free(data); return (1); } }
int fix(const char *infile) { char buf[1024]; int flags = (opt_fix ? O_RDWR : O_RDONLY) | O_BINARY; switch(af_identify_file_type(infile,1)){ case AF_IDENTIFY_ERR: perror(infile); return 0; default: fprintf(stderr,"%s is not an AFF file\n",infile); return 0; case AF_IDENTIFY_AFF: break; } printf("%s ",infile); int r=0; /* First see if the if the file begins with an AFF flag */ int fd = open(infile,flags,0666); if(fd<0) err(1,"fopen(%s)",infile); if(read(fd,buf,strlen(AF_HEADER)+1)!=strlen(AF_HEADER)+1) err(1,"can't read AFF file header. Stop."); if(strcmp(buf,AF_HEADER)!=0) err(1,"%s does not begin with an AF_HEADER. Stop.",infile); if(read(fd,buf,strlen(AF_SEGHEAD)+1)!=strlen(AF_SEGHEAD)+1) err(1,"Can't read AF_SEGHEAD after AF_HEADER. Stop."); if(strcmp(buf,AF_SEGHEAD)!=0) err(1,"%s does not have an AF_SEGHEAD after AF_SEGEADER. Stop.",infile); /* Figure out length */ off_t len = lseek(fd,0,SEEK_END); if(len<0) err(1,"Can't seek to end of %s. Stop.",infile); close(fd); AFFILE *af = af_open_with(infile,AF_HALF_OPEN|flags,0,&vnode_aff); printf("Scanning AFF file...\n"); r = (*af->v->open)(af); /* See if we can build a TOC */ if(r<0){ printf("AFF file corrupt at %"I64d" out of %"I64d" (%"I64d" bytes from end)\n", ftello(af->aseg),(int64_t)len,len-ftello(af->aseg)); if(opt_fix){ printf("Truncating... %d \n",fileno(af->aseg)); if(ftruncate(fileno(af->aseg),ftello(af->aseg))){ err(1,"ftruncate"); } } } /* See if it has a GID or an encrypted GID */ if(af_get_seg(af,AF_IMAGE_GID,0,0,0)!=0 && af_get_seg(af,AF_IMAGE_GID AF_AES256_SUFFIX,0,0,0)!=0){ printf("AFF file is missing a GID. "); if(opt_fix){ printf("Making one..."); if(af_make_gid(af)<0) af_err(1,"af_make_gid"); } putchar('\n'); } af_close(af); return 0; }
/* af_open_with is the real open routine. * It opens a particular file with a particular vnode implementation. */ AFFILE *af_open_with(const char *url,int flags,int mode, struct af_vnode *v) { /* Alloate the space for the AFFILE structure */ AFFILE *af = (AFFILE *)calloc(sizeof(AFFILE),1); af_crypto_allocate(af); #ifdef HAVE_PTHREAD pthread_rwlock_init(&af->rwlock); AF_WRLOCK(af); #endif af->v = v; af->version = 2; af->openflags = flags | O_BINARY; // make sure that we ask for binray af->openmode = mode; af->image_sectorsize = 512; // default size af->error_reporter = warnx; af->badflag = (unsigned char *)malloc(af->image_sectorsize); /* Decode URL */ af_parse_url(url,&af->protocol,&af->hostname,&af->username,&af->password, &af->port,&af->fname); /* A null passphrase is the same as no passphrase*/ if(af->password && af->password[0]==0){ free(af->password); af->password=0; } /* If no password was set and the AFFLIB_PASSPHRASE environment variable is set, use that */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE)){ af->password = strdup(getenv(AFFLIB_PASSPHRASE)); } /* If no password is set and its in a file, get it there */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE_FILE)){ int fd = open(AFFLIB_PASSPHRASE_FILE,O_RDONLY,0); if(fd>0){ struct stat sb; if(fstat(fd,&sb)==0){ af->password = (char *)malloc(sb.st_size); int r = read(fd,af->password,sb.st_size); if(r!=sb.st_size){ free(af->password); af->password=0; // couldn't read it } close(fd); } } } /* If no password is set and its in a file, get it there */ if(af->password==0 && getenv(AFFLIB_PASSPHRASE_FD)){ int fd = atoi(AFFLIB_PASSPHRASE_FD); af->password = (char *)malloc(1); int buflen = 0; int rlen = 0; char mybuf[1024]; while((rlen=read(fd,mybuf,sizeof(mybuf)))>0){ af->password = (char *)realloc(af->password,buflen+rlen+1); memcpy(af->password+buflen,mybuf,rlen); buflen += rlen; af->password[buflen] = '\000'; } } /* TK: If no password was set and the AFFLIB_ASK_PASS is set, ask for a passphrase */ /* Note things for hard files */ af->exists = (access(af->fname,R_OK) == 0); // does the file exist? /* Right now just set up the cache by hand */ const char *cache_pages = getenv(AFFLIB_CACHE_PAGES); if(cache_pages) af->num_pbufs = atoi(cache_pages); if(af->num_pbufs<1) af->num_pbufs = AFFLIB_CACHE_PAGES_DEFAULT; // default valuen af->pbcache = (struct aff_pagebuf *)calloc(af->num_pbufs,sizeof(struct aff_pagebuf)); if(af->pbcache==0){ // if can't allocate the full amount af->num_pbufs = 2; // try a significantly smaller cache af->pbcache = (struct aff_pagebuf *)calloc(af->num_pbufs,sizeof(struct aff_pagebuf)); } if(flags & AF_HALF_OPEN) return af; // for low-level tools /* Try opening it! */ if((*af->v->open)(af)){ strlcpy(af_error_str,af->error_str,sizeof(af_error_str)); // make a copy of the error string af_deallocate(af); return 0; } /* If there is no AFFKEY and the file is read-only, don't use a password */ if(af->password && (af_get_seg(af,AF_AFFKEY,0,0,0)!=0) && ((af->openflags & O_ACCMODE)==O_RDONLY)){ af_sanitize_password(af); } /* Set up the encryption if requested and if this support metadata */ if(AF_SEALING_VNODE(af) && ((flags & AF_NO_CRYPTO)==0)){ bool can_decrypt = false; if(af->password){ struct af_vnode_info vni; memset(&vni,0,sizeof(vni)); if((*af->v->vstat)(af,&vni)==0 && vni.supports_metadata){ int r = 0; if(af_get_seg(af,AF_AFFKEY,0,0,0)!=0){ // it does not have a password r = af_establish_aes_passphrase(af,af->password); } if(r==0){ r = af_use_aes_passphrase(af,af->password); if(r==0) { can_decrypt = true; } else { (*af->error_reporter)("af_open: invalid passphrase: '%s'",af->password); } } af_sanitize_password(af); } } /* Try public key... */ if(can_decrypt==false){ const char *kf = getenv(AFFLIB_DECRYPTING_PRIVATE_KEYFILE); if(kf){ af_set_unseal_keyfile(af,kf); } } } af_read_sizes(af); // set up the metadata if(af_trace) fprintf(af_trace,"af_open_with(%s,%o,%o,%s)\n",url,flags,mode,v->name); return af; }