int SMBCALL smb_addhashes(smb_t* smb, hash_t** hashes, BOOL skip_marked) { int retval; size_t h; COUNT_LIST_ITEMS(hashes, h); if(!h) /* nothing to add */ return(SMB_SUCCESS); if((retval=smb_open_hash(smb))!=SMB_SUCCESS) return(retval); fseek(smb->hash_fp,0,SEEK_END); for(h=0;hashes[h]!=NULL;h++) { /* skip hashes marked by smb_findhash() */ if(skip_marked && hashes[h]->flags&SMB_HASH_MARKED) continue; /* can't think of any reason to strip SMB_HASH_MARKED flag right now */ if(smb_fwrite(smb,hashes[h],sizeof(hash_t),smb->hash_fp)!=sizeof(hash_t)) { retval=SMB_ERR_WRITE; break; } } smb_close_hash(smb); return(retval); }
void dump_hashes(void) { char tmp[128]; int retval; hash_t hash; if((retval=smb_open_hash(&smb))!=SMB_SUCCESS) { fprintf(errfp,"\n%s!smb_open_hash returned %d: %s\n" ,beep, retval, smb.last_error); return; } while(!smb_feof(smb.hash_fp)) { if(smb_fread(&smb,&hash,sizeof(hash),smb.hash_fp)!=sizeof(hash)) break; printf("\n"); printf("%-10s: %"PRIu32"\n","Number", hash.number); printf("%-10s: %s\n", "Source", smb_hashsourcetype(hash.source)); printf("%-10s: %"PRIu32"\n","Length", hash.length); printf("%-10s: %s\n", "Time", my_timestr(hash.time)); printf("%-10s: %02x\n", "Flags", hash.flags); if(hash.flags&SMB_HASH_CRC16) printf("%-10s: %04x\n", "CRC-16", hash.crc16); if(hash.flags&SMB_HASH_CRC32) printf("%-10s: %08"PRIx32"\n","CRC-32", hash.crc32); if(hash.flags&SMB_HASH_MD5) printf("%-10s: %s\n", "MD5", MD5_hex((BYTE*)tmp,hash.md5)); } smb_close_hash(&smb); }
/* If return value is SMB_ERROR_NOT_FOUND, hash file is left open */ int SMBCALL smb_findhash(smb_t* smb, hash_t** compare, hash_t* found_hash, long source_mask, BOOL mark) { int retval; BOOL found=FALSE; size_t c,count; hash_t hash; if(found_hash!=NULL) memset(found_hash,0,sizeof(hash_t)); if((retval=smb_open_hash(smb))!=SMB_SUCCESS) return(retval); COUNT_LIST_ITEMS(compare, count); if(count) { rewind(smb->hash_fp); while(!feof(smb->hash_fp)) { if(smb_fread(smb,&hash,sizeof(hash),smb->hash_fp)!=sizeof(hash)) break; if(hash.flags==0) continue; /* invalid hash record (!?) */ if((source_mask&(1<<hash.source))==0) /* not checking this source type */ continue; for(c=0;compare[c]!=NULL;c++) { if(compare[c]->source!=hash.source) continue; /* wrong source */ if(compare[c]->length!=hash.length) continue; /* wrong source length */ if(compare[c]->flags&SMB_HASH_MARKED) continue; /* already marked */ if((compare[c]->flags&SMB_HASH_PROC_MASK)!=(hash.flags&SMB_HASH_PROC_MASK)) continue; /* wrong pre-process flags */ if((compare[c]->flags&hash.flags&SMB_HASH_MASK)==0) continue; /* no matching hashes */ if(compare[c]->flags&hash.flags&SMB_HASH_CRC16 && compare[c]->crc16!=hash.crc16) continue; /* wrong crc-16 */ if(compare[c]->flags&hash.flags&SMB_HASH_CRC32 && compare[c]->crc32!=hash.crc32) continue; /* wrong crc-32 */ if(compare[c]->flags&hash.flags&SMB_HASH_MD5 && memcmp(compare[c]->md5,hash.md5,sizeof(hash.md5))) continue; /* wrong crc-16 */ /* successful match! */ break; /* can't match more than one, so stop comparing */ } if(compare[c]==NULL) continue; /* no match */ found=TRUE; if(found_hash!=NULL) memcpy(found_hash,&hash,sizeof(hash)); if(!mark) break; compare[c]->flags|=SMB_HASH_MARKED; } if(found) { smb_close_hash(smb); return(SMB_SUCCESS); } } /* hash file left open */ return(SMB_ERR_NOT_FOUND); }
void maint(void) { int i; ulong l,m,n,f,flagged=0; time_t now; smbmsg_t msg; idxrec_t *idx; printf("Maintaining %s\r\n",smb.file); now=time(NULL); i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } if(smb_open_hash(&smb) == SMB_SUCCESS) { ulong max_hashes=0; printf("Maintaining %s hash file\r\n", smb.file); if((smb.status.attr&(SMB_EMAIL|SMB_NOHASH)) == 0) { max_hashes = smb.status.max_msgs; if(smb.status.max_crcs > max_hashes) max_hashes = smb.status.max_crcs; } if(!max_hashes) { CHSIZE_FP(smb.hash_fp,0); } else if(filelength(fileno(smb.hash_fp)) > (long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))) { if(fseek(smb.hash_fp, -((long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))), SEEK_END) == 0) { hash_t* hashes = malloc(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t)); if(hashes != NULL) { if(fread(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp) == max_hashes * SMB_HASH_SOURCE_TYPES) { CHSIZE_FP(smb.hash_fp,0); rewind(smb.hash_fp); fwrite(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp); } free(hashes); } } } smb_close_hash(&smb); } if(!smb.status.total_msgs) { smb_unlocksmbhdr(&smb); printf("Empty\n"); return; } printf("Loading index...\n"); if((idx=(idxrec_t *)malloc(sizeof(idxrec_t)*smb.status.total_msgs)) ==NULL) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!Error allocating %u bytes of memory\n" ,beep,sizeof(idxrec_t)*smb.status.total_msgs); return; } fseek(smb.sid_fp,0L,SEEK_SET); for(l=0;l<smb.status.total_msgs;l++) { printf("%lu of %"PRIu32"\r" ,l+1,smb.status.total_msgs); if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp)) break; } printf("\nDone.\n\n"); printf("Scanning for pre-flagged messages...\n"); for(m=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&MSG_DELETE) flagged++; } printf("\r100%% (%lu pre-flagged for deletion)\n",flagged); if(smb.status.max_age) { printf("Scanning for messages more than %u days old...\n" ,smb.status.max_age); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L) >smb.status.max_age) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } /* mark for deletion */ printf("\r100%% (%lu flagged for deletion due to age)\n",f); } printf("Scanning for read messages to be killed...\n"); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } printf("\r100%% (%lu flagged for deletion due to read status)\n",f); if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) { printf("Flagging excess messages for deletion...\n"); for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) { if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs); flagged++; idx[m].attr|=MSG_DELETE; } /* mark for deletion */ printf("\nDone.\n\n"); } if(!flagged) { /* No messages to delete */ free(idx); smb_unlocksmbhdr(&smb); return; } if(!(mode&NOANALYSIS)) { printf("Freeing allocated header and data blocks for deleted messages...\n"); if(!(smb.status.attr&SMB_HYPERALLOC)) { i=smb_open_da(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } i=smb_open_ha(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } } for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) { printf("%lu of %lu\r",++n,flagged); msg.idx=idx[m]; msg.hdr.number=msg.idx.number; if((i=smb_getmsgidx(&smb,&msg))!=0) { fprintf(errfp,"\n%s!smb_getmsgidx returned %d: %s\n" ,beep,i,smb.last_error); continue; } i=smb_lockmsghdr(&smb,&msg); if(i) { fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } if((i=smb_getmsghdr(&smb,&msg))!=0) { smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */ if((i=smb_putmsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_putmsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_unlockmsghdr(&smb,&msg); if((i=smb_freemsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); fprintf(errfp,"\n%s!smb_freemsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_freemsgmem(&msg); } } if(!(smb.status.attr&SMB_HYPERALLOC)) { smb_close_ha(&smb); smb_close_da(&smb); } printf("\nDone.\n\n"); } printf("Re-writing index...\n"); rewind(smb.sid_fp); CHSIZE_FP(smb.sid_fp,0); for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) continue; printf("%lu of %lu\r",++n,l-flagged); fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); } printf("\nDone.\n\n"); fflush(smb.sid_fp); free(idx); smb.status.total_msgs-=flagged; smb_putstatus(&smb); smb_unlocksmbhdr(&smb); }