librpc: Introduce cab.idl
authorGünther Deschner <gd@samba.org>
Thu, 15 Sep 2016 11:36:35 +0000 (13:36 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Thu, 24 Nov 2016 19:24:26 +0000 (20:24 +0100)
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>
librpc/idl/cab.idl [new file with mode: 0644]
librpc/idl/wscript_build
librpc/ndr/ndr_cab.c [new file with mode: 0644]
librpc/ndr/ndr_cab.h [new file with mode: 0644]
librpc/wscript_build
source4/librpc/wscript_build

diff --git a/librpc/idl/cab.idl b/librpc/idl/cab.idl
new file mode 100644 (file)
index 0000000..af8dad2
--- /dev/null
@@ -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
+               );
+
+}
index 13b29b2561e67baf2b14774fbcd9ebaae8c0481d..1f09ae013f06bf6cda3d461472656bb9ea83138e 100644 (file)
@@ -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 (file)
index 0000000..87c103a
--- /dev/null
@@ -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 (file)
index 0000000..39b6bc9
--- /dev/null
@@ -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);
index 1c7cc0aa9517ce2f349c2c2ac9a04be4ec96a01d..2b4cc0511962654364688c8d5e3102888084f4ac 100644 (file)
@@ -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'
index 77d1777f6dd2e6b68368f1f3632a414117e46008..60404f8e08d16cb14991c2e537cc5ab32339e743 100755 (executable)
@@ -69,18 +69,66 @@ bld.SAMBA_PIDL_TABLES('GEN_NDR_TABLES', 'gen_ndr/tables.c')
 
 bld.SAMBA_SUBSYSTEM('ndr-table',
        source='../../librpc/ndr/ndr_table.c gen_ndr/tables.c',
-        public_deps='''ndr-standard NDR_AUDIOSRV NDR_DSBACKUP NDR_EFS
-        NDR_DRSUAPI NDR_POLICYAGENT NDR_UNIXINFO NDR_SPOOLSS NDR_EPMAPPER
-        NDR_DBGIDL NDR_DSSETUP NDR_MSGSVC NDR_WINSIF NDR_MGMT
-        NDR_OXIDRESOLVER NDR_REMACT NDR_WZCSVC
-        NDR_BROWSER NDR_W32TIME NDR_SCERPC NDR_TRKWKS NDR_KEYSVC ndr-krb5pac
-        NDR_XATTR NDR_SCHANNEL NDR_ROT NDR_DRSBLOBS ndr_nbt NDR_WINSREPL
-        NDR_SECURITY NDR_DNSSERVER NDR_WINSTATION NDR_IRPC NDR_OPENDB
-        NDR_SASL_HELPERS NDR_NOTIFY NDR_WINBIND NDR_FRSRPC NDR_FRSAPI
-        NDR_FRSTRANS NDR_NFS4ACL NDR_NTP_SIGND NDR_DCOM NDR_WMI
-        NDR_NAMED_PIPE_AUTH NDR_NTLMSSP NDR_DFSBLOBS NDR_DNSP
-        NDR_NTPRINTING NDR_DNS NDR_BACKUPKEY NDR_PREG NDR_BKUPBLOBS NDR_FSCC
-        NDR_FRSBLOBS NDR_CLUSAPI NDR_WINSPOOL''',
+        public_deps='''
+                    ndr-standard
+                    NDR_AUDIOSRV
+                    NDR_DSBACKUP
+                    NDR_EFS
+                    NDR_DRSUAPI
+                    NDR_POLICYAGENT
+                    NDR_UNIXINFO
+                    NDR_SPOOLSS
+                    NDR_EPMAPPER
+                    NDR_DBGIDL
+                    NDR_DSSETUP
+                    NDR_MSGSVC
+                    NDR_WINSIF
+                    NDR_MGMT
+                    NDR_OXIDRESOLVER
+                    NDR_REMACT
+                    NDR_WZCSVC
+                    NDR_BROWSER
+                    NDR_W32TIME
+                    NDR_SCERPC
+                    NDR_TRKWKS
+                    NDR_KEYSVC
+                    ndr-krb5pac
+                    NDR_XATTR
+                    NDR_SCHANNEL
+                    NDR_ROT
+                    NDR_DRSBLOBS
+                    ndr_nbt
+                    NDR_WINSREPL
+                    NDR_SECURITY
+                    NDR_DNSSERVER
+                    NDR_WINSTATION
+                    NDR_IRPC
+                    NDR_OPENDB
+                    NDR_SASL_HELPERS
+                    NDR_NOTIFY
+                    NDR_WINBIND
+                    NDR_FRSRPC
+                    NDR_FRSAPI
+                    NDR_FRSTRANS
+                    NDR_NFS4ACL
+                    NDR_NTP_SIGND
+                    NDR_DCOM
+                    NDR_WMI
+                    NDR_NAMED_PIPE_AUTH
+                    NDR_NTLMSSP
+                    NDR_DFSBLOBS
+                    NDR_DNSP
+                    NDR_NTPRINTING
+                    NDR_DNS
+                    NDR_BACKUPKEY
+                    NDR_PREG
+                    NDR_BKUPBLOBS
+                    NDR_FSCC
+                    NDR_FRSBLOBS
+                    NDR_CLUSAPI
+                    NDR_WINSPOOL
+                    NDR_CAB
+                    ''',
         depends_on='GEN_NDR_TABLES'
         )