[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Fri Feb 26 02:42:42 MST 2010


The branch, master has been updated
       via  81bb8f6... s4-smb: Migrate named_pipe_server to tsocket.
       via  1983256... tsocket: Improve the tsocket_address_bsd_sockaddr documentation.
       via  27e7578... s4:provision: use generate_random_password()
       via  d2cd0a7... s4:pyglue: add generate_random_password()
       via  9ada48f... s4:torture/rpc: use generate_random_password()
       via  7473ca2... s4:libnet: use generate_random_password()
       via  792dd38... lib/util: add generate_random_password()
      from  c2edea5... devel: get the ownership of the directories right in tmpfs.sh

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 81bb8f67fa50acb914a428b5468fe39643cecb78
Author: Andreas Schneider <asn at redhat.com>
Date:   Thu Feb 4 17:03:04 2010 +0100

    s4-smb: Migrate named_pipe_server to tsocket.
    
    This is an improved version of commit 69d5cea2e59162f19460e7ce4b6382fc5fdd6ca0,
    which was reverted by commit 71c20f703b0c603d6aada63ed5634070a26df052.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 1983256c70cf07b8c8afddd024ee5fd2522ee83c
Author: Andreas Schneider <asn at redhat.com>
Date:   Thu Feb 25 14:32:39 2010 +0100

    tsocket: Improve the tsocket_address_bsd_sockaddr documentation.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit 27e7578e2763f0e9de2e0c94521d552678244cf2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 24 15:09:15 2010 +0100

    s4:provision: use generate_random_password()
    
    metze

commit d2cd0a783b059fc2a938f7e2a5f5d002e83be967
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 24 14:44:22 2010 +0100

    s4:pyglue: add generate_random_password()
    
    metze

commit 9ada48ffdb3b7ab4bc1bce0f6b2179f67292bcf8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 24 15:12:17 2010 +0100

    s4:torture/rpc: use generate_random_password()
    
    metze

commit 7473ca2d33e04d9b9dbb7fa56b0cb44603988036
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Feb 24 15:09:50 2010 +0100

    s4:libnet: use generate_random_password()
    
    metze

commit 792dd38d7c0be5319db1eef625c142a6490cd12b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 25 15:58:38 2010 +0100

    lib/util: add generate_random_password()
    
    metze

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

Summary of changes:
 lib/tsocket/tsocket.h                       |    4 +-
 lib/util/genrand.c                          |   42 +++
 lib/util/util.h                             |    5 +
 source4/libnet/libnet_join.c                |    2 +-
 source4/libnet/libnet_vampire.c             |    2 +-
 source4/scripting/bin/upgradeprovision      |    2 +-
 source4/scripting/python/pyglue.c           |   24 ++-
 source4/scripting/python/samba/provision.py |   10 +-
 source4/smbd/service_named_pipe.c           |  519 ++++++++++++++++-----------
 source4/smbd/service_stream.c               |    2 +-
 source4/torture/rpc/netlogon.c              |    8 +-
 source4/torture/rpc/samba3rpc.c             |    8 +-
 source4/torture/rpc/samr.c                  |    6 +-
 source4/torture/rpc/schannel.c              |    2 +-
 source4/torture/rpc/testjoin.c              |    2 +-
 15 files changed, 405 insertions(+), 233 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h
index 1cd40e4..d983325 100644
--- a/lib/tsocket/tsocket.h
+++ b/lib/tsocket/tsocket.h
@@ -869,7 +869,9 @@ ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
  * @brief Wrap an existing file descriptors into the tstream abstraction.
  *
  * You can use this function to wrap an existing file descriptors into the
- * tstream abstraction.
+ * tstream abstraction. After that you're not able to use this file descriptor
+ * for anything else. The file descriptor will be closed when the stream gets
+ * freed. If you still want to use the fd you have have to create a duplicate.
  *
  * @param[in]  mem_ctx      The talloc memory context to use.
  *
diff --git a/lib/util/genrand.c b/lib/util/genrand.c
index f054402..02b8d8b 100644
--- a/lib/util/genrand.c
+++ b/lib/util/genrand.c
@@ -362,6 +362,48 @@ again:
 }
 
 /**
+ * Generate a random text password.
+ */
+
+_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max)
+{
+	char *retstr;
+	const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>(){}[]~";
+	size_t len = max;
+	size_t diff;
+
+	if (min > max) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	diff = max - min;
+
+	if (diff > 0 ) {
+		size_t tmp;
+
+		generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
+
+		tmp %= diff;
+
+		len = min + tmp;
+	}
+
+again:
+	retstr = generate_random_str_list(mem_ctx, len, c_list);
+	if (!retstr) return NULL;
+
+	/* we need to make sure the random string passes basic quality tests
+	   or it might be rejected by windows as a password */
+	if (len >= 7 && !check_password_quality(retstr)) {
+		talloc_free(retstr);
+		goto again;
+	}
+
+	return retstr;
+}
+
+/**
  * Generate an array of unique text strings all of the same length.
  * The returned string will be allocated.
  * Returns NULL if the number of unique combinations cannot be created.
diff --git a/lib/util/util.h b/lib/util/util.h
index e1608a8..264396e 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -178,6 +178,11 @@ _PUBLIC_ uint32_t generate_random(void);
 _PUBLIC_ bool check_password_quality(const char *s);
 
 /**
+ * Generate a random text password.
+ */
+_PUBLIC_ char *generate_random_password(TALLOC_CTX *mem_ctx, size_t min, size_t max);
+
+/**
  Use the random number generator to generate a random string.
 **/
 _PUBLIC_ char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list);
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index 84d3250..71bef31 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -796,7 +796,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
 	
 	/* Grab a password of that minimum length */
 	
