From c5e9b1e606ff7636672e4feacd3a80b029121bd5 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 13 Nov 2011 20:39:58 +0100 Subject: [PATCH 1/5] idl: add parser for the to_null property Compile into a ndr_pull_charset_to_null call. Signed-off-by: Jeremy Allison --- pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index 7cda272..2078f58 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -1033,7 +1033,11 @@ sub ParseElementPullLevel if ($l->{IS_ZERO_TERMINATED}) { $self->CheckStringTerminator($ndr, $e, $l, $length); } - $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); + if ($l->{IS_TO_NULL}) { + $self->pidl("NDR_CHECK(ndr_pull_charset_to_null($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); + } else { + $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); + } return; } elsif (has_fast_array($e, $l)) { if ($l->{IS_ZERO_TERMINATED}) { -- 1.7.7.3 From 288be5008a2df48b9dc0240a4464ab593cbaa7ec Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Fri, 13 Jan 2012 16:32:59 -0800 Subject: [PATCH 2/5] ndr: add ndr_pull_charset_to_null() The same as ndr_pull_charset(), however only perform character conversion on bytes prior to and including the null terminator. Signed-off-by: Jeremy Allison --- librpc/ndr/libndr.h | 1 + librpc/ndr/ndr_string.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index 8c59bb9..f4b7db9 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -568,6 +568,7 @@ size_t ndr_size_string_array(const char **a, uint32_t count, int flags); uint32_t ndr_string_length(const void *_var, uint32_t element_size); enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size); enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset); +enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset); enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset); /* GUIDs */ diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c index d750e2c..ea3483a 100644 --- a/librpc/ndr/ndr_string.c +++ b/librpc/ndr/ndr_string.c @@ -694,6 +694,38 @@ _PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, return NDR_ERR_SUCCESS; } +_PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset) +{ + size_t converted_size; + uint32_t str_len; + + if (length == 0) { + *var = talloc_strdup(ndr->current_mem_ctx, ""); + return NDR_ERR_SUCCESS; + } + + if (NDR_BE(ndr) && chset == CH_UTF16) { + chset = CH_UTF16BE; + } + + NDR_PULL_NEED_BYTES(ndr, length*byte_mul); + + str_len = ndr_string_length(ndr->data+ndr->offset, byte_mul); + str_len = MIN(str_len, length); /* overrun protection */ + + if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX, + ndr->data+ndr->offset, str_len*byte_mul, + discard_const_p(void *, var), + &converted_size, false)) + { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul)); + + return NDR_ERR_SUCCESS; +} + _PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset) { ssize_t ret, required; -- 1.7.7.3 From ce3faef4cd7382e14b2fbfc7b3da6636580ba52e Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 13 Nov 2011 20:40:56 +0100 Subject: [PATCH 3/5] idl: add to_null attribute to the spoolss formname array OpenPrinterEx requests have been observed in the wild carrying a device mode formname "A4" followed by non-utf16 garbage after the null terminator. Such requests currently fail during unmarshalling in the ndr_pull_charset() codepath, causing intermittent print job failures. This change ensures that garbage after the device mode formname null terminator is not processed in unmarshalling. https://bugzilla.samba.org/show_bug.cgi?id=8606 Signed-off-by: Jeremy Allison --- librpc/idl/spoolss.idl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/librpc/idl/spoolss.idl b/librpc/idl/spoolss.idl index 4599e3a..4b1f94f 100644 --- a/librpc/idl/spoolss.idl +++ b/librpc/idl/spoolss.idl @@ -697,7 +697,7 @@ cpp_quote("#define spoolss_security_descriptor security_descriptor") uint16 yresolution; spoolss_DeviceModeTTOption ttoption; spoolss_DeviceModeCollate collate; - [charset(UTF16)] uint16 formname[MAXDEVICENAME]; + [charset(UTF16),to_null] uint16 formname[MAXDEVICENAME]; uint16 logpixels; /* reserved */ uint32 bitsperpel; /* reserved */ uint32 pelswidth; /* reserved */ -- 1.7.7.3 From 739f566c4481249dfdfaf2a6b954bf1042fd8c1e Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 23 Nov 2011 02:03:48 +0100 Subject: [PATCH 4/5] idl: add to_null attribute to the spoolss devicename array OpenPrinterEx requests have also been observed in the wild carrying non-utf16 garbage after the device mode devicename field null terminator. Signed-off-by: Jeremy Allison --- librpc/idl/spoolss.idl | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/librpc/idl/spoolss.idl b/librpc/idl/spoolss.idl index 4b1f94f..d888a79 100644 --- a/librpc/idl/spoolss.idl +++ b/librpc/idl/spoolss.idl @@ -678,7 +678,7 @@ cpp_quote("#define spoolss_security_descriptor security_descriptor") const int MAXDEVICENAME = 32; typedef [public,gensize] struct { - [charset(UTF16)] uint16 devicename[MAXDEVICENAME]; + [charset(UTF16),to_null] uint16 devicename[MAXDEVICENAME]; spoolss_DeviceModeSpecVersion specversion; uint16 driverversion; uint16 size; -- 1.7.7.3 From fdd9dc852af17eedcc5d6ba14a991fef4a4d4910 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Fri, 13 Jan 2012 13:51:22 -0800 Subject: [PATCH 5/5] idl: add to_null property to_null specifies that character conversion should only occur until the null pointer in an array based string. Signed-off-by: Jeremy Allison Autobuild-User: Jeremy Allison Autobuild-Date: Sat Jan 14 00:51:54 CET 2012 on sn-devel-104 --- pidl/lib/Parse/Pidl/NDR.pm | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/pidl/lib/Parse/Pidl/NDR.pm b/pidl/lib/Parse/Pidl/NDR.pm index d91c324..71e7228 100644 --- a/pidl/lib/Parse/Pidl/NDR.pm +++ b/pidl/lib/Parse/Pidl/NDR.pm @@ -171,6 +171,7 @@ sub GetElementLevelTable($$$) my $is_string = 0; my $is_fixed = 0; my $is_inline = 0; + my $is_to_null = 0; if ($d eq "*") { $is_conformant = 1; @@ -208,6 +209,10 @@ sub GetElementLevelTable($$$) delete($e->{PROPERTIES}->{string}); } + if (has_property($e, "to_null")) { + $is_to_null = 1; + } + push (@$order, { TYPE => "ARRAY", SIZE_IS => $size, @@ -218,7 +223,8 @@ sub GetElementLevelTable($$$) IS_VARYING => $is_varying, IS_CONFORMANT => $is_conformant, IS_FIXED => $is_fixed, - IS_INLINE => $is_inline + IS_INLINE => $is_inline, + IS_TO_NULL => $is_to_null }); } @@ -1099,6 +1105,7 @@ my %property_list = ( "noheader" => ["ELEMENT"], "charset" => ["ELEMENT"], "length_is" => ["ELEMENT"], + "to_null" => ["ELEMENT"], ); ##################################################################### -- 1.7.7.3