summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2016-09-15 13:36:35 +0200
committerAndreas Schneider <asn@cryptomilk.org>2016-11-24 20:24:26 +0100
commit88e1c4dc44388f554dd3cf09ec932009586a227f (patch)
tree221da0fbec1dfaf4a29e8735af29bb6d14b52187 /librpc
parent20eadb5f9a8f68e90c6d33ac78b65255a7631797 (diff)
downloadsamba-88e1c4dc44388f554dd3cf09ec932009586a227f.tar.gz
librpc: Introduce cab.idl
This allows processing of Windows Cabinet files (required for the MS-PAR print protocol implementation) 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.idl135
-rw-r--r--librpc/idl/wscript_build11
-rw-r--r--librpc/ndr/ndr_cab.c153
-rw-r--r--librpc/ndr/ndr_cab.h22
-rw-r--r--librpc/wscript_build7
5 files changed, 326 insertions, 2 deletions
diff --git a/librpc/idl/cab.idl b/librpc/idl/cab.idl
new file mode 100644
index 00000000000..af8dad24404
--- /dev/null
+++ b/librpc/idl/cab.idl
@@ -0,0 +1,135 @@
+#include "idl_types.h"
+
+import "misc.idl";
+
+/*
+ IDL structures defining Cabinet files
+
+ more info can be found at:
+ https://msdn.microsoft.com/en-us/library/bb267310.aspx#cabinet_format
+*/
+
+[
+ pointer_default(unique),
+ helper("../librpc/ndr/ndr_cab.h"),
+ helpstring("Cabinet structure"),
+ uuid("12345678-0000-0000-0000-00000000")
+]
+ interface cab
+{
+
+ /*
+ * flags.cfhdrPREV_CABINET is set if this cabinet file is not the first in
+ * a set of cabinet files. When this bit is set, the szCabinetPrev and
+ * szDiskPrev fields are present in this CFHEADER.
+ *
+ * flags.cfhdrNEXT_CABINET is set if this cabinet file is not the last in a
+ * set of cabinet files. When this bit is set, the szCabinetNext and
+ * szDiskNext fields are present in this CFHEADER.
+ *
+ * flags.cfhdrRESERVE_PRESENT is set if this cabinet file contains any
+ * reserved fields. When this bit is set, the cbCFHeader, cbCFFolder, and
+ * cbCFData fields are present in this CFHEADER.
+ */
+
+ typedef [bitmap16bit] bitmap {
+ cfhdrPREV_CABINET = 0x0001,
+ cfhdrNEXT_CABINET = 0x0002,
+ cfhdrRESERVE_PRESENT = 0x0004
+ } cf_flags;
+
+ typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
+ [charset(DOS),value("MSCF")] uint8 signature[4];
+ [value(0)] uint32 reserved1; /* reserved */
+ uint32 cbCabinet; /* size of this cabinet file in bytes */
+ [value(0)] uint32 reserved2; /* reserved */
+ [value(cFolders*8+36)] uint32 coffFiles; /* offset of the first CFFILE entry */
+ [value(0)] uint32 reserved3; /* reserved */
+ [value(3)] uint8 versionMinor; /* cabinet file format version, minor */
+ [value(1)] uint8 versionMajor; /* cabinet file format version, major */
+ uint16 cFolders; /* number of CFFOLDER entries in this cabinet */
+ uint16 cFiles; /* number of CFFILE entries in this cabinet */
+ cf_flags flags; /* cabinet file option indicators */
+ uint16 setID; /* must be the same for all cabinets in a set */
+ uint16 iCabinet; /* number of this cabinet file in a set */
+#if 0
+ [range(0,60000)] uint16 cbCFHeader; /* (optional) size of per-cabinet reserved area */
+ [range(0,255)] uint8 cbCFFolder; /* (optional) size of per-folder reserved area */
+ [range(0,255)] uint8 cbCFData; /* (optional) size of per-datablock reserved area */
+ uint8 abReserve[]; /* (optional) per-cabinet reserved area */
+ uint8 szCabinetPrev[]; /* (optional) name of previous cabinet file */
+ uint8 szDiskPrev[]; /* (optional) name of previous disk */
+ uint8 szCabinetNext[]; /* (optional) name of next cabinet file */
+ uint8 szDiskNext[]; /* (optional) name of next disk */
+#endif
+ } CFHEADER;
+
+ typedef enum {
+ CF_COMPRESS_NONE = 0,
+ CF_COMPRESS_MSZIP = 1,
+ CF_COMPRESS_LZX = 4611
+ } cf_compress_type;
+
+ typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
+ uint32 coffCabStart; /* offset of the first CFDATA block in this folder */
+ uint16 cCFData; /* number of CFDATA blocks in this folder */
+ cf_compress_type typeCompress; /* compression type indicator */
+#if 0
+ uint8 abReserve[]; /* (optional) per-folder reserved area */
+#endif
+ } CFFOLDER;
+
+ const int ifoldCONTINUED_FROM_PREV = 0xFFFD;
+ const int ifoldCONTINUED_TO_NEXT = 0xFFFE;
+ const int ifoldCONTINUED_PREV_AND_NEXT = 0xFFFF;
+
+ typedef [bitmap16bit] bitmap {
+ _A_RDONLY = 0x01, /* file is read-only */
+ _A_HIDDEN = 0x02, /* file is hidden */
+ _A_SYSTEM = 0x04, /* file is a system file */
+ _A_ARCH = 0x20, /* file modified since last backup */
+ _A_EXEC = 0x40, /* run after extraction */
+ _A_NAME_IS_UTF = 0x80 /* szName[] contains UTF */
+ } cf_attributes;
+
+ typedef [noprint,flag(NDR_NOALIGN)] struct {
+ uint16 date;
+ } cf_date;
+
+ typedef [noprint,flag(NDR_NOALIGN)] struct {
+ uint16 time;
+ } cf_time;
+
+ typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN),gensize] struct {
+ uint32 cbFile; /* uncompressed size of this file in bytes */
+ uint32 uoffFolderStart; /* uncompressed offset of this file in the folder */
+ uint16 iFolder; /* index into the CFFOLDER area */
+ cf_date date; /* date stamp for this file */
+ cf_time time; /* time stamp for this file */
+ cf_attributes attribs; /* attribute flags for this file */
+ [flag(r->attribs & _A_NAME_IS_UTF ? STR_UTF8|STR_NULLTERM : STR_ASCII|STR_NULLTERM)] string szName;
+ } CFFILE;
+
+ typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
+ 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
+ uint8 abReserve[]; /* (optional) per-datablock reserved area */
+#endif
+ uint8 ab[cbData]; /* compressed data bytes */
+ } CFDATA;
+
+ typedef [nopush,nopull,public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
+ CFHEADER cfheader;
+ CFFOLDER cffolders[cfheader.cFolders];
+ CFFILE cffiles[cfheader.cFiles];
+ [noprint,value(ndr_count_cfdata(r))] uint32 cfdata_count;
+ CFDATA cfdata[cfdata_count];
+ } cab_file;
+
+ void decode_cab_file(
+ [in] cab_file file
+ );
+
+}
diff --git a/librpc/idl/wscript_build b/librpc/idl/wscript_build
index 13b29b2561e..1f09ae013f0 100644
--- a/librpc/idl/wscript_build
+++ b/librpc/idl/wscript_build
@@ -34,8 +34,15 @@ bld.SAMBA_PIDL_LIST('PIDL',
output_dir='../gen_ndr')
bld.SAMBA_PIDL_LIST('PIDL',
- '''rap.idl ntprinting.idl preg.idl ioctl.idl printcap.idl
- fsrvp_state.idl''',
+ '''
+ rap.idl
+ ntprinting.idl
+ preg.idl
+ ioctl.idl
+ printcap.idl
+ fsrvp_state.idl
+ cab.idl
+ ''',
options='--header --ndr-parser',
output_dir='../gen_ndr')
diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c
new file mode 100644
index 00000000000..87c103a4901
--- /dev/null
+++ b/librpc/ndr/ndr_cab.c
@@ -0,0 +1,153 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling cab structures
+
+ Copyright (C) Guenther Deschner 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_cab.h"
+
+_PUBLIC_ void ndr_print_cf_time(struct ndr_print *ndr, const char *name, const struct cf_time *r)
+{
+ uint8_t hour = 0, minute = 0, seconds = 0;
+ char *s;
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ hour = r->time >> 11;
+ minute = (r->time >> 5) & 0x3f;
+ seconds = (r->time << 1) & 0x3e;
+ s = talloc_asprintf(ndr, "%02d:%02d:%02d", hour, minute, seconds);
+ if (s == NULL) { return; }
+ ndr_print_string(ndr, "time", s);
+ talloc_free(s);
+}
+
+_PUBLIC_ void ndr_print_cf_date(struct ndr_print *ndr, const char *name, const struct cf_date *r)
+{
+ uint16_t year = 0;
+ uint8_t month = 0, day = 0;
+ char *s;
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ year = (r->date >> 9);
+ year += 1980;
+ month = (r->date >> 5 & 0xf);
+ day = (r->date & 0x1f);
+ s = talloc_asprintf(ndr, "%02d/%02d/%04d", day, month, year);
+ if (s == NULL) { return; }
+ ndr_print_string(ndr, "date", s);
+ talloc_free(s);
+}
+
+uint32_t ndr_count_cfdata(const struct cab_file *r)
+{
+ uint32_t count = 0, i;
+
+ for (i = 0; i < r->cfheader.cFolders; i++) {
+ count += r->cffolders[i].cCFData;
+ }
+
+ return count;
+}
+
+_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;
+ uint32_t cntr_cffiles_0;
+ uint32_t cntr_cfdata_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
+ for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
+ NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
+ }
+ for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
+ NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
+ }
+#if 0
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
+#endif
+ for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (ndr_count_cfdata(r)); cntr_cfdata_0++) {
+ NDR_CHECK(ndr_push_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags, struct cab_file *r)
+{
+ uint32_t size_cffolders_0 = 0;
+ uint32_t cntr_cffolders_0;
+ TALLOC_CTX *_mem_save_cffolders_0 = NULL;
+ uint32_t size_cffiles_0 = 0;
+ uint32_t cntr_cffiles_0;
+ TALLOC_CTX *_mem_save_cffiles_0 = NULL;
+ uint32_t size_cfdata_0 = 0;
+ uint32_t cntr_cfdata_0;
+ TALLOC_CTX *_mem_save_cfdata_0 = NULL;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
+ size_cffolders_0 = r->cfheader.cFolders;
+ NDR_PULL_ALLOC_N(ndr, r->cffolders, size_cffolders_0);
+ _mem_save_cffolders_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cffolders, 0);
+ for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
+ NDR_CHECK(ndr_pull_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffolders_0, 0);
+ size_cffiles_0 = r->cfheader.cFiles;
+ NDR_PULL_ALLOC_N(ndr, r->cffiles, size_cffiles_0);
+ _mem_save_cffiles_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cffiles, 0);
+ for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (size_cffiles_0); cntr_cffiles_0++) {
+ NDR_CHECK(ndr_pull_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffiles_0, 0);
+#if 0
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cfdata_count));
+#else
+ r->cfdata_count = ndr_count_cfdata(r);
+#endif
+ size_cfdata_0 = r->cfdata_count;
+ NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
+ _mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
+ for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (size_cfdata_0); cntr_cfdata_0++) {
+ NDR_CHECK(ndr_pull_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_cab.h b/librpc/ndr/ndr_cab.h
new file mode 100644
index 00000000000..39b6bc9b483
--- /dev/null
+++ b/librpc/ndr/ndr_cab.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling cab structures
+
+ Copyright (C) Guenther Deschner 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+uint32_t ndr_count_cfdata(const struct cab_file *r);
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 1c7cc0aa951..2b4cc051196 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -423,6 +423,13 @@ bld.SAMBA_SUBSYSTEM('NDR_PREG',
public_deps='ndr'
)
+bld.SAMBA_SUBSYSTEM('NDR_CAB',
+ source='''
+ gen_ndr/ndr_cab.c
+ ndr/ndr_cab.c
+ ''',
+ public_deps='ndr')
+
bld.SAMBA_SUBSYSTEM('NDR_FILE_ID',
source='gen_ndr/ndr_file_id.c',
public_deps='ndr'