-	password_str = generate_random_str(tmp_ctx, MAX(8, policy_min_pw_len));	
+	password_str = generate_random_password(tmp_ctx, MAX(8, policy_min_pw_len), 255);
 
 	/* set full_name and reset flags */
 	ZERO_STRUCT(u_info21);
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index 9554a63..aa47100 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -94,7 +94,7 @@ static NTSTATUS vampire_prepare_db(void *private_data,
 	settings.realm = s->join->out.realm;
 	settings.domain = s->join->out.domain_name;
 	settings.server_dn_str = p->dest_dsa->server_dn_str;
-	settings.machine_password = generate_random_str(s, 16);
+	settings.machine_password = generate_random_password(s, 16, 255);
 	settings.targetdir = s->targetdir;
 
 	status = provision_bare(s, s->lp_ctx, &settings, &result);
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index e2ee8d0..1d58f5e 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -875,7 +875,7 @@ def update_machine_account_password(paths,creds,session,names):
 		assert(len(res) == 1)
 
 		msg = ldb.Message(res[0].dn)
-		machinepass = glue.generate_random_str(12)
+		machinepass = glue.generate_random_password(128, 255)
 		msg["userPassword"] = ldb.MessageElement(machinepass, ldb.FLAG_MOD_REPLACE, "userPassword")
 		sam_ldb.modify(msg)
 
diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c
index 136b121..6fe789a 100644
--- a/source4/scripting/python/pyglue.c
+++ b/source4/scripting/python/pyglue.c
@@ -79,6 +79,23 @@ static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
 	return ret;
 }
 
