ports/net/samba47/files/0001-Freenas-master-mdns-fixes-22.patch
Timur I. Bakeyev 3284397fb5 Update Samba ports to address multiple CVE vulnerabilities
Security:	CVE-2018-1139
		CVE-2018-1140
		CVE-2018-10858
		CVE-2018-10918
		CVE-2018-10919
Sponsored by:	iXsystems Inc.
2018-08-14 15:09:36 +00:00

375 lines
10 KiB
Diff

From 923bc7a1afeb0b920e60e14846987ae1d2d7dca4 Mon Sep 17 00:00:00 2001
From: John Hixson <john@ixsystems.com>
Date: Thu, 7 Dec 2017 09:36:32 -0500
Subject: [PATCH] Freenas/master mdns fixes (#22)
* mDNS fixes for Samba (work in progress).
* Fix mDNS - Can advertise on individual interfaces
* Fix mDNS browsing in smbclient
Signed-off-by: Timur I. Bakeyev <timur@iXsystems.com>
---
source3/client/dnsbrowse.c | 17 ++--
source3/smbd/dnsregister.c | 193 +++++++++++++++++++++++++++++----------------
2 files changed, 137 insertions(+), 73 deletions(-)
diff --git a/source3/client/dnsbrowse.c b/source3/client/dnsbrowse.c
index efd57d42d88..83aef966d2a 100644
--- a/source3/client/dnsbrowse.c
+++ b/source3/client/dnsbrowse.c
@@ -39,6 +39,7 @@ struct mdns_smbsrv_result
struct mdns_browse_state
{
struct mdns_smbsrv_result *listhead; /* Browse result list head */
+ TALLOC_CTX * ctx;
int browseDone;
};
@@ -64,7 +65,7 @@ static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
struct timeval tv;
DNSServiceErrorType err;
- TALLOC_CTX * ctx = talloc_tos();
+ TALLOC_CTX * ctx = talloc_new(NULL);
err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
browsesrv->ifIndex,
@@ -91,7 +91,7 @@ static void do_smb_resolve(struct mdns_s
}
}
- TALLOC_FREE(fdset);
+ TALLOC_FREE(ctx);
DNSServiceRefDeallocate(mdns_conn_sdref);
}
@@ -124,18 +125,19 @@ do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
return;
}
- bresult = talloc_array(talloc_tos(), struct mdns_smbsrv_result, 1);
+ bresult = talloc_array(bstatep->ctx, struct mdns_smbsrv_result, 1);
if (bresult == NULL) {
return;
}
+ bresult->nextResult = NULL;
if (bstatep->listhead != NULL) {
bresult->nextResult = bstatep->listhead;
}
- bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
- bresult->regType = talloc_strdup(talloc_tos(), regtype);
- bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
+ bresult->serviceName = talloc_strdup(bstatep->ctx, serviceName);
+ bresult->regType = talloc_strdup(bstatep->ctx, regtype);
+ bresult->domain = talloc_strdup(bstatep->ctx, replyDomain);
bresult->ifIndex = interfaceIndex;
bstatep->listhead = bresult;
}
@@ -151,10 +153,13 @@ int do_smb_browse(void)
DNSServiceRef mdns_conn_sdref = NULL;
DNSServiceErrorType err;
- TALLOC_CTX * ctx = talloc_stackframe();
+ TALLOC_CTX * ctx = talloc_new(NULL);
ZERO_STRUCT(bstate);
+ bstate.ctx = ctx;
+ bstate.listhead = NULL;
+
err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
do_smb_browse_reply, &bstate);
diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c
index df189001a09..f25b60f4611 100644
--- a/source3/smbd/dnsregister.c
+++ b/source3/smbd/dnsregister.c
@@ -36,85 +36,111 @@
#include <dns_sd.h>
struct dns_reg_state {
- struct tevent_context *event_ctx;
- uint16_t port;
- DNSServiceRef srv_ref;
- struct tevent_timer *te;
- int fd;
- struct tevent_fd *fde;
+ int count;
+ struct reg_state {
+ DNSServiceRef srv_ref;
+ TALLOC_CTX *mem_ctx;
+ struct tevent_context *event_ctx;
+ struct tevent_timer *te;
+ struct tevent_fd *fde;
+ uint16_t port;
+ int if_index;
+ int fd;
+ } *drs;
};
-static int dns_reg_state_destructor(struct dns_reg_state *dns_state)
+static void dns_register_smbd_retry(struct tevent_context *ctx,
+ struct tevent_timer *te,
+ struct timeval now,
+ void *private_data);
+static void dns_register_smbd_fde_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags,
+ void *private_data);
+
+
+static int reg_state_destructor(struct reg_state *state)
{
- if (dns_state->srv_ref != NULL) {
+ if (state == NULL) {
+ return -1;
+ }
+
+ if (state->srv_ref != NULL) {
/* Close connection to the mDNS daemon */
- DNSServiceRefDeallocate(dns_state->srv_ref);
- dns_state->srv_ref = NULL;
+ DNSServiceRefDeallocate(state->srv_ref);
+ state->srv_ref = NULL;
}
/* Clear event handler */
- TALLOC_FREE(dns_state->te);
- TALLOC_FREE(dns_state->fde);
- dns_state->fd = -1;
+ TALLOC_FREE(state->te);
+ TALLOC_FREE(state->fde);
+ state->fd = -1;
return 0;
}
-static void dns_register_smbd_retry(struct tevent_context *ctx,
- struct tevent_timer *te,
- struct timeval now,
- void *private_data);
-static void dns_register_smbd_fde_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags,
- void *private_data);
-static bool dns_register_smbd_schedule(struct dns_reg_state *dns_state,
+static bool dns_register_smbd_schedule(struct reg_state *state,
struct timeval tval)
{
- dns_reg_state_destructor(dns_state);
+ reg_state_destructor(state);
- dns_state->te = tevent_add_timer(dns_state->event_ctx,
- dns_state,
+ state->te = tevent_add_timer(state->event_ctx,
+ state->mem_ctx,
tval,
dns_register_smbd_retry,
- dns_state);
- if (!dns_state->te) {
+ state);
+ if (!state->te) {
return false;
}
return true;
}
+static void dns_register_smbd_callback(DNSServiceRef service,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ const char *name,
+ const char *type,
+ const char *domain,
+ void *context)
+{
+ if (errorCode != kDNSServiceErr_NoError) {
+ DEBUG(6, ("error=%d\n", errorCode));
+ } else {
+ DEBUG(6, ("%-15s %s.%s%s\n", "REGISTER", name, type, domain));
+ }
+}
+
static void dns_register_smbd_retry(struct tevent_context *ctx,
struct tevent_timer *te,
struct timeval now,
void *private_data)
{
- struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
- struct dns_reg_state);
+ struct reg_state *state = (struct reg_state *)private_data;
DNSServiceErrorType err;
- dns_reg_state_destructor(dns_state);
+ reg_state_destructor(state);
- DEBUG(6, ("registering _smb._tcp service on port %d\n",
- dns_state->port));
+ DEBUG(6, ("registering _smb._tcp service on port %d index %d\n",
+ state->port, state->if_index));
/* Register service with DNS. Connects with the mDNS
* daemon running on the local system to perform DNS
* service registration.
*/
- err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */,
- kDNSServiceInterfaceIndexAny,
- NULL /* service name */,
- "_smb._tcp" /* service type */,
- NULL /* domain */,
- "" /* SRV target host name */,
- htons(dns_state->port),
- 0 /* TXT record len */,
- NULL /* TXT record data */,
- NULL /* callback func */,
- NULL /* callback context */);
+ err = DNSServiceRegister(&state->srv_ref,
+ 0 /* flags */,
+ state->if_index /* interface index */,
+ NULL /* service name */,
+ "_smb._tcp" /* service type */,
+ NULL /* domain */,
+ "" /* SRV target host name */,
+ htons(state->port) /* port */,
+ 0 /* TXT record len */,
+ NULL /* TXT record data */,
+ dns_register_smbd_callback /* callback func */,
+ NULL /* callback context */);
if (err != kDNSServiceErr_NoError) {
/* Failed to register service. Schedule a re-try attempt.
@@ -123,24 +149,24 @@ static void dns_register_smbd_retry(struct tevent_context *ctx,
goto retry;
}
- dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref);
- if (dns_state->fd == -1) {
+ state->fd = DNSServiceRefSockFD(state->srv_ref);
+ if (state->fd == -1) {
goto retry;
}
- dns_state->fde = tevent_add_fd(dns_state->event_ctx,
- dns_state,
- dns_state->fd,
- TEVENT_FD_READ,
- dns_register_smbd_fde_handler,
- dns_state);
- if (!dns_state->fde) {
+ state->fde = tevent_add_fd(state->event_ctx,
+ state->mem_ctx,
+ state->fd,
+ TEVENT_FD_READ,
+ dns_register_smbd_fde_handler,
+ state);
+ if (!state->fde) {
goto retry;
}
return;
retry:
- dns_register_smbd_schedule(dns_state,
+ dns_register_smbd_schedule(state,
timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
}
@@ -150,44 +176,77 @@ static void dns_register_smbd_fde_handler(struct tevent_context *ev,
uint16_t flags,
void *private_data)
{
- struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
- struct dns_reg_state);
+ struct reg_state *state = (struct reg_state *)private_data;
DNSServiceErrorType err;
- err = DNSServiceProcessResult(dns_state->srv_ref);
+ err = DNSServiceProcessResult(state->srv_ref);
if (err != kDNSServiceErr_NoError) {
- DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
- err));
+ DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n", err));
goto retry;
}
- talloc_free(dns_state);
return;
retry:
- dns_register_smbd_schedule(dns_state,
- timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
+ dns_register_smbd_schedule(state, timeval_zero());
}
+static int dns_reg_state_destructor(struct dns_reg_state *state)
+{
+ if (state != NULL) {
+ talloc_free(state);
+ }
+ return 0;
+}
+
+
bool smbd_setup_mdns_registration(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
uint16_t port)
{
struct dns_reg_state *dns_state;
+ bool bind_all = true;
+ int i;
dns_state = talloc_zero(mem_ctx, struct dns_reg_state);
- if (dns_state == NULL) {
+ if (dns_state == NULL)
+ return false;
+
+ if (lp_interfaces() && lp_bind_interfaces_only())
+ bind_all = false;
+
+ dns_state->count = iface_count();
+ if (dns_state->count <= 0 || bind_all == true)
+ dns_state->count = 1;
+
+ dns_state->drs = talloc_array(mem_ctx, struct reg_state, dns_state->count);
+ if (dns_state->drs == NULL) {
+ talloc_free(dns_state);
return false;
}
- dns_state->event_ctx = ev;
- dns_state->port = port;
- dns_state->fd = -1;
- talloc_set_destructor(dns_state, dns_reg_state_destructor);
+ for (i = 0; i < dns_state->count; i++) {
+ struct interface *iface = get_interface(i);
+ struct reg_state *state = &dns_state->drs[i];
+
+ state->mem_ctx = mem_ctx;
+ state->srv_ref = NULL;
+ state->event_ctx = ev;
+ state->te = NULL;
+ state->fde = NULL;
+ state->port = port;
+ state->fd = -1;
+
+ state->if_index = bind_all ? kDNSServiceInterfaceIndexAny : iface->if_index;
- return dns_register_smbd_schedule(dns_state, timeval_zero());
+ dns_register_smbd_schedule(&dns_state->drs[i], timeval_zero());
+ }
+
+ talloc_set_destructor(dns_state, dns_reg_state_destructor);
+ return true;
}
+
#else /* WITH_DNSSD_SUPPORT */
bool smbd_setup_mdns_registration(struct tevent_context *ev,
--
2.14.2