summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2016-09-16 00:15:30 +0200
committerAndreas Schneider <asn@cryptomilk.org>2016-11-24 20:24:26 +0100
commit4cc4fca23e892250f44a8b6240ab2a488919f6a3 (patch)
tree03e8dbfaab072c5438e9102cb156add5858974b2 /librpc
parent88e1c4dc44388f554dd3cf09ec932009586a227f (diff)
downloadsamba-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.idl2
-rw-r--r--librpc/ndr/ndr_cab.c49
-rw-r--r--librpc/ndr/ndr_cab.h1
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);