+static PyObject *py_generate_random_password(PyObject *self, PyObject *args)
+{
+	int min, max;
+	PyObject *ret;
+	char *retstr;
+	if (!PyArg_ParseTuple(args, "ii", &min, &max))
+		return NULL;
+
+	retstr = generate_random_password(NULL, min, max);
+	if (retstr == NULL) {
+		return NULL;
+	}
+	ret = PyString_FromString(retstr);
+	talloc_free(retstr);
+	return ret;
+}
+
 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
 {
 	time_t t;
@@ -636,8 +653,11 @@ static PyObject *py_interface_ips(PyObject *self, PyObject *args)
 
 static PyMethodDef py_misc_methods[] = {
 	{ "generate_random_str", (PyCFunction)py_generate_random_str, METH_VARARGS,
-		"random_password(len) -> string\n"
-		"Generate random password with specified length." },
+		"generate_random_str(len) -> string\n"
+		"Generate random string with specified length." },
+	{ "generate_random_password", (PyCFunction)py_generate_random_password, METH_VARARGS,
+		"generate_random_password(min, max) -> string\n"
+		"Generate random password with a length >= min and <= max." },
 	{ "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
 		"unix2nttime(timestamp) -> nttime" },
 	{ "ldb_set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index def91f3..dfd47b7 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -1149,16 +1149,16 @@ def provision(setup_dir, message, session_info,
     policyguid_dc = policyguid_dc.upper()
 
     if adminpass is None:
-        adminpass = glue.generate_random_str(12)
+        adminpass = glue.generate_random_password(12, 32)
     if krbtgtpass is None:
-        krbtgtpass = glue.generate_random_str(12)
+        krbtgtpass = glue.generate_random_password(128, 255)
     if machinepass is None:
-        machinepass  = glue.generate_random_str(12)
+        machinepass  = glue.generate_random_password(128, 255)
     if dnspass is None:
-        dnspass = glue.generate_random_str(12)
+        dnspass = glue.generate_random_password(128, 255)
     if ldapadminpass is None:
         #Make a new, random password between Samba and it's LDAP server
-        ldapadminpass=glue.generate_random_str(12)        
+        ldapadminpass=glue.generate_random_password(128, 255)
 
     if backend_type is None:
         backend_type = "ldb"
diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c
index 712742b..ec833d0 100644
--- a/source4/smbd/service_named_pipe.c
+++ b/source4/smbd/service_named_pipe.c
@@ -25,9 +25,12 @@
 #include "param/param.h"
 #include "auth/session.h"
 #include "auth/auth_sam_reply.h"
-#include "lib/stream/packet.h"
+#include "lib/socket/socket.h"
+#include "lib/tsocket/tsocket.h"
+#include "libcli/util/tstream.h"
 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
 #include "system/passwd.h"
+#include "system/network.h"
 #include "libcli/raw/smb.h"
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_krb5.h"
@@ -41,224 +44,309 @@ struct named_pipe_socket {
 
 struct named_pipe_connection {
 	struct stream_connection *connection;
-	struct packet_context *packet;
 	const struct named_pipe_socket *pipe_sock;
-	NTSTATUS status;
+	struct tstream_context *tstream;
 };
 
-static void named_pipe_handover_connection(void *private_data)
+static void named_pipe_terminate_connection(struct named_pipe_connection *pipe_conn, const char *reason)
 {
-	struct named_pipe_connection *pipe_conn = talloc_get_type(
-		private_data, struct named_pipe_connection);
-	struct stream_connection *conn = pipe_conn->connection;
+	stream_terminate_connection(pipe_conn->connection, reason);
+}
+
+static NTSTATUS named_pipe_full_request(void *private_data, DATA_BLOB blob, size_t *size)
+{
+	if (blob.length < 8) {
+		return STATUS_MORE_ENTRIES;
+	}
+
+	if (memcmp(NAMED_PIPE_AUTH_MAGIC, &blob.data[4], 4) != 0) {
+		DEBUG(0,("named_pipe_full_request: wrong protocol\n"));
+		*size = blob.length;
+		/* the error will be handled in named_pipe_recv_auth_request */
+		return NT_STATUS_OK;
+	}
+
+	*size = 4 + RIVAL(blob.data, 0);
+	if (*size > blob.length) {
+		return STATUS_MORE_ENTRIES;
+	}
 
-	TEVENT_FD_NOT_WRITEABLE(conn->event.fde);
+	return NT_STATUS_OK;
+}
 
-	packet_set_socket(pipe_conn->packet, NULL);
-	packet_set_event_context(pipe_conn->packet, NULL);
-	packet_set_fde(pipe_conn->packet, NULL);
-	TALLOC_FREE(pipe_conn->packet);
+static void named_pipe_auth_request(struct tevent_req *subreq);
 
-	if (!NT_STATUS_IS_OK(pipe_conn->status)) {
-		stream_terminate_connection(conn, nt_errstr(pipe_conn->status));
+static void named_pipe_accept(struct stream_connection *conn)
+{
+	struct named_pipe_socket *pipe_sock = talloc_get_type(conn->private_data,
+						struct named_pipe_socket);
+	struct named_pipe_connection *pipe_conn;
+	struct tevent_req *subreq;
+	int rc, fd;
+
+	pipe_conn = talloc_zero(conn, struct named_pipe_connection);
+	if (pipe_conn == NULL) {
+		stream_terminate_connection(conn,
+				"named_pipe_accept: out of memory");
 		return;
 	}
 
+	TALLOC_FREE(conn->event.fde);
+
 	/*
-	 * remove the named_pipe layer together with its packet layer
+	 * We have to duplicate the fd, cause it gets closed when the tstream
+	 * is freed and you shouldn't work a fd the tstream is based on.
 	 */
-	conn->ops		= pipe_conn->pipe_sock->ops;
-	conn->private_data	= pipe_conn->pipe_sock->private_data;
-	talloc_unlink(conn, pipe_conn);
+	fd = dup(socket_get_fd(conn->socket));
+	if (fd == -1) {
+		char *reason;
+
+		reason = talloc_asprintf(conn,
+					 "named_pipe_accept: failed to duplicate the file descriptor - %s",
+					 strerror(errno));
+		if (reason == NULL) {
+			reason = strerror(errno);
+		}
+		stream_terminate_connection(conn, reason);
+	}
+	rc = tstream_bsd_existing_socket(pipe_conn,
+					 fd,
+					 &pipe_conn->tstream);
+	if (rc < 0) {
+		stream_terminate_connection(conn,
+				"named_pipe_accept: out of memory");
+		return;
+	}
 
-	/* we're now ready to start receiving events on this stream */
-	TEVENT_FD_READABLE(conn->event.fde);
+	pipe_conn->connection = conn;
+	pipe_conn->pipe_sock = pipe_sock;
+	conn->private_data = pipe_conn;
 
 	/*
-	 * hand over to the real pipe implementation,
-	 * now that we have setup the transport session_info
+	 * The named pipe pdu's have the length as 8 byte (initial_read_size),
+	 * named_pipe_full_request provides the pdu length then.
 	 */
-	conn->ops->accept_connection(conn);
-
-	DEBUG(10,("named_pipe_handover_connection[%s]: succeeded\n",
-	      conn->ops->name));
+	subreq = tstream_read_pdu_blob_send(pipe_conn,
+					    pipe_conn->connection->event.ctx,
+					    pipe_conn->tstream,
+					    8, /* initial_read_size */
+					    named_pipe_full_request,
+					    pipe_conn);
+	if (subreq == NULL) {
+		named_pipe_terminate_connection(pipe_conn,
+				"named_pipe_accept: "
+				"no memory for tstream_read_pdu_blob_send");
+		return;
+	}
+	tevent_req_set_callback(subreq, named_pipe_auth_request, pipe_conn);
 }
 
-static NTSTATUS named_pipe_recv_auth_request(void *private_data,
-					     DATA_BLOB req_blob)
+struct named_pipe_call {
+	struct named_pipe_connection *pipe_conn;
+	DATA_BLOB in;
+	DATA_BLOB out;
+	struct iovec out_iov[1];
+	NTSTATUS status;
+};
+
+static void named_pipe_handover_connection(struct tevent_req *subreq);
+
+static void named_pipe_auth_request(struct tevent_req *subreq)
 {
-	struct named_pipe_connection *pipe_conn = talloc_get_type(
-		private_data, struct named_pipe_connection);
+	struct named_pipe_connection *pipe_conn = tevent_req_callback_data(subreq,
+				      struct named_pipe_connection);
 	struct stream_connection *conn = pipe_conn->connection;
+	struct named_pipe_call *call;
 	enum ndr_err_code ndr_err;
-	struct named_pipe_auth_req req;
 	union netr_Validation val;
 	struct auth_serversupplied_info *server_info;
-	struct named_pipe_auth_rep rep;
-	DATA_BLOB rep_blob;
+	struct named_pipe_auth_req pipe_request;
+	struct named_pipe_auth_rep pipe_reply;
 	NTSTATUS status;
 
-	/*
-	 * make sure nothing happens on the socket untill the
-	 * real implementation takes over
-	 */
-	packet_recv_disable(pipe_conn->packet);
+	call = talloc(pipe_conn, struct named_pipe_call);
+	if (call == NULL) {
+		named_pipe_terminate_connection(pipe_conn,
+				"named_pipe_auth_request: "
+				"no memory for named_pipe_call");
+		return;
+	}
+	call->pipe_conn = pipe_conn;
+
+	status = tstream_read_pdu_blob_recv(subreq,
+					    call,
+					    &call->in);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		const char *reason;
+
+		reason = talloc_asprintf(call, "named_pipe_call_loop: "
+					 "tstream_read_pdu_blob_recv() - %s",
+					 nt_errstr(status));
+		if (reason == NULL) {
+			reason = nt_errstr(status);
+		}
+
+		named_pipe_terminate_connection(pipe_conn, reason);
+		return;
+	}
+
+	DEBUG(10,("Received named_pipe packet of length %lu from %s\n",
+		 (long) call->in.length,
+		 tsocket_address_string(pipe_conn->connection->remote_address, call)));
+	dump_data(11, call->in.data, call->in.length);
 
 	/*
 	 * TODO: check it's a root (uid == 0) pipe
 	 */
 
-	ZERO_STRUCT(rep);
-	rep.level = 0;
-	rep.status = NT_STATUS_INTERNAL_ERROR;
-
-	DEBUG(10,("named_pipe_auth: req_blob.length[%u]\n",
-		  (unsigned int)req_blob.length));
-	dump_data(11, req_blob.data, req_blob.length);
+	ZERO_STRUCT(pipe_reply);
+	pipe_reply.level = 0;
+	pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
 
 	/* parse the passed credentials */
 	ndr_err = ndr_pull_struct_blob_all(
-			&req_blob,
+			&call->in,
 			pipe_conn,
 			lp_iconv_convenience(conn->lp_ctx),
-			&req,
-			(ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
+			&pipe_request,
+			(ndr_pull_flags_fn_t) ndr_pull_named_pipe_auth_req);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-		rep.status = ndr_map_error2ntstatus(ndr_err);
+		pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
 		DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
-			  nt_errstr(rep.status)));
+			  nt_errstr(pipe_reply.status)));
 		goto reply;
 	}
 
 	if (DEBUGLVL(10)) {
-		NDR_PRINT_DEBUG(named_pipe_auth_req, &req);
+		NDR_PRINT_DEBUG(named_pipe_auth_req, &pipe_request);
 	}
 
