[SCM] Samba Shared Repository - branch v4-1-test updated

Karolin Seeger kseeger at samba.org
Mon Jun 1 17:56:04 MDT 2015


The branch, v4-1-test has been updated
       via  3e5744d s3: IPv6 enabled DNS connections for ADS client
       via  a6d7aa5 Add IPv6 support for determining FQDN during ADS join.
       via  ccf557c Add IPv6 support to ADS client side LDAP connects. Corrected format for IPv6 LDAP URI.
       via  34cffdb s4:torture:smb2:compound: compound read and padding
       via  9ba2dce s3:smb2: add padding to last command in compound requests
       via  db28391 s3: smbcacls: Ensure we read a hex number as %x, not %u.
      from  995bef1 s4: libcli/finddcs_cldap: continue processing CLDAP until all addresses are used

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-1-test


- Log -----------------------------------------------------------------
commit 3e5744d1888d76a2becb8e512bc1be21d0000472
Author: David Holder <david.holder at erion.co.uk>
Date:   Wed May 27 09:15:51 2015 -0700

    s3: IPv6 enabled DNS connections for ADS client
    
    This patch makes DNS client connections protocol independent.
    For example DNS updates. This makes IPv6-only clients possible.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11283
    
    Back-port from fff774eda3ed04d319232b108a94282af24cc6b0
    
    Signed-off-by: David Holder <david.holder at erion.co.uk>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <rb at sernet.de>
    
    Autobuild-User(v4-1-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-1-test): Tue Jun  2 01:55:28 CEST 2015 on sn-devel-104

commit a6d7aa50735096025d8806ddb11404a346f1261d
Author: David Holder <david.holder at erion.co.uk>
Date:   Wed May 27 11:40:17 2015 -0700

    Add IPv6 support for determining FQDN during ADS join.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11282
    
    Back ported from commit 6e08bfb4441022a00d0c29205e835a4858a3a57f
    
    Signed-off-by: David Holder <david.holder at erion.co.uk>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <rb at sernet.de>

commit ccf557c470fb4102df40819d30c6bdaf01bd6a6b
Author: David Holder <david.holder at erion.co.uk>
Date:   Wed May 27 11:10:52 2015 -0700

    Add IPv6 support to ADS client side LDAP connects. Corrected format for IPv6 LDAP URI.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11281
    
    (Back ported from commit c324d7901c991a6700abdc3ee701920fea5e5819)
    
    Signed-off-by: David Holder <david.holder at erion.co.uk>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <rb at sernet.de>

commit 34cffdbed31f345ba90a7dc4035282872973e1a7
Author: Ralph Boehme <slow at samba.org>
Date:   Thu May 14 04:27:54 2015 +0200

    s4:torture:smb2:compound: compound read and padding
    
    Add test to check that compound read responses are padded to an 8 byte
    boundary.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=11277
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Thu May 28 16:50:39 CEST 2015 on sn-devel-104
    
    (cherry picked from commit 2ffa939bbe2c02509e1790c8b3f6f9b6910e3cf6)

commit 9ba2dce359dbd2aff75a136428b825746103d43d
Author: Ralph Boehme <slow at samba.org>
Date:   Thu May 28 09:02:17 2015 +0200

    s3:smb2: add padding to last command in compound requests
    
    Following Windows behaviour, the last command in a compound request
    should be padded to an 8 byte boundary and OS X clients crash badly if
    we don't pad.
    
    [MS-SMB2] 3.3.4.1.3, "Sending Compounded Responses", doesn't make it
    clear whether the padding requirement governs the last command in a
    compound response, a future MS-SMB2 update will document Windwows
    product behaviour in a footnote.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=11277
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit dfa64b958b201931e0dbe11f153f606f20217594)

commit db283914bcfa38661f18ac89712c1e9eb949095b
Author: Jeremy Allison <jra at samba.org>
Date:   Fri May 22 09:24:56 2015 +0200

    s3: smbcacls: Ensure we read a hex number as %x, not %u.
    
    Based on a patch from Zoe O'Connell <zoe at metail.com>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11068
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Jim McDonough <jmcd at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/addns/dns.h                 |   2 +-
 lib/addns/dnssock.c             | 125 ++++++++++++++-------
 source3/lib/util.c              |  52 +++++----
 source3/libads/ldap.c           |   8 +-
 source3/smbd/smb2_server.c      |  16 ++-
 source3/utils/smbcacls.c        |   2 +-
 source4/torture/smb2/compound.c | 239 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 377 insertions(+), 67 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/addns/dns.h b/lib/addns/dns.h
