diff options
author | Karolin Seeger <kseeger@samba.org> | 2015-12-16 12:28:23 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2015-12-16 12:28:23 +0100 |
commit | 80a8843b65fb25baa77c0dfceeba1db9e5074baf (patch) | |
tree | 8a60f5e34b3f41633d3909b8fc9b232a33d6dc24 | |
parent | 776eb216f3ab6deb963dd2899f80b2edec63b521 (diff) | |
parent | cd89c8372cbc5868f23094a9b7481be21a89a7e9 (diff) | |
download | samba-80a8843b65fb25baa77c0dfceeba1db9e5074baf.tar.gz |
Merge tag 'samba-4.1.22' into v4-1-test
samba: tag release samba-4.1.22
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | WHATSNEW.txt | 162 | ||||
-rw-r--r-- | lib/ldb/common/ldb_dn.c | 67 | ||||
-rw-r--r-- | lib/ldb/common/ldb_match.c | 33 | ||||
-rwxr-xr-x | lib/ldb/wscript | 5 | ||||
-rw-r--r-- | lib/util/asn1.c | 106 | ||||
-rw-r--r-- | lib/util/charset/charset.h | 9 | ||||
-rw-r--r-- | lib/util/charset/codepoints.c | 29 | ||||
-rw-r--r-- | lib/util/charset/util_str.c | 3 | ||||
-rw-r--r-- | lib/util/charset/util_unistr.c | 6 | ||||
-rw-r--r-- | libcli/ldap/ldap_message.c | 786 | ||||
-rw-r--r-- | libcli/ldap/ldap_message.h | 2 | ||||
-rw-r--r-- | libcli/smb/smbXcli_base.c | 11 | ||||
-rwxr-xr-x | script/autobuild.py | 2 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 7 | ||||
-rw-r--r-- | source3/libsmb/libsmb_server.c | 15 | ||||
-rw-r--r-- | source3/modules/vfs_shadow_copy2.c | 45 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 13 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 24 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_controls.c | 8 |
20 files changed, 808 insertions, 527 deletions
@@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE= # e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes # # -> "3.0.0-SVN-build-199" # ######################################################## -SAMBA_VERSION_IS_GIT_SNAPSHOT=yes +SAMBA_VERSION_IS_GIT_SNAPSHOT=no ######################################################## # This is for specifying a release nickname # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 1c01e2b54b9..2cd1a200f9a 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,4 +1,162 @@ ============================== + Release Notes for Samba 4.1.22 + December 16, 2015 + ============================== + + +This is a security release in order to address the following CVEs: + +o CVE-2015-7540 (Remote DoS in Samba (AD) LDAP server) +o CVE-2015-3223 (Denial of service in Samba Active Directory + server) +o CVE-2015-5252 (Insufficient symlink verification in smbd) +o CVE-2015-5299 (Missing access control check in shadow copy + code) +o CVE-2015-5296 (Samba client requesting encryption vulnerable + to downgrade attack) +o CVE-2015-8467 (Denial of service attack against Windows + Active Directory server) +o CVE-2015-5330 (Remote memory read in Samba LDAP server) + +Please note that if building against a system libldb, the required +version has been bumped to ldb-1.1.24. This is needed to ensure +we build against a system ldb library that contains the fixes +for CVE-2015-5330 and CVE-2015-3223. + +======= +Details +======= + +o CVE-2015-7540: + All versions of Samba from 4.0.0 to 4.1.21 inclusive are vulnerable to + an anonymous memory exhaustion attack in the samba daemon LDAP server. + + A malicious client can send packets that cause the LDAP server provided + by the AD DC in the samba daemon process to consume unlimited memory + and be terminated. + +o CVE-2015-3223: + All versions of Samba from 4.0.0 to 4.3.2 inclusive (resp. all + ldb versions up to 1.1.23 inclusive) are vulnerable to + a denial of service attack in the samba daemon LDAP server. + + A malicious client can send packets that cause the LDAP server in the + samba daemon process to become unresponsive, preventing the server + from servicing any other requests. + + This flaw is not exploitable beyond causing the code to loop expending + CPU resources. + +o CVE-2015-5252: + All versions of Samba from 3.0.0 to 4.3.2 inclusive are vulnerable to + a bug in symlink verification, which under certain circumstances could + allow client access to files outside the exported share path. + + If a Samba share is configured with a path that shares a common path + prefix with another directory on the file system, the smbd daemon may + allow the client to follow a symlink pointing to a file or directory + in that other directory, even if the share parameter "wide links" is + set to "no" (the default). + +o CVE-2015-5299: + All versions of Samba from 3.2.0 to 4.3.2 inclusive are vulnerable to + a missing access control check in the vfs_shadow_copy2 module. When + looking for the shadow copy directory under the share path the current + accessing user should have DIRECTORY_LIST access rights in order to + view the current snapshots. + + This was not being checked in the affected versions of Samba. + +o CVE-2015-5296: + Versions of Samba from 3.2.0 to 4.3.2 inclusive do not ensure that + signing is negotiated when creating an encrypted client connection to + a server. + + Without this a man-in-the-middle attack could downgrade the connection + and connect using the supplied credentials as an unsigned, unencrypted + connection. + +o CVE-2015-8467: + Samba, operating as an AD DC, is sometimes operated in a domain with a + mix of Samba and Windows Active Directory Domain Controllers. + + All versions of Samba from 4.0.0 to 4.3.2 inclusive, when deployed as + an AD DC in the same domain with Windows DCs, could be used to + override the protection against the MS15-096 / CVE-2015-2535 security + issue in Windows. + + Prior to MS16-096 it was possible to bypass the quota of machine + accounts a non-administrative user could create. Pure Samba domains + are not impacted, as Samba does not implement the + SeMachineAccountPrivilege functionality to allow non-administrator + users to create new computer objects. + +o CVE-2015-5330: + All versions of Samba from 4.0.0 to 4.3.2 inclusive (resp. all + ldb versions up to 1.1.23 inclusive) are vulnerable to + a remote memory read attack in the samba daemon LDAP server. + + A malicious client can send packets that cause the LDAP server in the + samba daemon process to return heap memory beyond the length of the + requested value. + + This memory may contain data that the client should not be allowed to + see, allowing compromise of the server. + + The memory may either be returned to the client in an error string, or + stored in the database by a suitabily privileged user. If untrusted + users can create objects in your database, please confirm that all DN + and name attributes are reasonable. + + +Changes since 4.1.21: +--------------------- + +o Andrew Bartlett <abartlet@samba.org> + * BUG 11552: CVE-2015-8467: samdb: Match MS15-096 behaviour for + userAccountControl. + +o Jeremy Allison <jra@samba.org> + * BUG 9187: CVE-2015-7540: Bogus LDAP request cause samba to use all the + memory and be ookilled. + * BUG 11325: CVE-2015-3223: Fix LDAP \00 search expression attack DoS. + * BUG 11395: CVE-2015-5252: Fix insufficient symlink verification (file + access outside the share). + * BUG 11529: CVE-2015-5299: s3-shadow-copy2: Fix missing access check on + snapdir. + +o Douglas Bagnall <douglas.bagnall@catalyst.net.nz> + * BUG 11599: CVE-2015-5330: Fix remote read memory exploit in LDB. + +o Stefan Metzmacher <metze@samba.org> + * BUG 11536: CVE-2015-5296: Add man in the middle protection when forcing + smb encryption on the client side. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the "Samba 4.1 and newer" product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + + ============================== Release Notes for Samba 4.1.21 October 13, 2015 ============================== @@ -35,10 +193,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- -====================================================================== ============================== Release Notes for Samba 4.1.20 diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index 6b6f90c13ea..cd17cda3aad 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -189,33 +189,23 @@ struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, /* see RFC2253 section 2.4 */ static int ldb_dn_escape_internal(char *dst, const char *src, int len) { - const char *p, *s; + char c; char *d; - size_t l; - - p = s = src; + int i; d = dst; - while (p - src < len) { - p += strcspn(p, ",=\n\r+<>#;\\\" "); - - if (p - src == len) /* found no escapable chars */ - break; - - /* copy the part of the string before the stop */ - memcpy(d, s, p - s); - d += (p - s); /* move to current position */ - - switch (*p) { + for (i = 0; i < len; i++){ + c = src[i]; + switch (c) { case ' ': - if (p == src || (p-src)==(len-1)) { + if (i == 0 || i == len - 1) { /* if at the beginning or end * of the string then escape */ *d++ = '\\'; - *d++ = *p++; + *d++ = c; } else { /* otherwise don't escape */ - *d++ = *p++; + *d++ = c; } break; @@ -231,36 +221,36 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len) case '?': /* these must be escaped using \c form */ *d++ = '\\'; - *d++ = *p++; + *d++ = c; break; - default: { + case ';': + case '\r': + case '\n': + case '=': + case '\0': { /* any others get \XX form */ unsigned char v; const char *hexbytes = "0123456789ABCDEF"; - v = *(const unsigned char *)p; + v = (const unsigned char)c; *d++ = '\\'; *d++ = hexbytes[v>>4]; *d++ = hexbytes[v&0xF]; - p++; break; } + default: + *d++ = c; } - s = p; /* move forward */ } - /* copy the last part (with zero) and return */ - l = len - (s - src); - memcpy(d, s, l + 1); - /* return the length of the resulting string */ - return (l + (d - dst)); + return (d - dst); } char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value) { char *dst; - + size_t len; if (!value.length) return NULL; @@ -271,10 +261,14 @@ char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value) return NULL; } - ldb_dn_escape_internal(dst, (const char *)value.data, value.length); - - dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1); + len = ldb_dn_escape_internal(dst, (const char *)value.data, value.length); + dst = talloc_realloc(mem_ctx, dst, char, len + 1); + if ( ! dst) { + talloc_free(dst); + return NULL; + } + dst[len] = '\0'; return dst; } @@ -592,12 +586,15 @@ static bool ldb_dn_explode(struct ldb_dn *dn) p++; *d++ = '\0'; - dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt); + dn->components[dn->comp_num].value.data = \ + (uint8_t *)talloc_memdup(dn->components, dt, l + 1); dn->components[dn->comp_num].value.length = l; if ( ! dn->components[dn->comp_num].value.data) { /* ouch ! */ goto failed; } + talloc_set_name_const(dn->components[dn->comp_num].value.data, + (const char *)dn->components[dn->comp_num].value.data); dt = d; @@ -713,11 +710,13 @@ static bool ldb_dn_explode(struct ldb_dn *dn) *d++ = '\0'; dn->components[dn->comp_num].value.length = l; dn->components[dn->comp_num].value.data = - (uint8_t *)talloc_strdup(dn->components, dt); + (uint8_t *)talloc_memdup(dn->components, dt, l + 1); if ( ! dn->components[dn->comp_num].value.data) { /* ouch */ goto failed; } + talloc_set_name_const(dn->components[dn->comp_num].value.data, + (const char *)dn->components[dn->comp_num].value.data); dn->comp_num++; diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index 7918aec65f1..0f5c5b51440 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -240,7 +240,6 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, struct ldb_val val; struct ldb_val cnk; struct ldb_val *chunk; - char *p, *g; uint8_t *save_p = NULL; unsigned int c = 0; @@ -270,6 +269,14 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, if (cnk.length > val.length) { goto mismatch; } + /* + * Empty strings are returned as length 0. Ensure + * we can cope with this. + */ + if (cnk.length == 0) { + goto mismatch; + } + if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch; val.length -= cnk.length; val.data += cnk.length; @@ -279,20 +286,36 @@ static int ldb_wildcard_compare(struct ldb_context *ldb, } while (tree->u.substring.chunks[c]) { + uint8_t *p; chunk = tree->u.substring.chunks[c]; if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; - /* FIXME: case of embedded nulls */ - p = strstr((char *)val.data, (char *)cnk.data); + /* + * Empty strings are returned as length 0. Ensure + * we can cope with this. + */ + if (cnk.length == 0) { + goto mismatch; + } + /* + * Values might be binary blobs. Don't use string + * search, but memory search instead. + */ + p = memmem((const void *)val.data,val.length, + (const void *)cnk.data, cnk.length); if (p == NULL) goto mismatch; if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { + uint8_t *g; do { /* greedy */ - g = strstr((char *)p + cnk.length, (char *)cnk.data); + g = memmem(p + cnk.length, + val.length - (p - val.data), + (const uint8_t *)cnk.data, + cnk.length); if (g) p = g; } while(g); } - val.length = val.length - (p - (char *)(val.data)) - cnk.length; + val.length = val.length - (p - (uint8_t *)(val.data)) - cnk.length; val.data = (uint8_t *)(p + cnk.length); c++; talloc_free(cnk.data); diff --git a/lib/ldb/wscript b/lib/ldb/wscript index fb32ecdea87..794d6db7934 100755 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -2,6 +2,7 @@ APPNAME = 'ldb' VERSION = '1.1.17' +SYSTEM_VERSION = '1.1.24' blddir = 'bin' @@ -46,11 +47,11 @@ def configure(conf): conf.env.standalone_ldb = conf.IN_LAUNCH_DIR() if not conf.env.standalone_ldb: - if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', minversion=VERSION, + if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', minversion=SYSTEM_VERSION, onlyif='talloc tdb tevent', implied_deps='replace talloc tdb tevent'): conf.define('USING_SYSTEM_LDB', 1) - if conf.CHECK_BUNDLED_SYSTEM_PKG('pyldb-util', minversion=VERSION, + if conf.CHECK_BUNDLED_SYSTEM_PKG('pyldb-util', minversion=SYSTEM_VERSION, onlyif='talloc tdb tevent ldb', implied_deps='replace talloc tdb tevent ldb'): conf.define('USING_SYSTEM_PYLDB_UTIL', 1) diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 70637a3e065..ec294503b59 100644 --- a/lib/util/asn1.c +++ b/lib/util/asn1.c @@ -326,87 +326,76 @@ bool asn1_write_OID(struct asn1_data *data, const char *OID) /* write an octet string */ bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length) { - asn1_push_tag(data, ASN1_OCTET_STRING); - asn1_write(data, p, length); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_push_tag(data, ASN1_OCTET_STRING)) return false; + if (!asn1_write(data, p, length)) return false; + return asn1_pop_tag(data); } /* write a LDAP string */ bool asn1_write_LDAPString(struct asn1_data *data, const char *s) { - asn1_write(data, s, strlen(s)); - return !data->has_error; + return asn1_write(data, s, strlen(s)); } /* write a LDAP string from a DATA_BLOB */ bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s) { - asn1_write(data, s->data, s->length); - return !data->has_error; + return asn1_write(data, s->data, s->length); } /* write a general string */ bool asn1_write_GeneralString(struct asn1_data *data, const char *s) { - asn1_push_tag(data, ASN1_GENERAL_STRING); - asn1_write_LDAPString(data, s); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_push_tag(data, ASN1_GENERAL_STRING)) return false; + if (!asn1_write_LDAPString(data, s)) return false; + return asn1_pop_tag(data); } bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num)); - asn1_write(data, blob->data, blob->length); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; + if (!asn1_write(data, blob->data, blob->length)) return false; + return asn1_pop_tag(data); } /* write a BOOLEAN */ bool asn1_write_BOOLEAN(struct asn1_data *data, bool v) { - asn1_push_tag(data, ASN1_BOOLEAN); - asn1_write_uint8(data, v ? 0xFF : 0); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_push_tag(data, ASN1_BOOLEAN)) return false; + if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false; + return asn1_pop_tag(data); } bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v) { uint8_t tmp = 0; - asn1_start_tag(data, ASN1_BOOLEAN); - asn1_read_uint8(data, &tmp); + if (!asn1_start_tag(data, ASN1_BOOLEAN)) return false; + *v = false; + if (!asn1_read_uint8(data, &tmp)) return false; if (tmp == 0xFF) { *v = true; - } else { - *v = false; } - asn1_end_tag(data); - return !data->has_error; + return asn1_end_tag(data); } /* write a BOOLEAN in a simple context */ bool asn1_write_BOOLEAN_context(struct asn1_data *data, bool v, int context) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context)); - asn1_write_uint8(data, v ? 0xFF : 0); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false; + if (!asn1_write_uint8(data, v ? 0xFF : 0)) return false; + return asn1_pop_tag(data); } bool asn1_read_BOOLEAN_context(struct asn1_data *data, bool *v, int context) { uint8_t tmp = 0; - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context)); - asn1_read_uint8(data, &tmp); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(context))) return false; + *v = false; + if (!asn1_read_uint8(data, &tmp)) return false; if (tmp == 0xFF) { *v = true; - } else { - *v = false; } - asn1_end_tag(data); - return !data->has_error; + return asn1_end_tag(data); } /* check a BOOLEAN */ @@ -414,12 +403,12 @@ bool asn1_check_BOOLEAN(struct asn1_data *data, bool v) { uint8_t b = 0; - asn1_read_uint8(data, &b); + if (!asn1_read_uint8(data, &b)) return false; if (b != ASN1_BOOLEAN) { data->has_error = true; return false; } - asn1_read_uint8(data, &b); + if (!asn1_read_uint8(data, &b)) return false; if (b != v) { data->has_error = true; return false; @@ -770,9 +759,8 @@ bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **OID) return false; } - asn1_read(data, blob.data, len); - asn1_end_tag(data); - if (data->has_error) { + if (!asn1_read(data, blob.data, len)) return false; + if (!asn1_end_tag(data)) { data_blob_free(&blob); return false; } @@ -817,9 +805,8 @@ bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s) data->has_error = true; return false; } - asn1_read(data, *s, len); (*s)[len] = 0; - return !data->has_error; + return asn1_read(data, *s, len); } @@ -848,17 +835,17 @@ bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLO data->has_error = true; return false; } - asn1_read(data, blob->data, len); - asn1_end_tag(data); + if (!asn1_read(data, blob->data, len)) goto err; + if (!asn1_end_tag(data)) goto err; blob->length--; blob->data[len] = 0; - - if (data->has_error) { - data_blob_free(blob); - *blob = data_blob_null; - return false; - } return true; + + err: + + data_blob_free(blob); + *blob = data_blob_null; + return false; } bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob) @@ -876,9 +863,8 @@ bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blo data->has_error = true; return false; } - asn1_read(data, blob->data, len); - asn1_end_tag(data); - return !data->has_error; + if (!asn1_read(data, blob->data, len)) return false; + return asn1_end_tag(data); } /* read an integer without tag*/ @@ -966,8 +952,8 @@ bool asn1_check_enumerated(struct asn1_data *data, int v) { uint8_t b; if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; - asn1_read_uint8(data, &b); - asn1_end_tag(data); + if (!asn1_read_uint8(data, &b)) return false; + if (!asn1_end_tag(data)) return false; if (v != b) data->has_error = false; @@ -979,9 +965,8 @@ bool asn1_check_enumerated(struct asn1_data *data, int v) bool asn1_write_enumerated(struct asn1_data *data, uint8_t v) { if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false; - asn1_write_uint8(data, v); - asn1_pop_tag(data); - return !data->has_error; + if (!asn1_write_uint8(data, v)) return false; + return asn1_pop_tag(data); } /* @@ -1022,8 +1007,7 @@ NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size) asn1->data = blob.data; asn1->length = blob.length; - asn1_start_tag(asn1, tag); - if (asn1->has_error) { + if (!asn1_start_tag(asn1, tag)) { talloc_free(asn1); return STATUS_MORE_ENTRIES; } diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index e4297e4f3ce..060f1cf56f7 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -171,15 +171,16 @@ smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic, charset_t from, charset_t to); const char *charset_name(struct smb_iconv_handle *ic, charset_t ch); -codepoint_t next_codepoint_ext(const char *str, charset_t src_charset, - size_t *size); +codepoint_t next_codepoint_ext(const char *str, size_t len, + charset_t src_charset, size_t *size); codepoint_t next_codepoint(const char *str, size_t *size); ssize_t push_codepoint(char *str, codepoint_t c); /* codepoints */ codepoint_t next_codepoint_handle_ext(struct smb_iconv_handle *ic, - const char *str, charset_t src_charset, - size_t *size); + const char *str, size_t len, + charset_t src_charset, + size_t *size); codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic, const char *str, size_t *size); ssize_t push_codepoint_handle(struct smb_iconv_handle *ic, diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c index 0984164d483..19d084f3d4a 100644 --- a/lib/util/charset/codepoints.c +++ b/lib/util/charset/codepoints.c @@ -319,7 +319,8 @@ smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic, */ _PUBLIC_ codepoint_t next_codepoint_handle_ext( struct smb_iconv_handle *ic, - const char *str, charset_t src_charset, + const char *str, size_t len, + charset_t src_charset, size_t *bytes_consumed) { /* it cannot occupy more than 4 bytes in UTF16 format */ @@ -330,7 +331,10 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext( size_t olen; char *outbuf; - if ((str[0] & 0x80) == 0) { + + if (((str[0] & 0x80) == 0) && (src_charset == CH_DOS || + src_charset == CH_UNIX || + src_charset == CH_UTF8)) { *bytes_consumed = 1; return (codepoint_t)str[0]; } @@ -339,7 +343,7 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext( * we assume that no multi-byte character can take more than 5 bytes. * This is OK as we only support codepoints up to 1M (U+100000) */ - ilen_orig = strnlen(str, 5); + ilen_orig = MIN(len, 5); ilen = ilen_orig; descriptor = get_conv_handle(ic, src_charset, CH_UTF16); @@ -395,9 +399,16 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext( return INVALID_CODEPOINT if the next character cannot be converted */ _PUBLIC_ codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic, - const char *str, size_t *size) + const char *str, size_t *size) { - return next_codepoint_handle_ext(ic, str, CH_UNIX, size); + /* + * We assume that no multi-byte character can take more than 5 bytes + * thus avoiding walking all the way down a long string. This is OK as + * Unicode codepoints only go up to (U+10ffff), which can always be + * encoded in 4 bytes or less. + */ + return next_codepoint_handle_ext(ic, str, strnlen(str, 5), CH_UNIX, + size); } /* @@ -459,11 +470,11 @@ _PUBLIC_ ssize_t push_codepoint_handle(struct smb_iconv_handle *ic, return 5 - olen; } -_PUBLIC_ codepoint_t next_codepoint_ext(const char *str, charset_t src_charset, - size_t *size) +_PUBLIC_ codepoint_t next_codepoint_ext(const char *str, size_t len, + charset_t src_charset, size_t *size) { - return next_codepoint_handle_ext(get_iconv_handle(), str, - src_charset, size); + return next_codepoint_handle_ext(get_iconv_handle(), str, len, + src_charset, size); } _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size) diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c index d2e6cbbc620..2653bfc2d81 100644 --- a/lib/util/charset/util_str.c +++ b/lib/util/charset/util_str.c @@ -210,7 +210,8 @@ _PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic, while (*s) { size_t c_size; - codepoint_t c = next_codepoint_handle_ext(ic, s, src_charset, &c_size); + codepoint_t c = next_codepoint_handle_ext(ic, s, strnlen(s, 5), + src_charset, &c_size); s += c_size; switch (dst_charset) { diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index e4ae65053c7..2cc87186dae 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -110,10 +110,12 @@ _PUBLIC_ char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle, return NULL; } - while (n-- && *src) { + while (n && *src) { size_t c_size; - codepoint_t c = next_codepoint_handle(iconv_handle, src, &c_size); + codepoint_t c = next_codepoint_handle_ext(iconv_handle, src, n, + CH_UNIX, &c_size); src += c_size; + n -= c_size; c = toupper_m(c); diff --git a/libcli/ldap/ldap_message.c b/libcli/ldap/ldap_message.c index 1c5542c0d90..ba94f4ccfac 100644 --- a/libcli/ldap/ldap_message.c +++ b/libcli/ldap/ldap_message.c @@ -229,31 +229,31 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree switch (tree->operation) { case LDB_OP_AND: case LDB_OP_OR: - asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1)); + if (!asn1_push_tag(data, ASN1_CONTEXT(tree->operation==LDB_OP_AND?0:1))) return false; for (i=0; i<tree->u.list.num_elements; i++) { if (!ldap_push_filter(data, tree->u.list.elements[i])) { return false; } } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_NOT: - asn1_push_tag(data, ASN1_CONTEXT(2)); + if (!asn1_push_tag(data, ASN1_CONTEXT(2))) return false; if (!ldap_push_filter(data, tree->u.isnot.child)) { return false; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_EQUALITY: /* equality test */ - asn1_push_tag(data, ASN1_CONTEXT(3)); - asn1_write_OctetString(data, tree->u.equality.attr, - strlen(tree->u.equality.attr)); - asn1_write_OctetString(data, tree->u.equality.value.data, - tree->u.equality.value.length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false; + if (!asn1_write_OctetString(data, tree->u.equality.attr, + strlen(tree->u.equality.attr))) return false; + if (!asn1_write_OctetString(data, tree->u.equality.value.data, + tree->u.equality.value.length)) return false; + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_SUBSTRING: @@ -266,16 +266,16 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree any [1] LDAPString, final [2] LDAPString } } */ - asn1_push_tag(data, ASN1_CONTEXT(4)); - asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr)); - asn1_push_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_push_tag(data, ASN1_CONTEXT(4))) return false; + if (!asn1_write_OctetString(data, tree->u.substring.attr, strlen(tree->u.substring.attr))) return false; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) return false; if (tree->u.substring.chunks && tree->u.substring.chunks[0]) { i = 0; if (!tree->u.substring.start_with_wildcard) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0)); - asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) return false; + if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false; + if (!asn1_pop_tag(data)) return false; i++; } while (tree->u.substring.chunks[i]) { @@ -287,51 +287,51 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree } else { ctx = 1; } - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx)); - asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i]); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(ctx))) return false; + if (!asn1_write_DATA_BLOB_LDAPString(data, tree->u.substring.chunks[i])) return false; + if (!asn1_pop_tag(data)) return false; i++; } } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) return false; + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_GREATER: /* greaterOrEqual test */ - asn1_push_tag(data, ASN1_CONTEXT(5)); - asn1_write_OctetString(data, tree->u.comparison.attr, - strlen(tree->u.comparison.attr)); - asn1_write_OctetString(data, tree->u.comparison.value.data, - tree->u.comparison.value.length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT(5))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.attr, + strlen(tree->u.comparison.attr))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.value.data, + tree->u.comparison.value.length)) return false; + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_LESS: /* lessOrEqual test */ - asn1_push_tag(data, ASN1_CONTEXT(6)); - asn1_write_OctetString(data, tree->u.comparison.attr, - strlen(tree->u.comparison.attr)); - asn1_write_OctetString(data, tree->u.comparison.value.data, - tree->u.comparison.value.length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT(6))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.attr, + strlen(tree->u.comparison.attr))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.value.data, + tree->u.comparison.value.length)) return false; + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_PRESENT: /* present test */ - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7)); - asn1_write_LDAPString(data, tree->u.present.attr); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(7))) return false; + if (!asn1_write_LDAPString(data, tree->u.present.attr)) return false; + if (!asn1_pop_tag(data)) return false; return !data->has_error; case LDB_OP_APPROX: /* approx test */ - asn1_push_tag(data, ASN1_CONTEXT(8)); - asn1_write_OctetString(data, tree->u.comparison.attr, - strlen(tree->u.comparison.attr)); - asn1_write_OctetString(data, tree->u.comparison.value.data, - tree->u.comparison.value.length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT(8))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.attr, + strlen(tree->u.comparison.attr))) return false; + if (!asn1_write_OctetString(data, tree->u.comparison.value.data, + tree->u.comparison.value.length)) return false; + if (!asn1_pop_tag(data)) return false; break; case LDB_OP_EXTENDED: @@ -343,24 +343,24 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree dnAttributes [4] BOOLEAN DEFAULT FALSE } */ - asn1_push_tag(data, ASN1_CONTEXT(9)); + if (!asn1_push_tag(data, ASN1_CONTEXT(9))) return false; if (tree->u.extended.rule_id) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1)); - asn1_write_LDAPString(data, tree->u.extended.rule_id); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) return false; + if (!asn1_write_LDAPString(data, tree->u.extended.rule_id)) return false; + if (!asn1_pop_tag(data)) return false; } if (tree->u.extended.attr) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2)); - asn1_write_LDAPString(data, tree->u.extended.attr); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(2))) return false; + if (!asn1_write_LDAPString(data, tree->u.extended.attr)) return false; + if (!asn1_pop_tag(data)) return false; } - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3)); - asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value); - asn1_pop_tag(data); - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4)); - asn1_write_uint8(data, tree->u.extended.dnAttributes); - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(3))) return false; + if (!asn1_write_DATA_BLOB_LDAPString(data, &tree->u.extended.value)) return false; + if (!asn1_pop_tag(data)) return false; + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(4))) return false; + if (!asn1_write_uint8(data, tree->u.extended.dnAttributes)) return false; + if (!asn1_pop_tag(data)) return false; + if (!asn1_pop_tag(data)) return false; break; default: @@ -369,20 +369,21 @@ static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree return !data->has_error; } -static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result) +static bool ldap_encode_response(struct asn1_data *data, struct ldap_Result *result) { - asn1_write_enumerated(data, result->resultcode); - asn1_write_OctetString(data, result->dn, - (result->dn) ? strlen(result->dn) : 0); - asn1_write_OctetString(data, result->errormessage, + if (!asn1_write_enumerated(data, result->resultcode)) return false; + if (!asn1_write_OctetString(data, result->dn, + (result->dn) ? strlen(result->dn) : 0)) return false; + if (!asn1_write_OctetString(data, result->errormessage, (result->errormessage) ? - strlen(result->errormessage) : 0); + strlen(result->errormessage) : 0)) return false; if (result->referral) { - asn1_push_tag(data, ASN1_CONTEXT(3)); - asn1_write_OctetString(data, result->referral, - strlen(result->referral)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT(3))) return false; + if (!asn1_write_OctetString(data, result->referral, + strlen(result->referral))) return false; + if (!asn1_pop_tag(data)) return false; } + return true; } _PUBLIC_ bool ldap_encode(struct ldap_message *msg, @@ -394,286 +395,286 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg, if (!data) return false; - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_Integer(data, msg->messageid); + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_Integer(data, msg->messageid)) goto err; switch (msg->type) { case LDAP_TAG_BindRequest: { struct ldap_BindRequest *r = &msg->r.BindRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_Integer(data, r->version); - asn1_write_OctetString(data, r->dn, - (r->dn != NULL) ? strlen(r->dn) : 0); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_Integer(data, r->version)) goto err; + if (!asn1_write_OctetString(data, r->dn, + (r->dn != NULL) ? strlen(r->dn) : 0)) goto err; switch (r->mechanism) { case LDAP_AUTH_MECH_SIMPLE: /* context, primitive */ - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0)); - asn1_write(data, r->creds.password, - strlen(r->creds.password)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err; + if (!asn1_write(data, r->creds.password, + strlen(r->creds.password))) goto err; + if (!asn1_pop_tag(data)) goto err; break; case LDAP_AUTH_MECH_SASL: /* context, constructed */ - asn1_push_tag(data, ASN1_CONTEXT(3)); - asn1_write_OctetString(data, r->creds.SASL.mechanism, - strlen(r->creds.SASL.mechanism)); + if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err; + if (!asn1_write_OctetString(data, r->creds.SASL.mechanism, + strlen(r->creds.SASL.mechanism))) goto err; if (r->creds.SASL.secblob) { - asn1_write_OctetString(data, r->creds.SASL.secblob->data, - r->creds.SASL.secblob->length); + if (!asn1_write_OctetString(data, r->creds.SASL.secblob->data, + r->creds.SASL.secblob->length)) goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; default: - return false; + goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_BindResponse: { struct ldap_BindResponse *r = &msg->r.BindResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, &r->response); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, &r->response)) goto err; if (r->SASL.secblob) { - asn1_write_ContextSimple(data, 7, r->SASL.secblob); + if (!asn1_write_ContextSimple(data, 7, r->SASL.secblob)) goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_UnbindRequest: { /* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */ - asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_SearchRequest: { struct ldap_SearchRequest *r = &msg->r.SearchRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->basedn, strlen(r->basedn)); - asn1_write_enumerated(data, r->scope); - asn1_write_enumerated(data, r->deref); - asn1_write_Integer(data, r->sizelimit); - asn1_write_Integer(data, r->timelimit); - asn1_write_BOOLEAN(data, r->attributesonly); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->basedn, strlen(r->basedn))) goto err; + if (!asn1_write_enumerated(data, r->scope)) goto err; + if (!asn1_write_enumerated(data, r->deref)) goto err; + if (!asn1_write_Integer(data, r->sizelimit)) goto err; + if (!asn1_write_Integer(data, r->timelimit)) goto err; + if (!asn1_write_BOOLEAN(data, r->attributesonly)) goto err; if (!ldap_push_filter(data, r->tree)) { - return false; + goto err; } - asn1_push_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; for (i=0; i<r->num_attributes; i++) { - asn1_write_OctetString(data, r->attributes[i], - strlen(r->attributes[i])); + if (!asn1_write_OctetString(data, r->attributes[i], + strlen(r->attributes[i]))) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_SearchResultEntry: { struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->dn, strlen(r->dn)); - asn1_push_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; for (i=0; i<r->num_attributes; i++) { struct ldb_message_element *attr = &r->attributes[i]; - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_OctetString(data, attr->name, - strlen(attr->name)); - asn1_push_tag(data, ASN1_SEQUENCE(1)); + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_OctetString(data, attr->name, + strlen(attr->name))) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(1))) goto err; for (j=0; j<attr->num_values; j++) { - asn1_write_OctetString(data, + if (!asn1_write_OctetString(data, attr->values[j].data, - attr->values[j].length); + attr->values[j].length)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_SearchResultDone: { struct ldap_Result *r = &msg->r.SearchResultDone; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ModifyRequest: { struct ldap_ModifyRequest *r = &msg->r.ModifyRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->dn, strlen(r->dn)); - asn1_push_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; for (i=0; i<r->num_mods; i++) { struct ldb_message_element *attrib = &r->mods[i].attrib; - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_enumerated(data, r->mods[i].type); - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_OctetString(data, attrib->name, - strlen(attrib->name)); - asn1_push_tag(data, ASN1_SET); + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_enumerated(data, r->mods[i].type)) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_OctetString(data, attrib->name, + strlen(attrib->name))) goto err; + if (!asn1_push_tag(data, ASN1_SET)) goto err; for (j=0; j<attrib->num_values; j++) { - asn1_write_OctetString(data, + if (!asn1_write_OctetString(data, attrib->values[j].data, - attrib->values[j].length); + attrib->values[j].length)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ModifyResponse: { struct ldap_Result *r = &msg->r.ModifyResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_AddRequest: { struct ldap_AddRequest *r = &msg->r.AddRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->dn, strlen(r->dn)); - asn1_push_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; for (i=0; i<r->num_attributes; i++) { struct ldb_message_element *attrib = &r->attributes[i]; - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_OctetString(data, attrib->name, - strlen(attrib->name)); - asn1_push_tag(data, ASN1_SET); + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_OctetString(data, attrib->name, + strlen(attrib->name))) goto err; + if (!asn1_push_tag(data, ASN1_SET)) goto err; for (j=0; j<r->attributes[i].num_values; j++) { - asn1_write_OctetString(data, + if (!asn1_write_OctetString(data, attrib->values[j].data, - attrib->values[j].length); + attrib->values[j].length)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_AddResponse: { struct ldap_Result *r = &msg->r.AddResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_DelRequest: { struct ldap_DelRequest *r = &msg->r.DelRequest; - asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type)); - asn1_write(data, r->dn, strlen(r->dn)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err; + if (!asn1_write(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_DelResponse: { struct ldap_Result *r = &msg->r.DelResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ModifyDNRequest: { struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->dn, strlen(r->dn)); - asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn)); - asn1_write_BOOLEAN(data, r->deleteolddn); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_write_OctetString(data, r->newrdn, strlen(r->newrdn))) goto err; + if (!asn1_write_BOOLEAN(data, r->deleteolddn)) goto err; if (r->newsuperior) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0)); - asn1_write(data, r->newsuperior, - strlen(r->newsuperior)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err; + if (!asn1_write(data, r->newsuperior, + strlen(r->newsuperior))) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ModifyDNResponse: { struct ldap_Result *r = &msg->r.ModifyDNResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_CompareRequest: { struct ldap_CompareRequest *r = &msg->r.CompareRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->dn, strlen(r->dn)); - asn1_push_tag(data, ASN1_SEQUENCE(0)); - asn1_write_OctetString(data, r->attribute, - strlen(r->attribute)); - asn1_write_OctetString(data, r->value.data, - r->value.length); - asn1_pop_tag(data); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->dn, strlen(r->dn))) goto err; + if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err; + if (!asn1_write_OctetString(data, r->attribute, + strlen(r->attribute))) goto err; + if (!asn1_write_OctetString(data, r->value.data, + r->value.length)) goto err; + if (!asn1_pop_tag(data)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_CompareResponse: { struct ldap_Result *r = &msg->r.ModifyDNResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, r); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, r)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_AbandonRequest: { struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; - asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type)); - asn1_write_implicit_Integer(data, r->messageid); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION_SIMPLE(msg->type))) goto err; + if (!asn1_write_implicit_Integer(data, r->messageid)) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_SearchResultReference: { struct ldap_SearchResRef *r = &msg->r.SearchResultReference; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_write_OctetString(data, r->referral, strlen(r->referral)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_write_OctetString(data, r->referral, strlen(r->referral))) goto err; + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ExtendedRequest: { struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0)); - asn1_write(data, r->oid, strlen(r->oid)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto err; + if (!asn1_write(data, r->oid, strlen(r->oid))) goto err; + if (!asn1_pop_tag(data)) goto err; if (r->value) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1)); - asn1_write(data, r->value->data, r->value->length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto err; + if (!asn1_write(data, r->value->data, r->value->length)) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; } case LDAP_TAG_ExtendedResponse: { struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse; - asn1_push_tag(data, ASN1_APPLICATION(msg->type)); - ldap_encode_response(data, &r->response); + if (!asn1_push_tag(data, ASN1_APPLICATION(msg->type))) goto err; + if (!ldap_encode_response(data, &r->response)) goto err; if (r->oid) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10)); - asn1_write(data, r->oid, strlen(r->oid)); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(10))) goto err; + if (!asn1_write(data, r->oid, strlen(r->oid))) goto err; + if (!asn1_pop_tag(data)) goto err; } if (r->value) { - asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11)); - asn1_write(data, r->value->data, r->value->length); - asn1_pop_tag(data); + if (!asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(11))) goto err; + if (!asn1_write(data, r->value->data, r->value->length)) goto err; + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; break; } default: - return false; + goto err; } if (msg->controls != NULL) { - asn1_push_tag(data, ASN1_CONTEXT(0)); + if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err; for (i = 0; msg->controls[i] != NULL; i++) { if (!ldap_encode_control(mem_ctx, data, @@ -681,23 +682,24 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg, msg->controls[i])) { DEBUG(0,("Unable to encode control %s\n", msg->controls[i]->oid)); - return false; + goto err; } } - asn1_pop_tag(data); + if (!asn1_pop_tag(data)) goto err; } - asn1_pop_tag(data); - - if (data->has_error) { - asn1_free(data); - return false; - } + if (!asn1_pop_tag(data)) goto err; *result = data_blob_talloc(mem_ctx, data->data, data->length); asn1_free(data); + return true; + + err: + + asn1_free(data); + return false; } static const char *blob2string_talloc(TALLOC_CTX *mem_ctx, @@ -721,20 +723,21 @@ bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx, return true; } -static void ldap_decode_response(TALLOC_CTX *mem_ctx, +static bool ldap_decode_response(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldap_Result *result) { - asn1_read_enumerated(data, &result->resultcode); - asn1_read_OctetString_talloc(mem_ctx, data, &result->dn); - asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage); + if (!asn1_read_enumerated(data, &result->resultcode)) return false; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->dn)) return false; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage)) return false; if (asn1_peek_tag(data, ASN1_CONTEXT(3))) { - asn1_start_tag(data, ASN1_CONTEXT(3)); - asn1_read_OctetString_talloc(mem_ctx, data, &result->referral); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT(3))) return false; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &result->referral)) return false; + if (!asn1_end_tag(data)) return false; } else { result->referral = NULL; } + return true; } static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value) @@ -835,10 +838,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, const char *attrib; DATA_BLOB value; - asn1_start_tag(data, ASN1_CONTEXT(filter_tag)); - asn1_read_OctetString_talloc(mem_ctx, data, &attrib); - asn1_read_OctetString(data, mem_ctx, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed; + if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) { goto failed; } @@ -874,13 +877,13 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, } while (asn1_tag_remaining(data)) { - asn1_peek_uint8(data, &subs_tag); + if (!asn1_peek_uint8(data, &subs_tag)) goto failed; subs_tag &= 0x1f; /* strip off the asn1 stuff */ if (subs_tag > 2) goto failed; - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag)); - asn1_read_LDAPString(data, mem_ctx, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag))) goto failed; + if (!asn1_read_LDAPString(data, mem_ctx, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; switch (subs_tag) { case 0: @@ -947,10 +950,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, const char *attrib; DATA_BLOB value; - asn1_start_tag(data, ASN1_CONTEXT(filter_tag)); - asn1_read_OctetString_talloc(mem_ctx, data, &attrib); - asn1_read_OctetString(data, mem_ctx, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed; + if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) { goto failed; } @@ -966,10 +969,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, const char *attrib; DATA_BLOB value; - asn1_start_tag(data, ASN1_CONTEXT(filter_tag)); - asn1_read_OctetString_talloc(mem_ctx, data, &attrib); - asn1_read_OctetString(data, mem_ctx, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed; + if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) { goto failed; } @@ -1004,10 +1007,10 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, const char *attrib; DATA_BLOB value; - asn1_start_tag(data, ASN1_CONTEXT(filter_tag)); - asn1_read_OctetString_talloc(mem_ctx, data, &attrib); - asn1_read_OctetString(data, mem_ctx, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) goto failed; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib)) goto failed; + if (!asn1_read_OctetString(data, mem_ctx, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) { goto failed; } @@ -1030,18 +1033,18 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, we need to check we properly implement --SSS */ /* either oid or type must be defined */ if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */ - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1)); - asn1_read_LDAPString(data, ret, &oid); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1))) goto failed; + if (!asn1_read_LDAPString(data, ret, &oid)) goto failed; + if (!asn1_end_tag(data)) goto failed; } if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) { /* optional */ - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2)); - asn1_read_LDAPString(data, ret, &attr); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2))) goto failed; + if (!asn1_read_LDAPString(data, ret, &attr)) goto failed; + if (!asn1_end_tag(data)) goto failed; } - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3)); - asn1_read_LDAPString(data, ret, &value); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3))) goto failed; + if (!asn1_read_LDAPString(data, ret, &value)) goto failed; + if (!asn1_end_tag(data)) goto failed; /* dnAttributes is marked as BOOLEAN DEFAULT FALSE it is not marked as OPTIONAL but openldap tools do not set this unless it is to be set as TRUE @@ -1049,9 +1052,9 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, seems that AD always requires the dnAttributes boolean value to be set */ if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) { - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4)); - asn1_read_uint8(data, &dnAttributes); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4))) goto failed; + if (!asn1_read_uint8(data, &dnAttributes)) goto failed; + if (!asn1_end_tag(data)) goto failed; } else { dnAttributes = 0; } @@ -1099,45 +1102,45 @@ failed: } /* Decode a single LDAP attribute, possibly containing multiple values */ -static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data, +static bool ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldb_message_element *attrib) { - asn1_start_tag(data, ASN1_SEQUENCE(0)); - asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name); - asn1_start_tag(data, ASN1_SET); + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false; + if (!asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name)) return false; + if (!asn1_start_tag(data, ASN1_SET)) return false; while (asn1_peek_tag(data, ASN1_OCTET_STRING)) { DATA_BLOB blob; - asn1_read_OctetString(data, mem_ctx, &blob); + if (!asn1_read_OctetString(data, mem_ctx, &blob)) return false; add_value_to_attrib(mem_ctx, &blob, attrib); } - asn1_end_tag(data); - asn1_end_tag(data); - + if (!asn1_end_tag(data)) return false; + return asn1_end_tag(data); } /* Decode a set of LDAP attributes, as found in the dereference control */ -void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data, +bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldb_message_element **attributes, int *num_attributes) { while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) { struct ldb_message_element attrib; ZERO_STRUCT(attrib); - ldap_decode_attrib(mem_ctx, data, &attrib); + if (!ldap_decode_attrib(mem_ctx, data, &attrib)) return false; add_attrib_to_array_talloc(mem_ctx, &attrib, attributes, num_attributes); } + return true; } /* Decode a set of LDAP attributes, as found in a search entry */ -static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data, +static bool ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldb_message_element **attributes, int *num_attributes) { - asn1_start_tag(data, ASN1_SEQUENCE(0)); - ldap_decode_attribs_bare(mem_ctx, data, - attributes, num_attributes); - asn1_end_tag(data); + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) return false; + if (!ldap_decode_attribs_bare(mem_ctx, data, + attributes, num_attributes)) return false; + return asn1_end_tag(data); } /* This routine returns LDAP status codes */ @@ -1148,46 +1151,45 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, { uint8_t tag; - asn1_start_tag(data, ASN1_SEQUENCE(0)); - asn1_read_Integer(data, &msg->messageid); + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err; + if (!asn1_read_Integer(data, &msg->messageid)) goto prot_err; - if (!asn1_peek_uint8(data, &tag)) - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + if (!asn1_peek_uint8(data, &tag)) goto prot_err; switch(tag) { case ASN1_APPLICATION(LDAP_TAG_BindRequest): { struct ldap_BindRequest *r = &msg->r.BindRequest; msg->type = LDAP_TAG_BindRequest; - asn1_start_tag(data, tag); - asn1_read_Integer(data, &r->version); - asn1_read_OctetString_talloc(msg, data, &r->dn); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_Integer(data, &r->version)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) { int pwlen; r->creds.password = ""; r->mechanism = LDAP_AUTH_MECH_SIMPLE; - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0)); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err; pwlen = asn1_tag_remaining(data); if (pwlen == -1) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } if (pwlen != 0) { char *pw = talloc_array(msg, char, pwlen+1); if (!pw) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); } - asn1_read(data, pw, pwlen); + if (!asn1_read(data, pw, pwlen)) goto prot_err; pw[pwlen] = '\0'; r->creds.password = pw; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){ - asn1_start_tag(data, ASN1_CONTEXT(3)); + if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto prot_err; r->mechanism = LDAP_AUTH_MECH_SASL; - asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism); + if (!asn1_read_OctetString_talloc(msg, data, &r->creds.SASL.mechanism)) goto prot_err; if (asn1_peek_tag(data, ASN1_OCTET_STRING)) { /* optional */ DATA_BLOB tmp_blob = data_blob(NULL, 0); - asn1_read_OctetString(data, msg, &tmp_blob); + if (!asn1_read_OctetString(data, msg, &tmp_blob)) goto prot_err; r->creds.SASL.secblob = talloc(msg, DATA_BLOB); if (!r->creds.SASL.secblob) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); @@ -1198,23 +1200,23 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, } else { r->creds.SASL.secblob = NULL; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; } else { /* Neither Simple nor SASL bind */ - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_BindResponse): { struct ldap_BindResponse *r = &msg->r.BindResponse; msg->type = LDAP_TAG_BindResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, &r->response); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, &r->response)) goto prot_err; if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) { DATA_BLOB tmp_blob = data_blob(NULL, 0); - asn1_read_ContextSimple(data, 7, &tmp_blob); + if (!asn1_read_ContextSimple(data, 7, &tmp_blob)) goto prot_err; r->SASL.secblob = talloc(msg, DATA_BLOB); if (!r->SASL.secblob) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); @@ -1225,14 +1227,14 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, } else { r->SASL.secblob = NULL; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): { msg->type = LDAP_TAG_UnbindRequest; - asn1_start_tag(data, tag); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } @@ -1241,41 +1243,41 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, int sizelimit, timelimit; const char **attrs = NULL; msg->type = LDAP_TAG_SearchRequest; - asn1_start_tag(data, tag); - asn1_read_OctetString_talloc(msg, data, &r->basedn); - asn1_read_enumerated(data, (int *)(void *)&(r->scope)); - asn1_read_enumerated(data, (int *)(void *)&(r->deref)); - asn1_read_Integer(data, &sizelimit); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->basedn)) goto prot_err; + if (!asn1_read_enumerated(data, (int *)(void *)&(r->scope))) goto prot_err; + if (!asn1_read_enumerated(data, (int *)(void *)&(r->deref))) goto prot_err; + if (!asn1_read_Integer(data, &sizelimit)) goto prot_err; r->sizelimit = sizelimit; - asn1_read_Integer(data, &timelimit); + if (!asn1_read_Integer(data, &timelimit)) goto prot_err; r->timelimit = timelimit; - asn1_read_BOOLEAN(data, &r->attributesonly); + if (!asn1_read_BOOLEAN(data, &r->attributesonly)) goto prot_err; r->tree = ldap_decode_filter_tree(msg, data); if (r->tree == NULL) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } - asn1_start_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err; r->num_attributes = 0; r->attributes = NULL; - while (asn1_tag_remaining(data) > 0) { + while (asn1_tag_remaining(data) > 0) { const char *attr; if (!asn1_read_OctetString_talloc(msg, data, &attr)) - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; if (!add_string_to_array(msg, attr, &attrs, &r->num_attributes)) - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } r->attributes = attrs; - asn1_end_tag(data); - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } @@ -1284,38 +1286,38 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, msg->type = LDAP_TAG_SearchResultEntry; r->attributes = NULL; r->num_attributes = 0; - asn1_start_tag(data, tag); - asn1_read_OctetString_talloc(msg, data, &r->dn); - ldap_decode_attribs(msg, data, &r->attributes, - &r->num_attributes); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; + if (!ldap_decode_attribs(msg, data, &r->attributes, + &r->num_attributes)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): { struct ldap_Result *r = &msg->r.SearchResultDone; msg->type = LDAP_TAG_SearchResultDone; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): { struct ldap_SearchResRef *r = &msg->r.SearchResultReference; msg->type = LDAP_TAG_SearchResultReference; - asn1_start_tag(data, tag); - asn1_read_OctetString_talloc(msg, data, &r->referral); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->referral)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_ModifyRequest): { struct ldap_ModifyRequest *r = &msg->r.ModifyRequest; msg->type = LDAP_TAG_ModifyRequest; - asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest)); - asn1_read_OctetString_talloc(msg, data, &r->dn); - asn1_start_tag(data, ASN1_SEQUENCE(0)); + if (!asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest))) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err; r->num_mods = 0; r->mods = NULL; @@ -1324,52 +1326,52 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_mod mod; int v; ZERO_STRUCT(mod); - asn1_start_tag(data, ASN1_SEQUENCE(0)); - asn1_read_enumerated(data, &v); + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err; + if (!asn1_read_enumerated(data, &v)) goto prot_err; mod.type = v; - ldap_decode_attrib(msg, data, &mod.attrib); - asn1_end_tag(data); + if (!ldap_decode_attrib(msg, data, &mod.attrib)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; if (!add_mod_to_array_talloc(msg, &mod, &r->mods, &r->num_mods)) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); } } - asn1_end_tag(data); - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): { struct ldap_Result *r = &msg->r.ModifyResponse; msg->type = LDAP_TAG_ModifyResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_AddRequest): { struct ldap_AddRequest *r = &msg->r.AddRequest; msg->type = LDAP_TAG_AddRequest; - asn1_start_tag(data, tag); - asn1_read_OctetString_talloc(msg, data, &r->dn); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; r->attributes = NULL; r->num_attributes = 0; - ldap_decode_attribs(msg, data, &r->attributes, - &r->num_attributes); + if (!ldap_decode_attribs(msg, data, &r->attributes, + &r->num_attributes)) goto prot_err; - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_AddResponse): { struct ldap_Result *r = &msg->r.AddResponse; msg->type = LDAP_TAG_AddResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } @@ -1378,102 +1380,102 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, int len; char *dn; msg->type = LDAP_TAG_DelRequest; - asn1_start_tag(data, - ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest)); + if (!asn1_start_tag(data, + ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest))) goto prot_err; len = asn1_tag_remaining(data); if (len == -1) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } dn = talloc_array(msg, char, len+1); if (dn == NULL) break; - asn1_read(data, dn, len); + if (!asn1_read(data, dn, len)) goto prot_err; dn[len] = '\0'; r->dn = dn; - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_DelResponse): { struct ldap_Result *r = &msg->r.DelResponse; msg->type = LDAP_TAG_DelResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest): { struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; msg->type = LDAP_TAG_ModifyDNRequest; - asn1_start_tag(data, - ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest)); - asn1_read_OctetString_talloc(msg, data, &r->dn); - asn1_read_OctetString_talloc(msg, data, &r->newrdn); - asn1_read_BOOLEAN(data, &r->deleteolddn); + if (!asn1_start_tag(data, + ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest))) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->newrdn)) goto prot_err; + if (!asn1_read_BOOLEAN(data, &r->deleteolddn)) goto prot_err; r->newsuperior = NULL; if (asn1_tag_remaining(data) > 0) { int len; char *newsup; - asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0)); + if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0))) goto prot_err; len = asn1_tag_remaining(data); if (len == -1) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } newsup = talloc_array(msg, char, len+1); if (newsup == NULL) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); } - asn1_read(data, newsup, len); + if (!asn1_read(data, newsup, len)) goto prot_err; newsup[len] = '\0'; r->newsuperior = newsup; - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): { struct ldap_Result *r = &msg->r.ModifyDNResponse; msg->type = LDAP_TAG_ModifyDNResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_CompareRequest): { struct ldap_CompareRequest *r = &msg->r.CompareRequest; msg->type = LDAP_TAG_CompareRequest; - asn1_start_tag(data, - ASN1_APPLICATION(LDAP_TAG_CompareRequest)); - asn1_read_OctetString_talloc(msg, data, &r->dn); - asn1_start_tag(data, ASN1_SEQUENCE(0)); - asn1_read_OctetString_talloc(msg, data, &r->attribute); - asn1_read_OctetString(data, msg, &r->value); + if (!asn1_start_tag(data, + ASN1_APPLICATION(LDAP_TAG_CompareRequest))) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->dn)) goto prot_err; + if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto prot_err; + if (!asn1_read_OctetString_talloc(msg, data, &r->attribute)) goto prot_err; + if (!asn1_read_OctetString(data, msg, &r->value)) goto prot_err; if (r->value.data) { talloc_steal(msg, r->value.data); } - asn1_end_tag(data); - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION(LDAP_TAG_CompareResponse): { struct ldap_Result *r = &msg->r.CompareResponse; msg->type = LDAP_TAG_CompareResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, r); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, r)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): { struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; msg->type = LDAP_TAG_AbandonRequest; - asn1_start_tag(data, tag); - asn1_read_implicit_Integer(data, &r->messageid); - asn1_end_tag(data); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!asn1_read_implicit_Integer(data, &r->messageid)) goto prot_err; + if (!asn1_end_tag(data)) goto prot_err; break; } @@ -1482,9 +1484,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, DATA_BLOB tmp_blob = data_blob(NULL, 0); msg->type = LDAP_TAG_ExtendedRequest; - asn1_start_tag(data,tag); + if (!asn1_start_tag(data,tag)) goto prot_err; if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } r->oid = blob2string_talloc(msg, tmp_blob); data_blob_free(&tmp_blob); @@ -1493,7 +1495,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, } if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { - asn1_read_ContextSimple(data, 1, &tmp_blob); + if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err; r->value = talloc(msg, DATA_BLOB); if (!r->value) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); @@ -1504,7 +1506,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, r->value = NULL; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } @@ -1513,11 +1515,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, DATA_BLOB tmp_blob = data_blob(NULL, 0); msg->type = LDAP_TAG_ExtendedResponse; - asn1_start_tag(data, tag); - ldap_decode_response(msg, data, &r->response); + if (!asn1_start_tag(data, tag)) goto prot_err; + if (!ldap_decode_response(msg, data, &r->response)) goto prot_err; if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(10))) { - asn1_read_ContextSimple(data, 1, &tmp_blob); + if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err; r->oid = blob2string_talloc(msg, tmp_blob); data_blob_free(&tmp_blob); if (!r->oid) { @@ -1528,7 +1530,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, } if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(11))) { - asn1_read_ContextSimple(data, 1, &tmp_blob); + if (!asn1_read_ContextSimple(data, 1, &tmp_blob)) goto prot_err; r->value = talloc(msg, DATA_BLOB); if (!r->value) { return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); @@ -1539,11 +1541,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, r->value = NULL; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; break; } - default: - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + default: + goto prot_err; } msg->controls = NULL; @@ -1554,7 +1556,7 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldb_control **ctrl = NULL; bool *decoded = NULL; - asn1_start_tag(data, ASN1_CONTEXT(0)); + if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto prot_err; while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) { DATA_BLOB value; @@ -1576,9 +1578,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, } if (!ldap_decode_control_wrapper(ctrl[i], data, ctrl[i], &value)) { - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto prot_err; } - + if (!ldap_decode_control_value(ctrl[i], value, control_handlers, ctrl[i])) { @@ -1603,14 +1605,18 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, msg->controls = ctrl; msg->controls_decoded = decoded; - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; } - asn1_end_tag(data); + if (!asn1_end_tag(data)) goto prot_err; if ((data->has_error) || (data->nesting != NULL)) { return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); } return NT_STATUS_OK; + + prot_err: + + return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); } diff --git a/libcli/ldap/ldap_message.h b/libcli/ldap/ldap_message.h index b41f7f5497b..2f64881c053 100644 --- a/libcli/ldap/ldap_message.h +++ b/libcli/ldap/ldap_message.h @@ -228,7 +228,7 @@ bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx, struct asn1_data *data, const char **result); -void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data, +bool ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data, struct ldb_message_element **attributes, int *num_attributes); diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 5063e591784..546ce40e874 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -4754,6 +4754,9 @@ uint8_t smb2cli_session_security_mode(struct smbXcli_session *session) if (conn->mandatory_signing) { security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED; } + if (session->smb2->should_sign) { + security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED; + } return security_mode; } @@ -5031,6 +5034,14 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session, NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session) { + if (!session->smb2->should_sign) { + /* + * We need required signing on the session + * in order to prevent man in the middle attacks. + */ + return NT_STATUS_INVALID_PARAMETER_MIX; + } + if (session->smb2->should_encrypt) { return NT_STATUS_OK; } diff --git a/script/autobuild.py b/script/autobuild.py index 9d117c60e0b..192061a5a70 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -82,7 +82,7 @@ tasks = { ("ldb-make", "cd lib/ldb && make", "text/plain"), ("ldb-install", "cd lib/ldb && make install", "text/plain"), - ("configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=!talloc,!tdb,!pytdb,!ntdb,!pyntdb,!ldb,!pyldb,!tevent,!pytevent --abi-check --enable-debug -C ${PREFIX}", "text/plain"), + ("configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=!talloc,!tdb,!pytdb,!ntdb,!pyntdb,!ldb,!pyldb,!tevent,!pytevent --minimum-library-version=ldb:1.1.17,pyldb-util:1.1.17 --abi-check --enable-debug -C ${PREFIX}", "text/plain"), ("make", "make", "text/plain"), ("install", "make install", "text/plain")], diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 729f4fe0edf..c72cbfdcc80 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -114,6 +114,11 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, const char *domain; NTSTATUS status; int flags = 0; + int signing_state = get_cmdline_auth_info_signing_state(auth_info); + + if (force_encrypt) { + signing_state = SMB_SIGNING_REQUIRED; + } /* make a copy so we don't modify the global string 'service' */ servicename = talloc_strdup(ctx,share); @@ -152,7 +157,7 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx, status = cli_connect_nb( server, NULL, port, name_type, NULL, - get_cmdline_auth_info_signing_state(auth_info), + signing_state, flags, &c); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index b1a4ed7319b..ea81f84f231 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -273,6 +273,7 @@ SMBC_server_internal(TALLOC_CTX *ctx, char *newserver, *newshare; int flags = 0; struct smbXcli_tcon *tcon = NULL; + int signing_state = SMB_SIGNING_DEFAULT; ZERO_STRUCT(c); *in_cache = false; @@ -439,6 +440,10 @@ SMBC_server_internal(TALLOC_CTX *ctx, flags |= CLI_FULL_CONNECTION_USE_NT_HASH; } + if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { + signing_state = SMB_SIGNING_REQUIRED; + } + if (port == 0) { if (share == NULL || *share == '\0' || is_ipc) { /* @@ -446,7 +451,7 @@ SMBC_server_internal(TALLOC_CTX *ctx, */ status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20, smbc_getNetbiosName(context), - SMB_SIGNING_DEFAULT, flags, &c); + signing_state, flags, &c); } } @@ -456,7 +461,7 @@ SMBC_server_internal(TALLOC_CTX *ctx, */ status = cli_connect_nb(server_n, NULL, port, 0x20, smbc_getNetbiosName(context), - SMB_SIGNING_DEFAULT, flags, &c); + signing_state, flags, &c); } if (!NT_STATUS_IS_OK(status)) { @@ -745,6 +750,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", pp_workgroup, pp_username, pp_password); if (!ipc_srv) { + int signing_state = SMB_SIGNING_DEFAULT; /* We didn't find a cached connection. Get the password */ if (!*pp_password || (*pp_password)[0] == '\0') { @@ -766,6 +772,9 @@ SMBC_attr_server(TALLOC_CTX *ctx, if (smbc_getOptionUseCCache(context)) { flags |= CLI_FULL_CONNECTION_USE_CCACHE; } + if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { + signing_state = SMB_SIGNING_REQUIRED; + } nt_status = cli_full_connection(&ipc_cli, lp_netbios_name(), server, @@ -774,7 +783,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, *pp_workgroup, *pp_password, flags, - SMB_SIGNING_DEFAULT); + signing_state); if (! NT_STATUS_IS_OK(nt_status)) { DEBUG(1,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index fca05cf7ab9..07e2f8ac0e7 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -30,6 +30,7 @@ */ #include "includes.h" +#include "smbd/smbd.h" #include "system/filesys.h" #include "include/ntioctl.h" #include <ccan/hash/hash.h> @@ -1138,6 +1139,42 @@ static char *have_snapdir(struct vfs_handle_struct *handle, return NULL; } +static bool check_access_snapdir(struct vfs_handle_struct *handle, + const char *path) +{ + struct smb_filename smb_fname; + int ret; + NTSTATUS status; + + ZERO_STRUCT(smb_fname); + smb_fname.base_name = talloc_asprintf(talloc_tos(), + "%s", + path); + if (smb_fname.base_name == NULL) { + return false; + } + + ret = SMB_VFS_NEXT_STAT(handle, &smb_fname); + if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) { + TALLOC_FREE(smb_fname.base_name); + return false; + } + + status = smbd_check_access_rights(handle->conn, + &smb_fname, + false, + SEC_DIR_LIST); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("user does not have list permission " + "on snapdir %s\n", + smb_fname.base_name)); + TALLOC_FREE(smb_fname.base_name); + return false; + } + TALLOC_FREE(smb_fname.base_name); + return true; +} + /** * Find the snapshot directory (if any) for the given * filename (which is relative to the share). @@ -1287,6 +1324,7 @@ static int shadow_copy2_get_shadow_copy_data( const char *snapdir; struct dirent *d; TALLOC_CTX *tmp_ctx = talloc_stackframe(); + bool ret; snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name); if (snapdir == NULL) { @@ -1296,6 +1334,13 @@ static int shadow_copy2_get_shadow_copy_data( talloc_free(tmp_ctx); return -1; } + ret = check_access_snapdir(handle, snapdir); + if (!ret) { + DEBUG(0,("access denied on listing snapdir %s\n", snapdir)); + errno = EACCES; + talloc_free(tmp_ctx); + return -1; + } p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 118f6c90b2b..edf4ee15df8 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -976,6 +976,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, struct smb_filename *smb_fname_cwd = NULL; struct privilege_paths *priv_paths = NULL; int ret; + bool matched; DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n", fname, @@ -1070,7 +1071,10 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, } rootdir_len = strlen(conn_rootdir); - if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) { + matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0); + + if (!matched || (resolved_name[rootdir_len] != '/' && + resolved_name[rootdir_len] != '\0')) { DEBUG(2, ("check_reduced_name_with_privilege: Bad access " "attempt: %s is a symlink outside the " "share path\n", @@ -1210,6 +1214,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) if (!allow_widelinks || !allow_symlinks) { const char *conn_rootdir; size_t rootdir_len; + bool matched; conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname); if (conn_rootdir == NULL) { @@ -1220,8 +1225,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) } rootdir_len = strlen(conn_rootdir); - if (strncmp(conn_rootdir, resolved_name, - rootdir_len) != 0) { + matched = (strncmp(conn_rootdir, resolved_name, + rootdir_len) == 0); + if (!matched || (resolved_name[rootdir_len] != '/' && + resolved_name[rootdir_len] != '\0')) { DEBUG(2, ("check_reduced_name: Bad access " "attempt: %s is a symlink outside the " "share path\n", fname)); diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 2c8a0647ccd..97934c747f8 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -1468,12 +1468,15 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, struct security_token *user_token; struct security_descriptor *domain_sd; struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); const struct uac_to_guid { uint32_t uac; + uint32_t priv_to_change_from; const char *oid; const char *guid; enum sec_privilege privilege; bool delete_is_privileged; + bool admin_required; const char *error_string; } map[] = { { @@ -1502,6 +1505,16 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, .error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" }, { + .uac = UF_WORKSTATION_TRUST_ACCOUNT, + .priv_to_change_from = UF_NORMAL_ACCOUNT, + .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group" + }, + { + .uac = UF_NORMAL_ACCOUNT, + .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT, + .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group" + }, + { .uac = UF_INTERDOMAIN_TRUST_ACCOUNT, .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID, .error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP. This bit is restricted to the LSA CreateTrustedDomain interface", @@ -1553,7 +1566,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, return ldb_module_operr(ac->module); } - ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module), + ret = dsdb_get_sd_from_ldb_message(ldb, ac, res->msgs[0], &domain_sd); if (ret != LDB_SUCCESS) { @@ -1580,12 +1593,19 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, if (have_priv == false) { ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } - } else { + } else if (map[i].priv_to_change_from & user_account_control_old) { + bool is_admin = security_token_has_builtin_administrators(user_token); + if (is_admin == false) { + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else if (map[i].guid) { ret = acl_check_extended_right(ac, domain_sd, user_token, map[i].guid, SEC_ADS_CONTROL_ACCESS, sid); + } else { + ret = LDB_SUCCESS; } if (ret != LDB_SUCCESS) { break; diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c index 17d96f6f9d7..983082bdd22 100644 --- a/source4/libcli/ldap/ldap_controls.c +++ b/source4/libcli/ldap/ldap_controls.c @@ -1187,10 +1187,10 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out) if (!asn1_start_tag(data, ASN1_CONTEXT(0))) { return false; } - - ldap_decode_attribs_bare(r, data, &r[i]->attributes, - &r[i]->num_attributes); - + if (!ldap_decode_attribs_bare(r, data, &r[i]->attributes, + &r[i]->num_attributes)) { + return false; + } if (!asn1_end_tag(data)) { return false; } |