diff options
author | Günther Deschner <gd@samba.org> | 2016-09-16 00:15:30 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2016-11-24 20:24:26 +0100 |
commit | 4cc4fca23e892250f44a8b6240ab2a488919f6a3 (patch) | |
tree | 03e8dbfaab072c5438e9102cb156add5858974b2 /librpc | |
parent | 88e1c4dc44388f554dd3cf09ec932009586a227f (diff) | |
download | samba-4cc4fca23e892250f44a8b6240ab2a488919f6a3.tar.gz |
librpc: Add autogenerated checksum calculation for Cabinet files
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'librpc')
-rw-r--r-- | librpc/idl/cab.idl | 2 | ||||
-rw-r--r-- | librpc/ndr/ndr_cab.c | 49 | ||||
-rw-r--r-- | librpc/ndr/ndr_cab.h | 1 |
3 files changed, 51 insertions, 1 deletions
diff --git a/librpc/idl/cab.idl b/librpc/idl/cab.idl index af8dad24404..2174bce7334 100644 --- a/librpc/idl/cab.idl +++ b/librpc/idl/cab.idl @@ -111,7 +111,7 @@ import "misc.idl"; } CFFILE; typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct { - uint32 csum; /* checksum of this CFDATA entry */ + [value(ndr_cab_generate_checksum(r))] uint32 csum; /* checksum of this CFDATA entry */ uint16 cbData; /* number of compressed bytes in this block */ uint16 cbUncomp; /* number of uncompressed bytes in this block */ #if 0 diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c index 87c103a4901..611e378cb34 100644 --- a/librpc/ndr/ndr_cab.c +++ b/librpc/ndr/ndr_cab.c @@ -63,6 +63,55 @@ uint32_t ndr_count_cfdata(const struct cab_file *r) return count; } +static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_t seed) +{ + int num_ulong; + uint32_t checksum; + uint8_t *pb; + uint32_t ul; + + num_ulong = length / 4; + checksum = seed; + pb = data; + + while (num_ulong-- > 0) { + ul = *pb++; + ul |= (((uint32_t)(*pb++)) << 8); + ul |= (((uint32_t)(*pb++)) << 16); + ul |= (((uint32_t)(*pb++)) << 24); + + checksum ^= ul; + } + + ul = 0; + + switch (length % 4) { + case 3: + ul |= (((uint32_t)(*pb++)) << 16); + case 2: + ul |= (((uint32_t)(*pb++)) << 8); + case 1: + ul |= *pb++; + default: + break; + } + + checksum ^= ul; + + return checksum; +} + +uint32_t ndr_cab_generate_checksum(const struct CFDATA *r) +{ + uint32_t csumPartial; + + csumPartial = ndr_cab_compute_checksum(&r->ab[0], r->cbData, 0); + + return ndr_cab_compute_checksum((uint8_t *)discard_const(&r->cbData), + sizeof(r->cbData) + sizeof(r->cbUncomp), + csumPartial); +} + _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r) { uint32_t cntr_cffolders_0; diff --git a/librpc/ndr/ndr_cab.h b/librpc/ndr/ndr_cab.h index 39b6bc9b483..59dbc991442 100644 --- a/librpc/ndr/ndr_cab.h +++ b/librpc/ndr/ndr_cab.h @@ -20,3 +20,4 @@ */ uint32_t ndr_count_cfdata(const struct cab_file *r); +uint32_t ndr_cab_generate_checksum(const struct CFDATA *r); |