index bf2ade3..de1897b 100644
--- a/lib/addns/dns.h
+++ b/lib/addns/dns.h
@@ -222,7 +222,7 @@ struct dns_update_request {
 struct dns_connection {
 	int32_t hType;
 	int s;
-	struct sockaddr RecvAddr;
+	struct sockaddr_storage RecvAddr;
 };
 
 struct dns_buffer {
diff --git a/lib/addns/dnssock.c b/lib/addns/dnssock.c
index 5f99519..bab20a4 100644
--- a/lib/addns/dnssock.c
+++ b/lib/addns/dnssock.c
@@ -27,6 +27,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 #include "system/select.h"
+#include "../lib/util/debug.h"
 
 static int destroy_dns_connection(struct dns_connection *conn)
 {
@@ -40,42 +41,58 @@ static DNS_ERROR dns_tcp_open( const char *nameserver,
 			       TALLOC_CTX *mem_ctx,
 			       struct dns_connection **result )
 {
-	uint32_t ulAddress;
-	struct hostent *pHost;
-	struct sockaddr_in s_in;
+	struct addrinfo hints;
+	struct addrinfo *ai_result = NULL;
+	struct addrinfo *rp;
 	struct dns_connection *conn;
-	int res;
+	int ret;
+	char service[16];
+
+	snprintf(service, sizeof(service), "%d", DNS_TCP_PORT);
 
 	if (!(conn = talloc(mem_ctx, struct dns_connection))) {
 		return ERROR_DNS_NO_MEMORY;
 	}
 
-	if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
-		if ( (pHost = gethostbyname( nameserver )) == NULL ) {
-			TALLOC_FREE(conn);
-			return ERROR_DNS_INVALID_NAME_SERVER;
-		}
-		memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
-	}
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = 0;
+	hints.ai_protocol = IPPROTO_TCP;
 
-	conn->s = socket( PF_INET, SOCK_STREAM, 0 );
-	if (conn->s == -1) {
-		TALLOC_FREE(conn);
-		return ERROR_DNS_CONNECTION_FAILED;
+	ret = getaddrinfo(nameserver, service, &hints, &ai_result);
+	if (ret != 0) {
+		DEBUG(1,("dns_tcp_open: getaddrinfo: %s\n", gai_strerror(ret)));
+		return ERROR_DNS_INVALID_NAME_SERVER;
 	}
 
-	talloc_set_destructor(conn, destroy_dns_connection);
+	for (rp = ai_result; rp != NULL; rp = rp->ai_next) {
+		conn->s = socket(rp->ai_family,
+				rp->ai_socktype,
+				rp->ai_protocol);
+		if (conn->s == -1) {
+			continue;
+		}
+		do {
+			ret = connect(conn->s, rp->ai_addr, rp->ai_addrlen);
+		} while ((ret == -1) && (errno == EINTR));
+		if (ret != -1) {
+			/* Successful connect */
+			break;
+		}
+		close(conn->s);
+	}
 
-	s_in.sin_family = AF_INET;
-	s_in.sin_addr.s_addr = ulAddress;
-	s_in.sin_port = htons( DNS_TCP_PORT );
+	freeaddrinfo(ai_result);
 
-	res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
-	if (res == -1) {
+	/* Failed to connect with any address */
+	if (rp == NULL) {
 		TALLOC_FREE(conn);
 		return ERROR_DNS_CONNECTION_FAILED;
 	}
 
+	talloc_set_destructor(conn, destroy_dns_connection);
+
 	conn->hType = DNS_TCP;
 
 	*result = conn;
@@ -89,44 +106,72 @@ static DNS_ERROR dns_udp_open( const char *nameserver,
 			       TALLOC_CTX *mem_ctx,
 			       struct dns_connection **result )
 {
-	unsigned long ulAddress;
-	struct hostent *pHost;
-	struct sockaddr_in RecvAddr;
+	struct addrinfo hints;
+	struct addrinfo *ai_result = NULL;
+	struct addrinfo *rp;
+	struct sockaddr_storage RecvAddr;
 	struct dns_connection *conn;
+	int ret;
+	socklen_t RecvAddrLen;
+	char service[16];
+
+	snprintf(service, sizeof(service), "%d", DNS_UDP_PORT);
 
 	if (!(conn = talloc(NULL, struct dns_connection))) {
 		return ERROR_DNS_NO_MEMORY;
 	}
 
-	if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
-		if ( (pHost = gethostbyname( nameserver )) == NULL ) {
-			TALLOC_FREE(conn);
-			return ERROR_DNS_INVALID_NAME_SERVER;
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_flags = 0;
+	hints.ai_protocol = IPPROTO_UDP;
+
+	ret = getaddrinfo(nameserver, service, &hints, &ai_result);
+	if (ret != 0) {
+		DEBUG(1,("dns_ucp_open:getaddrinfo: %s\n", gai_strerror(ret)));
+		TALLOC_FREE(conn);
+		return ERROR_DNS_INVALID_NAME_SERVER;
+	}
+
+	for (rp = ai_result; rp != NULL; rp = rp->ai_next) {
+		conn->s = socket(rp->ai_family,
+				rp->ai_socktype,
+				rp->ai_protocol);
+		if (conn->s == -1) {
+			continue;
 		}
-		memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
+		ret = connect(conn->s, rp->ai_addr, rp->ai_addrlen);
+		if (ret != -1) {
+			/* Successful connect */
+			break;
+		}
+		close(conn->s);
 	}
 
-	/* Create a socket for sending data */
+	freeaddrinfo(ai_result);
 
-	conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	if (conn->s == -1) {
+	/* Failed to connect with any address */
+	if (rp == NULL) {
 		TALLOC_FREE(conn);
-		return ERROR_DNS_CONNECTION_FAILED;
+                return ERROR_DNS_CONNECTION_FAILED;
 	}
 
 	talloc_set_destructor(conn, destroy_dns_connection);
 
 	/* Set up the RecvAddr structure with the IP address of
-	   the receiver (in this example case "123.456.789.1")
-	   and the specified port number. */
+	   the receiver and the specified port number. */
 
-	ZERO_STRUCT(RecvAddr);
-	RecvAddr.sin_family = AF_INET;
-	RecvAddr.sin_port = htons( DNS_UDP_PORT );
-	RecvAddr.sin_addr.s_addr = ulAddress;
+	RecvAddrLen = sizeof(RecvAddr);
+	if (getpeername(conn->s,
+			(struct sockaddr *)&RecvAddr,
+			&RecvAddrLen) == -1) {
+		TALLOC_FREE(conn);
+		return ERROR_DNS_CONNECTION_FAILED;
+	}
 
 	conn->hType = DNS_UDP;
-	memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
+	memcpy(&conn->RecvAddr, &RecvAddr, sizeof(struct sockaddr_storage));
 
 	*result = conn;
 	return ERROR_DNS_SUCCESS;
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 9e6ac9c..641a67e 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -1827,48 +1827,60 @@ bool unix_wild_match(const char *pattern, const char *string)
 }
 
 /**********************************************************************
- Converts a name to a fully qualified domain name.
- Returns true if lookup succeeded, false if not (then fqdn is set to name)
- Note we deliberately use gethostbyname here, not getaddrinfo as we want
- to examine the h_aliases and I don't know how to do that with getaddrinfo.
+  Converts a name to a fully qualified domain name.
+  Returns true if lookup succeeded, false if not (then fqdn is set to name)
+  Uses getaddrinfo() with AI_CANONNAME flag to obtain the official
+  canonical name of the host. getaddrinfo() may use a variety of sources
+  including /etc/hosts to obtain the domainname. It expects aliases in
+  /etc/hosts to NOT be the FQDN. The FQDN should come first.
 ***********************************************************************/
 
 bool name_to_fqdn(fstring fqdn, const char *name)
 {
 	char *full = NULL;
-	struct hostent *hp = gethostbyname(name);
+	struct addrinfo hints;
+	struct addrinfo *result;
+	int s;
 
-	if (!hp || !hp->h_name || !*hp->h_name) {
+	/* Configure hints to obtain canonical name */
+
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
+	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+	hints.ai_flags = AI_CANONNAME;  /* Get host's FQDN */
+	hints.ai_protocol = 0;          /* Any protocol */
+
+	s = getaddrinfo(name, NULL, &hints, &result);
+	if (s != 0) {
+		DEBUG(1, ("getaddrinfo: %s\n", gai_strerror(s)));
 		DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
 		fstrcpy(fqdn, name);
 		return false;
 	}
+	full = result->ai_canonname;
 
-	/* Find out if the fqdn is returned as an alias
+	/* Find out if the FQDN is returned as an alias
 	 * to cope with /etc/hosts files where the first
-	 * name is not the fqdn but the short name */
-	if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
-		int i;
-		for (i = 0; hp->h_aliases[i]; i++) {
-			if (strchr_m(hp->h_aliases[i], '.')) {
-				full = hp->h_aliases[i];
-				break;
-			}
-		}
+	 * name is not the FQDN but the short name.
+	 * getaddrinfo provides no easy way of handling aliases
+	 * in /etc/hosts. Users should make sure the FQDN
+	 * comes first in /etc/hosts. */
+	if (full && (! strchr_m(full, '.'))) {
+		DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
+		DEBUGADD(1, ("    Full qualified domain names (FQDNs) should not be specified\n"));
+		DEBUGADD(1, ("    as an alias in /etc/hosts. FQDN should be the first name\n"));
+		DEBUGADD(1, ("    prior to any aliases.\n"));
 	}
 	if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
 		DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
 		DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
 		DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
 		DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
-		full = hp->h_name;
-	}
-	if (!full) {
-		full = hp->h_name;
 	}
 
 	DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
 	fstrcpy(fqdn, full);
+	freeaddrinfo(result);           /* No longer needed */
 	return true;
 }
 
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index b9adc9d..c1eecec 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -87,7 +87,13 @@ static void gotalarm_sig(int signum)
 #ifndef LDAP_PROTO_TCP
 #define LDAP_PROTO_TCP 1
 #endif
-		uri = talloc_asprintf(talloc_tos(), "ldap://%s:%u", server, port);
+		if ( strchr_m(server, ':') ) {
+			/* IPv6 URI */
+			uri = talloc_asprintf(talloc_tos(), "ldap://[%s]:%u", server, port);
+		} else {
+			/* IPv4 URI */
+			uri = talloc_asprintf(talloc_tos(), "ldap://%s:%u", server, port);
+		}
 		if (uri == NULL) {
 			return NULL;
 		}
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index a4e149f..eed0b0e 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2517,8 +2517,13 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
 		outdyn_v->iov_len = 0;
 	}
 
-	/* see if we need to recalculate the offset to the next response */
-	if (next_command_ofs > 0) {
+	/*
+	 * See if we need to recalculate the offset to the next response
+	 *
+	 * Note that all responses may require padding (including the very last
+	 * one).
+	 */
+	if (req->out.vector_count >= (2 * SMBD_SMB2_NUM_IOV_PER_REQ)) {
 		next_command_ofs  = SMB2_HDR_BODY;
 		next_command_ofs += SMBD_SMB2_OUT_BODY_LEN(req);
 		next_command_ofs += SMBD_SMB2_OUT_DYN_LEN(req);
@@ -2572,8 +2577,11 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
 		next_command_ofs += pad_size;
 	}
 
-	SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
-
+	if ((req->current_idx + SMBD_SMB2_NUM_IOV_PER_REQ) >= req->out.vector_count) {
+		SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
+	} else {
+		SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
+	}
 	return smbd_smb2_request_reply(req);
 }
 
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 23a1192..d8e7985 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -571,7 +571,7 @@ static bool parse_ace(struct cli_state *cli, struct security_ace *ace,
 	}
 
 	if (strncmp(tok, "0x", 2) == 0) {
-		if (sscanf(tok, "%u", &amask) != 1) {
+		if (sscanf(tok, "%x", &amask) != 1) {
 			printf("ACE '%s': bad hex number at '%s'\n",
 				orig_str, tok);
 			SAFE_FREE(str);
diff --git a/source4/torture/smb2/compound.c b/source4/torture/smb2/compound.c
index 9b3cacc..a502103 100644
--- a/source4/torture/smb2/compound.c
+++ b/source4/torture/smb2/compound.c
@@ -34,6 +34,14 @@
 		goto done; \
 	}} while (0)
 
+#define CHECK_VALUE(v, correct) do { \
+	if ((v) != (correct)) { \
+		torture_result(tctx, TORTURE_FAIL, \
+		    "(%s) Incorrect value %s=%d - should be %d\n", \
+		    __location__, #v, (int)v, (int)correct); \
+		ret = false; \
+	}} while (0)
+
 static struct {
 	struct smb2_handle handle;
 	uint8_t level;
@@ -433,6 +441,236 @@ done:
 	return ret;
 }
 
+static bool test_compound_padding(struct torture_context *tctx,
+				  struct smb2_tree *tree)
+{
+	struct smb2_handle h;
+	struct smb2_create cr;
+	struct smb2_read r;
+	const char *fname = "compound_read.dat";
+	const char *sname = "compound_read.dat:foo";
+	struct smb2_request *req[3];
+	NTSTATUS status;
+	bool ret = false;
+
+	smb2_util_unlink(tree, fname);
+
+	/* Write file */
+	ZERO_STRUCT(cr);
+	cr.in.desired_access = SEC_FILE_WRITE_DATA;
+	cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	cr.in.create_disposition = NTCREATEX_DISP_CREATE;
+	cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	cr.in.fname = fname;
+	cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+		NTCREATEX_SHARE_ACCESS_WRITE|
+		NTCREATEX_SHARE_ACCESS_DELETE;
+	status = smb2_create(tree, tctx, &cr);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h = cr.out.file.handle;
+
+	status = smb2_util_write(tree, h, "123", 0, 3);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smb2_util_close(tree, h);
+
+	/* Write stream */
+	ZERO_STRUCT(cr);
+	cr.in.desired_access = SEC_FILE_WRITE_DATA;
+	cr.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	cr.in.create_disposition = NTCREATEX_DISP_CREATE;
+	cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	cr.in.fname = sname;
+	cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+		NTCREATEX_SHARE_ACCESS_WRITE|
+		NTCREATEX_SHARE_ACCESS_DELETE;
+	status = smb2_create(tree, tctx, &cr);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h = cr.out.file.handle;
+
+	status = smb2_util_write(tree, h, "456", 0, 3);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smb2_util_close(tree, h);
+
+	/* Check compound read from basefile */
+	smb2_transport_compound_start(tree->session->transport, 2);
+
+	ZERO_STRUCT(cr);
+	cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	cr.in.desired_access	= SEC_FILE_READ_DATA;
+	cr.in.file_attributes	= FILE_ATTRIBUTE_NORMAL;
+	cr.in.create_disposition = NTCREATEX_DISP_OPEN;
+	cr.in.fname		= fname;
+	cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+		NTCREATEX_SHARE_ACCESS_WRITE|
+		NTCREATEX_SHARE_ACCESS_DELETE;
+	req[0] = smb2_create_send(tree, &cr);
+
+	smb2_transport_compound_set_related(tree->session->transport, true);
+
+	ZERO_STRUCT(r);
+	h.data[0] = UINT64_MAX;
+	h.data[1] = UINT64_MAX;
+	r.in.file.handle = h;
+	r.in.length      = 3;
+	r.in.offset      = 0;
+	r.in.min_count      = 1;
+	req[1] = smb2_read_send(tree, &r);
+
+	status = smb2_create_recv(req[0], tree, &cr);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * We must do a manual smb2_request_receive() in order to be
+	 * able to check the transport layer info, as smb2_read_recv()
+	 * will destroy the req. smb2_read_recv() will call
+	 * smb2_request_receive() again, but that's ok.
+	 */
+	if (!smb2_request_receive(req[1]) ||
+	    !smb2_request_is_ok(req[1])) {
+		torture_fail(tctx, "failed to receive read request");
+	}
+
+	/*
+	 * size must be 24: 16 byte read response header plus 3
+	 * requested bytes padded to an 8 byte boundary.
+	 */
+	CHECK_VALUE(req[1]->in.body_size, 24);
+
+	status = smb2_read_recv(req[1], tree, &r);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smb2_util_close(tree, cr.out.file.handle);
+
+	/* Check compound read from stream */
+	smb2_transport_compound_start(tree->session->transport, 2);
+
+	ZERO_STRUCT(cr);
+	cr.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	cr.in.desired_access	= SEC_FILE_READ_DATA;
+	cr.in.file_attributes	= FILE_ATTRIBUTE_NORMAL;
+	cr.in.create_disposition = NTCREATEX_DISP_OPEN;
+	cr.in.fname		= sname;
+	cr.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
+		NTCREATEX_SHARE_ACCESS_WRITE|
+		NTCREATEX_SHARE_ACCESS_DELETE;
+	req[0] = smb2_create_send(tree, &cr);
+
+	smb2_transport_compound_set_related(tree->session->transport, true);
+
+	ZERO_STRUCT(r);
+	h.data[0] = UINT64_MAX;
+	h.data[1] = UINT64_MAX;
+	r.in.file.handle = h;
+	r.in.length      = 3;
+	r.in.offset      = 0;
+	r.in.min_count   = 1;
+	req[1] = smb2_read_send(tree, &r);
+
+	status = smb2_create_recv(req[0], tree, &cr);
+	CHECK_STATUS(status, NT_STATUS_OK);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list