-	if (strcmp(NAMED_PIPE_AUTH_MAGIC, req.magic) != 0) {
+	if (strcmp(NAMED_PIPE_AUTH_MAGIC, pipe_request.magic) != 0) {
 		DEBUG(2, ("named_pipe_auth_req: invalid magic '%s' != %s\n",
-			  req.magic, NAMED_PIPE_AUTH_MAGIC));
-		rep.status = NT_STATUS_INVALID_PARAMETER;
+			  pipe_request.magic, NAMED_PIPE_AUTH_MAGIC));
+		pipe_reply.status = NT_STATUS_INVALID_PARAMETER;
 		goto reply;
 	}
 
-	switch (req.level) {
+	switch (pipe_request.level) {
 	case 0:
 		/*
 		 * anon connection, we don't create a session info
 		 * and leave it NULL
 		 */
-		rep.level = 0;
-		rep.status = NT_STATUS_OK;
+		pipe_reply.level = 0;
+		pipe_reply.status = NT_STATUS_OK;
 		break;
 	case 1:
-		val.sam3 = &req.info.info1;
-
-		rep.level = 1;
-		rep.status = make_server_info_netlogon_validation(pipe_conn,
-								  "TODO",
-								  3, &val,
-								  &server_info);
-		if (!NT_STATUS_IS_OK(rep.status)) {
+		val.sam3 = &pipe_request.info.info1;
+
+		pipe_reply.level = 1;
+		pipe_reply.status = make_server_info_netlogon_validation(pipe_conn,
+									 "TODO",
+									 3, &val,
+									 &server_info);
+		if (!NT_STATUS_IS_OK(pipe_reply.status)) {
 			DEBUG(2, ("make_server_info_netlogon_validation returned "
-				  "%s\n", nt_errstr(rep.status)));
+				  "%s\n", nt_errstr(pipe_reply.status)));
 			goto reply;
 		}
 
 		/* setup the session_info on the connection */
-		rep.status = auth_generate_session_info(conn,
-							conn->event.ctx,
-							conn->lp_ctx,
-							server_info,
-							&conn->session_info);
-		if (!NT_STATUS_IS_OK(rep.status)) {
+		pipe_reply.status = auth_generate_session_info(conn,
+							       conn->event.ctx,
+							       conn->lp_ctx,
+							       server_info,
+							       &conn->session_info);
+		if (!NT_STATUS_IS_OK(pipe_reply.status)) {
 			DEBUG(2, ("auth_generate_session_info failed: %s\n",


-- 
Samba Shared Repository


More information about the samba-cvs mailing list