From 71e7cdcce26c1ed7504760a94cf51e79b2ec570c Mon Sep 17 00:00:00 2001
From: Ira Cooper <ira@wakeful.net>
Date: Sun, 29 Jan 2012 20:36:05 +0100
Subject: [PATCH] s3-smbd: Fix bug #8724.

Fix bug #8724 - Memory leak in parent smbd on connection.
This is CVE-2012-0817.

Patch have been created by Ira Cooper <ira@wakeful.net> and
Jeremy Allison <jra@samba.org>.
(cherry picked from commit 964620240c83024bea8bbce0bc282b0851513808)
---
 source3/lib/substitute.c |    9 +++++++--
 source3/smbd/server.c    |    6 ++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c
index e72a8c3..68328e5 100644
--- a/source3/lib/substitute.c
+++ b/source3/lib/substitute.c
@@ -195,7 +195,7 @@ void sub_set_smb_name(const char *name)
 }
 
 static char sub_peeraddr[INET6_ADDRSTRLEN];
-static const char *sub_peername = "";
+static const char *sub_peername = NULL;
 static char sub_sockaddr[INET6_ADDRSTRLEN];
 
 void sub_set_socket_ids(const char *peeraddr, const char *peername,
@@ -208,6 +208,11 @@ void sub_set_socket_ids(const char *peeraddr, const char *peername,
 	}
 	strlcpy(sub_peeraddr, addr, sizeof(sub_peeraddr));
 
+	if (sub_peername != NULL &&
+			sub_peername != sub_peeraddr) {
+		free(discard_const_p(char,sub_peername));
+		sub_peername = NULL;
+	}
 	sub_peername = SMB_STRDUP(peername);
 	if (sub_peername == NULL) {
 		sub_peername = sub_peeraddr;
@@ -646,7 +651,7 @@ static char *alloc_sub_basic(const char *smb_name, const char *domain_name,
 			break;
 		case 'M' :
 			a_string = realloc_string_sub(a_string, "%M",
-						      sub_peername);
+						      sub_peername ? sub_peername : "");
 			break;
 		case 'R' :
 			a_string = realloc_string_sub(a_string, "%R", remote_proto);
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 8ac0511..db68ace 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -64,6 +64,12 @@ static void smbd_set_server_fd(int fd)
 	 * name, default to its address.
 	 */
 
+	if (sconn->client_id.name != NULL &&
+	    sconn->client_id.name != sconn->client_id.addr) {
+		talloc_free(discard_const_p(char, sconn->client_id.name));
+		sconn->client_id.name = NULL;
+	}
+
 	client_addr(fd, sconn->client_id.addr, sizeof(sconn->client_id.addr));
 
 	name = client_name(sconn->sock);
-- 
1.7.1