resolves: RHEL-61732 - Update to version 7.1
This commit is contained in:
parent
a701777a99
commit
5cc75f6ad3
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,3 +27,4 @@ cifs-utils-4.6.tar.bz2
|
|||||||
/cifs-utils-6.11.tar.bz2
|
/cifs-utils-6.11.tar.bz2
|
||||||
/cifs-utils-6.14.tar.bz2
|
/cifs-utils-6.14.tar.bz2
|
||||||
/cifs-utils-7.0.tar.bz2
|
/cifs-utils-7.0.tar.bz2
|
||||||
|
/cifs-utils-7.1.tar.bz2
|
||||||
|
@ -1,781 +0,0 @@
|
|||||||
From 770e891a8b7ad53d4d700e08cf8d3154028b4588 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Voit <david.voit@gmail.com>
|
|
||||||
Date: Wed, 3 Apr 2024 07:24:48 +0200
|
|
||||||
Subject: [PATCH] Implement CLDAP Ping to find the closest site
|
|
||||||
|
|
||||||
For domain based DFS we always need to contact the domain controllers.
|
|
||||||
On setups, which are using bigger AD installations you could get random dc on the other side of the world,
|
|
||||||
if you don't have site support. This can lead to network timeouts and other problems.
|
|
||||||
|
|
||||||
CLDAP-Ping uses ASN.1 + UDP (CLDAP) and custom-DCE encoding including DName compressions without
|
|
||||||
field separation. Finally after finding the sitename we now need to do a DNS SRV lookups to find
|
|
||||||
the correct IPs to our closest site and fill up the remaining IPs from the global list.
|
|
||||||
|
|
||||||
Signed-off-by: David Voit <david.voit@gmail.com>
|
|
||||||
---
|
|
||||||
Makefile.am | 15 ++-
|
|
||||||
cldap_ping.c | 345 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
cldap_ping.h | 14 ++
|
|
||||||
mount.cifs.c | 5 +-
|
|
||||||
resolve_host.c | 256 ++++++++++++++++++++++++++++++++----
|
|
||||||
resolve_host.h | 6 +-
|
|
||||||
6 files changed, 604 insertions(+), 37 deletions(-)
|
|
||||||
create mode 100644 cldap_ping.c
|
|
||||||
create mode 100644 cldap_ping.h
|
|
||||||
|
|
||||||
Index: cifs-utils/Makefile.am
|
|
||||||
===================================================================
|
|
||||||
--- cifs-utils.orig/Makefile.am
|
|
||||||
+++ cifs-utils/Makefile.am
|
|
||||||
@@ -3,8 +3,8 @@ ACLOCAL_AMFLAGS = -I aclocal
|
|
||||||
|
|
||||||
root_sbindir = $(ROOTSBINDIR)
|
|
||||||
root_sbin_PROGRAMS = mount.cifs
|
|
||||||
-mount_cifs_SOURCES = mount.cifs.c mtab.c resolve_host.c util.c
|
|
||||||
-mount_cifs_LDADD = $(LIBCAP) $(CAPNG_LDADD) $(RT_LDADD)
|
|
||||||
+mount_cifs_SOURCES = mount.cifs.c mtab.c $(resolve_hosts_SOURCES) util.c
|
|
||||||
+mount_cifs_LDADD = $(LIBCAP) $(CAPNG_LDADD) $(RT_LDADD) $(resolve_hosts_LDADD)
|
|
||||||
include_HEADERS = cifsidmap.h
|
|
||||||
rst_man_pages = mount.cifs.8
|
|
||||||
|
|
||||||
@@ -28,6 +28,9 @@ bin_PROGRAMS =
|
|
||||||
bin_SCRIPTS =
|
|
||||||
sbin_PROGRAMS =
|
|
||||||
|
|
||||||
+resolve_hosts_SOURCES = data_blob.c asn1.c cldap_ping.c resolve_host.c
|
|
||||||
+resolve_hosts_LDADD = -ltalloc -lresolv
|
|
||||||
+
|
|
||||||
if CONFIG_CIFSUPCALL
|
|
||||||
sbin_PROGRAMS += cifs.upcall
|
|
||||||
cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c
|
|
||||||
@@ -43,8 +46,8 @@ endif
|
|
||||||
|
|
||||||
if CONFIG_CIFSCREDS
|
|
||||||
bin_PROGRAMS += cifscreds
|
|
||||||
-cifscreds_SOURCES = cifscreds.c cifskey.c resolve_host.c util.c
|
|
||||||
-cifscreds_LDADD = -lkeyutils
|
|
||||||
+cifscreds_SOURCES = cifscreds.c cifskey.c $(resolve_hosts_SOURCES) util.c
|
|
||||||
+cifscreds_LDADD = -lkeyutils $(resolve_hosts_LDADD)
|
|
||||||
|
|
||||||
rst_man_pages += cifscreds.1
|
|
||||||
|
|
||||||
@@ -105,8 +108,8 @@ endif
|
|
||||||
if CONFIG_PAM
|
|
||||||
pam_PROGRAMS = pam_cifscreds.so
|
|
||||||
rst_man_pages += pam_cifscreds.8
|
|
||||||
-pam_cifscreds.so: pam_cifscreds.c cifskey.c resolve_host.c util.c
|
|
||||||
- $(CC) $(DEFS) $(CFLAGS) $(AM_CFLAGS) $(LDFLAGS) -shared -fpic -o $@ $+ -lpam -lkeyutils
|
|
||||||
+pam_cifscreds.so: pam_cifscreds.c cifskey.c $(resolve_hosts_SOURCES) util.c
|
|
||||||
+ $(CC) $(DEFS) $(CFLAGS) $(AM_CFLAGS) $(LDFLAGS) -shared -fpic -o $@ $+ -lpam -lkeyutils $(resolve_hosts_LDADD)
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
Index: cifs-utils/cldap_ping.c
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ cifs-utils/cldap_ping.c
|
|
||||||
@@ -0,0 +1,345 @@
|
|
||||||
+/*
|
|
||||||
+ * CLDAP Ping to find closest ClientSiteName
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2024 David Voit (david.voit@gmail.com)
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; either version 3 of the License, or
|
|
||||||
+ * (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * This program is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
+ * GNU General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU General Public License
|
|
||||||
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <talloc.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <sys/socket.h>
|
|
||||||
+#include <arpa/inet.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <resolv.h>
|
|
||||||
+#include <stdbool.h>
|
|
||||||
+#include "data_blob.h"
|
|
||||||
+#include "asn1.h"
|
|
||||||
+#include "cldap_ping.h"
|
|
||||||
+
|
|
||||||
+#define LDAP_DNS_DOMAIN "DnsDomain"
|
|
||||||
+#define LDAP_DNS_DOMAIN_LEN strlen(LDAP_DNS_DOMAIN)
|
|
||||||
+#define LDAP_NT_VERSION "NtVer"
|
|
||||||
+#define LDAP_NT_VERSION_LEN strlen(LDAP_NT_VERSION)
|
|
||||||
+#define LDAP_ATTRIBUTE_NETLOGON "NetLogon"
|
|
||||||
+#define LDAP_ATTRIBUTE_NETLOGON_LEN strlen(LDAP_ATTRIBUTE_NETLOGON)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+// Parse a ASN.1 BER tag size-field, returns start of payload of tag
|
|
||||||
+char *parse_ber_size(char *buf, size_t *tag_size) {
|
|
||||||
+ size_t size = *buf & 0xff;
|
|
||||||
+ char *ret = (buf + 1);
|
|
||||||
+ if (size >= 0x81) {
|
|
||||||
+ switch (size) {
|
|
||||||
+ case 0x81:
|
|
||||||
+ size = *ret & 0xff;
|
|
||||||
+ ret += 1;
|
|
||||||
+ break;
|
|
||||||
+ case 0x82:
|
|
||||||
+ size = (*ret << 8) | (*(ret + 1) & 0xff);
|
|
||||||
+ ret += 2;
|
|
||||||
+ break;
|
|
||||||
+ case 0x83:
|
|
||||||
+ size = (*ret << 16) | (*(ret + 1) << 8) | (*(ret + 2) & 0xff);
|
|
||||||
+ ret += 3;
|
|
||||||
+ break;
|
|
||||||
+ case 0x84:
|
|
||||||
+ size = (*ret << 24) | (*(ret + 1) << 16) | (*(ret + 2) << 8) | (*(ret + 3) & 0xff);
|
|
||||||
+ ret += 4;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *tag_size = size;
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// simple wrapper over dn_expand which also calculates the new offset for the next compressed dn
|
|
||||||
+int read_dns_string(char *buf, size_t buf_size, char *dest, size_t dest_size, size_t *offset) {
|
|
||||||
+ int compressed_length = dn_expand((u_char *)buf, (u_char *)buf+buf_size, (u_char *)buf + *offset, dest, (int)dest_size);
|
|
||||||
+ if (compressed_length < 0) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *offset = *offset+compressed_length;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// LDAP request for: (&(DnsDomain=DOMAIN_HERE)(NtVer=\\06\\00\\00\\00))
|
|
||||||
+ASN1_DATA *generate_cldap_query(char *domain) {
|
|
||||||
+ ASN1_DATA *data;
|
|
||||||
+ TALLOC_CTX *mem_ctx = talloc_init("cldap");
|
|
||||||
+
|
|
||||||
+ data = asn1_init(mem_ctx);
|
|
||||||
+ asn1_push_tag(data, ASN1_SEQUENCE(0));
|
|
||||||
+
|
|
||||||
+ // Message id
|
|
||||||
+ asn1_push_tag(data, ASN1_INTEGER);
|
|
||||||
+ asn1_write_uint8(data, 1);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // SearchRequest
|
|
||||||
+ asn1_push_tag(data, ASN1_APPLICATION(3));
|
|
||||||
+
|
|
||||||
+ // empty baseObject
|
|
||||||
+ asn1_push_tag(data, ASN1_OCTET_STRING);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // scope 0 = baseObject
|
|
||||||
+ asn1_push_tag(data, ASN1_ENUMERATED);
|
|
||||||
+ asn1_write_uint8(data, 0);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // derefAliasses 0=neverDerefAlias
|
|
||||||
+ asn1_push_tag(data, ASN1_ENUMERATED);
|
|
||||||
+ asn1_write_uint8(data, 0);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // sizeLimit
|
|
||||||
+ asn1_push_tag(data, ASN1_INTEGER);
|
|
||||||
+ asn1_write_uint8(data, 0);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // timeLimit
|
|
||||||
+ asn1_push_tag(data, ASN1_INTEGER);
|
|
||||||
+ asn1_write_uint8(data, 0);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // typesOnly
|
|
||||||
+ asn1_push_tag(data, ASN1_BOOLEAN);
|
|
||||||
+ asn1_write_uint8(data, 0);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // AND
|
|
||||||
+ asn1_push_tag(data, ASN1_CONTEXT(0));
|
|
||||||
+ // equalityMatch
|
|
||||||
+ asn1_push_tag(data, ASN1_CONTEXT(3));
|
|
||||||
+ asn1_write_OctetString(data, LDAP_DNS_DOMAIN, LDAP_DNS_DOMAIN_LEN);
|
|
||||||
+ asn1_write_OctetString(data, domain, strlen(domain));
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // equalityMatch
|
|
||||||
+ asn1_push_tag(data, ASN1_CONTEXT(3));
|
|
||||||
+ asn1_write_OctetString(data, LDAP_NT_VERSION, LDAP_NT_VERSION_LEN);
|
|
||||||
+ // Bitmask NETLOGON_NT_VERSION_5 & NETLOGON_NT_VERSION_5EX -> To get NETLOGON_SAM_LOGON_RESPONSE_EX as response
|
|
||||||
+ asn1_write_OctetString(data, "\x06\x00\x00\x00", 4);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // End AND
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ asn1_push_tag(data, ASN1_SEQUENCE(0));
|
|
||||||
+ asn1_write_OctetString(data, LDAP_ATTRIBUTE_NETLOGON, LDAP_ATTRIBUTE_NETLOGON_LEN);
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ // End SearchRequest
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+ // End Sequence
|
|
||||||
+ asn1_pop_tag(data);
|
|
||||||
+
|
|
||||||
+ return data;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// Input is a cldap response, output is a pointer to the NETLOGON_SAM_LOGON_RESPONSE_EX payload
|
|
||||||
+ssize_t extract_netlogon_section(char *buffer, size_t buffer_size, char **netlogon_payload) {
|
|
||||||
+ size_t ber_size;
|
|
||||||
+ size_t netlogon_payload_size;
|
|
||||||
+ // Not enough space to read initial sequence - not an correct cldap response
|
|
||||||
+ if (buffer_size < 7) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Sequence tag
|
|
||||||
+ if (*buffer != 0x30) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *message_id_tag = parse_ber_size(buffer + 1, &ber_size);
|
|
||||||
+
|
|
||||||
+ if (ber_size > buffer_size) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (*message_id_tag != 0x02) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *message_id = parse_ber_size(message_id_tag + 1, &ber_size);
|
|
||||||
+
|
|
||||||
+ if (ber_size != 1 || *message_id != 1) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // SearchResultEntry
|
|
||||||
+ if (*(message_id+1) != 0x64) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *object_name_tag = parse_ber_size(message_id+2, &ber_size);
|
|
||||||
+ if (object_name_tag == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *object_name = parse_ber_size(object_name_tag+1, &ber_size);
|
|
||||||
+ if (object_name == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (*object_name_tag != 4 || ber_size != 0) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *partial_attribute_list_tag = parse_ber_size(object_name+1, &ber_size);
|
|
||||||
+ if (partial_attribute_list_tag == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (*partial_attribute_list_tag != 0x30) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ char *partial_attribute_tag = parse_ber_size(partial_attribute_list_tag+1, &ber_size);
|
|
||||||
+ if (partial_attribute_tag == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *attribute_name = parse_ber_size(partial_attribute_tag+1, &ber_size);
|
|
||||||
+ if (attribute_name == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (ber_size != LDAP_ATTRIBUTE_NETLOGON_LEN) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (strncasecmp(LDAP_ATTRIBUTE_NETLOGON, attribute_name, LDAP_ATTRIBUTE_NETLOGON_LEN) != 0) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // SET
|
|
||||||
+ if (*(attribute_name+LDAP_ATTRIBUTE_NETLOGON_LEN) != 0x31) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *start_of_data = parse_ber_size(attribute_name+LDAP_ATTRIBUTE_NETLOGON_LEN+1, &ber_size);
|
|
||||||
+ if (start_of_data == NULL) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // octat-string of NetLogon data
|
|
||||||
+ if (*start_of_data != '\x04') {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *netlogon_payload = parse_ber_size(start_of_data + 1, &netlogon_payload_size);
|
|
||||||
+
|
|
||||||
+ if (*netlogon_payload == NULL) {
|
|
||||||
+ *netlogon_payload = NULL;
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_LDAP;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return (ssize_t)netlogon_payload_size;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int netlogon_get_client_site(char *netlogon_response, size_t netlogon_size, char *sitename) {
|
|
||||||
+ // 24 mandatory bytes
|
|
||||||
+ if (netlogon_size < 25) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_NETLOGON;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // LOGON_SAM_PAUSE_RESPONSE_EX -> Netlogon service is not in-sync try next dc instead
|
|
||||||
+ if (*netlogon_response == 0x18 && *(netlogon_response + 1) == 0x00) {
|
|
||||||
+ return CLDAP_PING_TRYNEXT;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // NETLOGON_SAM_LOGON_RESPONSE_EX Opcode: 0x17
|
|
||||||
+ if (*netlogon_response != 0x17 || *(netlogon_response + 1) != 0x00) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_NETLOGON;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // skip over sbz, ds_flags and domain_guid
|
|
||||||
+ // and start directly at variable string portion of NETLOGON_SAM_LOGON_RESPONSE_EX
|
|
||||||
+ size_t offset = 24;
|
|
||||||
+
|
|
||||||
+ for (int i=0; i < 8; i++) {
|
|
||||||
+ // iterate over DnsForestName, DnsDomainName, NetbiosDomainName, NetbiosComputerName, UserName, DcSiteName
|
|
||||||
+ // to finally get to our desired ClientSiteName field
|
|
||||||
+ if (read_dns_string(netlogon_response, netlogon_size, sitename, MAXCDNAME, &offset) < 0) {
|
|
||||||
+ return CLDAP_PING_PARSE_ERROR_NETLOGON;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int cldap_ping(char *domain, sa_family_t family, void *addr, char *site_name) {
|
|
||||||
+ char buffer[8196];
|
|
||||||
+ ssize_t response_size;
|
|
||||||
+ char *netlogon_response;
|
|
||||||
+ ssize_t netlogon_size;
|
|
||||||
+ struct sockaddr_storage socketaddr;
|
|
||||||
+ size_t addr_size;
|
|
||||||
+ int sock = socket(family, SOCK_DGRAM, 0);
|
|
||||||
+ if (sock < 0) {
|
|
||||||
+ return CLDAP_PING_NETWORK_ERROR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ASN1_DATA *data = generate_cldap_query(domain);
|
|
||||||
+
|
|
||||||
+ if (family == AF_INET6) {
|
|
||||||
+ addr_size = sizeof(struct sockaddr_in6);
|
|
||||||
+ bzero((void *) &socketaddr, addr_size);
|
|
||||||
+ socketaddr.ss_family = AF_INET6;
|
|
||||||
+ ((struct sockaddr_in6 *)&socketaddr)->sin6_addr = *((struct in6_addr*)addr);
|
|
||||||
+ ((struct sockaddr_in6 *)&socketaddr)->sin6_port = htons(389);
|
|
||||||
+ } else {
|
|
||||||
+ addr_size = sizeof(struct sockaddr_in);
|
|
||||||
+ bzero((void *) &socketaddr, addr_size);
|
|
||||||
+ socketaddr.ss_family = AF_INET;
|
|
||||||
+ ((struct sockaddr_in *)&socketaddr)->sin_addr = *((struct in_addr*)addr);
|
|
||||||
+ ((struct sockaddr_in *)&socketaddr)->sin_port = htons(389);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ struct timeval timeout = {.tv_sec = 2, .tv_usec = 0};
|
|
||||||
+ if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
|
|
||||||
+ return CLDAP_PING_NETWORK_ERROR;
|
|
||||||
+ }
|
|
||||||
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
|
|
||||||
+ return CLDAP_PING_NETWORK_ERROR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sendto(sock, data->data, data->length, 0, (struct sockaddr *)&socketaddr, addr_size) < 0) {
|
|
||||||
+ close(sock);
|
|
||||||
+ return CLDAP_PING_TRYNEXT;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ asn1_free(data);
|
|
||||||
+ response_size = recv(sock, buffer, sizeof(buffer), 0);
|
|
||||||
+ close(sock);
|
|
||||||
+
|
|
||||||
+ if (response_size < 0) {
|
|
||||||
+ return CLDAP_PING_TRYNEXT;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ netlogon_size = extract_netlogon_section(buffer, response_size, &netlogon_response);
|
|
||||||
+ if (netlogon_size < 0) {
|
|
||||||
+ return (int)netlogon_size;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return netlogon_get_client_site(netlogon_response, netlogon_size, site_name);
|
|
||||||
+}
|
|
||||||
Index: cifs-utils/cldap_ping.h
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ cifs-utils/cldap_ping.h
|
|
||||||
@@ -0,0 +1,14 @@
|
|
||||||
+#ifndef _CLDAP_PING_H_
|
|
||||||
+#define _CLDAP_PING_H_
|
|
||||||
+
|
|
||||||
+#define CLDAP_PING_NETWORK_ERROR -1
|
|
||||||
+#define CLDAP_PING_TRYNEXT -2
|
|
||||||
+#define CLDAP_PING_PARSE_ERROR_LDAP -3
|
|
||||||
+#define CLDAP_PING_PARSE_ERROR_NETLOGON -4
|
|
||||||
+
|
|
||||||
+// returns CLDAP_PING_TRYNEXT if you should use another dc
|
|
||||||
+// any other error code < 0 is a fatal error
|
|
||||||
+// site_name must be of MAXCDNAME size!
|
|
||||||
+int cldap_ping(char *domain, sa_family_t family, void *addr, char *site_name);
|
|
||||||
+
|
|
||||||
+#endif /* _CLDAP_PING_H_ */
|
|
||||||
Index: cifs-utils/mount.cifs.c
|
|
||||||
===================================================================
|
|
||||||
--- cifs-utils.orig/mount.cifs.c
|
|
||||||
+++ cifs-utils/mount.cifs.c
|
|
||||||
@@ -1889,8 +1889,11 @@ assemble_mountinfo(struct parsed_mount_i
|
|
||||||
if (rc)
|
|
||||||
goto assemble_exit;
|
|
||||||
|
|
||||||
- if (parsed_info->addrlist[0] == '\0')
|
|
||||||
+ if (parsed_info->addrlist[0] == '\0') {
|
|
||||||
rc = resolve_host(parsed_info->host, parsed_info->addrlist);
|
|
||||||
+ if (rc == 0 && parsed_info->verboseflag)
|
|
||||||
+ fprintf(stderr, "Host \"%s\" resolved to the following IP addresses: %s\n", parsed_info->host, parsed_info->addrlist);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
switch (rc) {
|
|
||||||
case EX_USAGE:
|
|
||||||
Index: cifs-utils/resolve_host.c
|
|
||||||
===================================================================
|
|
||||||
--- cifs-utils.orig/resolve_host.c
|
|
||||||
+++ cifs-utils/resolve_host.c
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Jeff Layton (jlayton@samba.org)
|
|
||||||
* Copyright (C) 2010 Igor Druzhinin (jaxbrigs@gmail.com)
|
|
||||||
+ * Copyright (C) 2024 David Voit (david.voit@gmail.com)
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
@@ -27,15 +28,16 @@
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
+#include <resolv.h>
|
|
||||||
#include "mount.h"
|
|
||||||
#include "util.h"
|
|
||||||
+#include "cldap_ping.h"
|
|
||||||
#include "resolve_host.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* resolve hostname to comma-separated list of address(es)
|
|
||||||
*/
|
|
||||||
-int resolve_host(const char *host, char *addrstr)
|
|
||||||
-{
|
|
||||||
+int resolve_host(const char *host, char *addrstr) {
|
|
||||||
int rc;
|
|
||||||
/* 10 for max width of decimal scopeid */
|
|
||||||
char tmpbuf[NI_MAXHOST + 1 + 10 + 1];
|
|
||||||
@@ -44,6 +46,7 @@ int resolve_host(const char *host, char
|
|
||||||
struct addrinfo *addrlist, *addr;
|
|
||||||
struct sockaddr_in *sin;
|
|
||||||
struct sockaddr_in6 *sin6;
|
|
||||||
+ size_t count_v4 = 0, count_v6 = 0;
|
|
||||||
|
|
||||||
rc = getaddrinfo(host, NULL, NULL, &addrlist);
|
|
||||||
if (rc != 0)
|
|
||||||
@@ -59,34 +62,45 @@ int resolve_host(const char *host, char
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (addr->ai_addr->sa_family) {
|
|
||||||
- case AF_INET6:
|
|
||||||
- sin6 = (struct sockaddr_in6 *)addr->ai_addr;
|
|
||||||
- ipaddr = inet_ntop(AF_INET6, &sin6->sin6_addr, tmpbuf,
|
|
||||||
- sizeof(tmpbuf));
|
|
||||||
- if (!ipaddr) {
|
|
||||||
- rc = EX_SYSERR;
|
|
||||||
- goto resolve_host_out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (sin6->sin6_scope_id) {
|
|
||||||
- len = strnlen(tmpbuf, sizeof(tmpbuf));
|
|
||||||
- snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%%%u",
|
|
||||||
- sin6->sin6_scope_id);
|
|
||||||
- }
|
|
||||||
- break;
|
|
||||||
- case AF_INET:
|
|
||||||
- sin = (struct sockaddr_in *)addr->ai_addr;
|
|
||||||
- ipaddr = inet_ntop(AF_INET, &sin->sin_addr, tmpbuf,
|
|
||||||
- sizeof(tmpbuf));
|
|
||||||
- if (!ipaddr) {
|
|
||||||
- rc = EX_SYSERR;
|
|
||||||
- goto resolve_host_out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- break;
|
|
||||||
- default:
|
|
||||||
- addr = addr->ai_next;
|
|
||||||
- continue;
|
|
||||||
+ case AF_INET6:
|
|
||||||
+ count_v6++;
|
|
||||||
+ if (count_v6 + count_v4 > MAX_ADDRESSES) {
|
|
||||||
+ addr = addr->ai_next;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sin6 = (struct sockaddr_in6 *) addr->ai_addr;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET6, &sin6->sin6_addr, tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ if (sin6->sin6_scope_id) {
|
|
||||||
+ len = strnlen(tmpbuf, sizeof(tmpbuf));
|
|
||||||
+ snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%%%u",
|
|
||||||
+ sin6->sin6_scope_id);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case AF_INET:
|
|
||||||
+ count_v4++;
|
|
||||||
+ if (count_v6 + count_v4 > MAX_ADDRESSES) {
|
|
||||||
+ addr = addr->ai_next;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ sin = (struct sockaddr_in *) addr->ai_addr;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET, &sin->sin_addr, tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ addr = addr->ai_next;
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr == addrlist)
|
|
||||||
@@ -98,6 +112,192 @@ int resolve_host(const char *host, char
|
|
||||||
addr = addr->ai_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+ // Is this a DFS domain where we need to do a cldap ping to find the closest node?
|
|
||||||
+ if (count_v4 > 1 || count_v6 > 1) {
|
|
||||||
+ int res;
|
|
||||||
+ ns_msg global_domain_handle;
|
|
||||||
+ unsigned char global_domain_lookup[4096];
|
|
||||||
+ ns_msg site_domain_handle;
|
|
||||||
+ unsigned char site_domain_lookup[4096];
|
|
||||||
+ char dname[MAXCDNAME];
|
|
||||||
+ int srv_cnt;
|
|
||||||
+
|
|
||||||
+ res = res_init();
|
|
||||||
+ if (res != 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ res = snprintf(dname, MAXCDNAME, "_ldap._tcp.dc._msdcs.%s", host);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ res = res_query(dname, C_IN, ns_t_srv, global_domain_lookup, sizeof(global_domain_lookup));
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ // res is also the size of the response_buffer
|
|
||||||
+ res = ns_initparse(global_domain_lookup, res, &global_domain_handle);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ srv_cnt = ns_msg_count (global_domain_handle, ns_s_an);
|
|
||||||
+
|
|
||||||
+ // No or just one DC we are done
|
|
||||||
+ if (srv_cnt < 2)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ char site_name[MAXCDNAME];
|
|
||||||
+ // We assume that AD always sends the ip addresses in the addtional data block
|
|
||||||
+ for (int i = 0; i < ns_msg_count(global_domain_handle, ns_s_ar); i++) {
|
|
||||||
+ ns_rr rr;
|
|
||||||
+ res = ns_parserr(&global_domain_handle, ns_s_ar, i, &rr);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ switch (ns_rr_type(rr)) {
|
|
||||||
+ case ns_t_aaaa:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_IN6ADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ res = cldap_ping((char *) host, AF_INET6, (void *)ns_rr_rdata(rr), site_name);
|
|
||||||
+ break;
|
|
||||||
+ case ns_t_a:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_INADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ res = cldap_ping((char *) host, AF_INET, (void *)ns_rr_rdata(rr), site_name);
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (res == CLDAP_PING_TRYNEXT) {
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (res < 0) {
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (site_name[0] == '\0') {
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ } else {
|
|
||||||
+ // site found - leave loop
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ res = snprintf(dname, MAXCDNAME, "_ldap._tcp.%s._sites.dc._msdcs.%s", site_name, host);
|
|
||||||
+ if (res < 0) {
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ res = res_query(dname, C_IN, ns_t_srv, site_domain_lookup, sizeof(site_domain_lookup));
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ // res is also the size of the response_buffer
|
|
||||||
+ res = ns_initparse(site_domain_lookup, res, &site_domain_handle);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ int number_addresses = 0;
|
|
||||||
+ for (int i = 0; i < ns_msg_count(site_domain_handle, ns_s_ar); i++) {
|
|
||||||
+ if (i > MAX_ADDRESSES)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ ns_rr rr;
|
|
||||||
+ res = ns_parserr(&site_domain_handle, ns_s_ar, i, &rr);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ switch (ns_rr_type(rr)) {
|
|
||||||
+ case ns_t_aaaa:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_IN6ADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET6, ns_rr_rdata(rr), tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case ns_t_a:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_INADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET, ns_rr_rdata(rr), tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ number_addresses++;
|
|
||||||
+
|
|
||||||
+ if (i == 0)
|
|
||||||
+ *addrstr = '\0';
|
|
||||||
+ else
|
|
||||||
+ strlcat(addrstr, ",", MAX_ADDR_LIST_LEN);
|
|
||||||
+
|
|
||||||
+ strlcat(addrstr, tmpbuf, MAX_ADDR_LIST_LEN);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Preferred site ips is now the first entry in addrstr, fill up with other sites till MAX_ADDRESS
|
|
||||||
+ for (int i = 0; i < ns_msg_count(global_domain_handle, ns_s_ar); i++) {
|
|
||||||
+ if (number_addresses > MAX_ADDRESSES)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ ns_rr rr;
|
|
||||||
+ res = ns_parserr(&global_domain_handle, ns_s_ar, i, &rr);
|
|
||||||
+ if (res < 0)
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+
|
|
||||||
+ switch (ns_rr_type(rr)) {
|
|
||||||
+ case ns_t_aaaa:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_IN6ADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET6, ns_rr_rdata(rr), tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case ns_t_a:
|
|
||||||
+ if (ns_rr_rdlen(rr) != NS_INADDRSZ)
|
|
||||||
+ continue;
|
|
||||||
+ ipaddr = inet_ntop(AF_INET, ns_rr_rdata(rr), tmpbuf,
|
|
||||||
+ sizeof(tmpbuf));
|
|
||||||
+ if (!ipaddr) {
|
|
||||||
+ rc = EX_SYSERR;
|
|
||||||
+ goto resolve_host_out;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ char *found = strstr(addrstr, tmpbuf);
|
|
||||||
+
|
|
||||||
+ if (found) {
|
|
||||||
+ // We only have a real match if the substring is between ',' or it's the last/first entry in the list
|
|
||||||
+ char previous_seperator = found > addrstr ? *(found-1) : '\0';
|
|
||||||
+ char next_seperator = *(found+strlen(tmpbuf));
|
|
||||||
+
|
|
||||||
+ if ((next_seperator == ',' || next_seperator == '\0')
|
|
||||||
+ && (previous_seperator == ',' || previous_seperator == '\0')) {
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ number_addresses++;
|
|
||||||
+ strlcat(addrstr, ",", MAX_ADDR_LIST_LEN);
|
|
||||||
+ strlcat(addrstr, tmpbuf, MAX_ADDR_LIST_LEN);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
resolve_host_out:
|
|
||||||
freeaddrinfo(addrlist);
|
|
||||||
return rc;
|
|
||||||
Index: cifs-utils/resolve_host.h
|
|
||||||
===================================================================
|
|
||||||
--- cifs-utils.orig/resolve_host.h
|
|
||||||
+++ cifs-utils/resolve_host.h
|
|
||||||
@@ -26,8 +26,10 @@
|
|
||||||
/* currently maximum length of IPv6 address string */
|
|
||||||
#define MAX_ADDRESS_LEN INET6_ADDRSTRLEN
|
|
||||||
|
|
||||||
-/* limit list of addresses to 16 max-size addrs */
|
|
||||||
-#define MAX_ADDR_LIST_LEN ((MAX_ADDRESS_LEN + 1) * 16)
|
|
||||||
+#define MAX_ADDRESSES 16
|
|
||||||
+
|
|
||||||
+/* limit list of addresses to MAX_ADDRESSES max-size addrs */
|
|
||||||
+#define MAX_ADDR_LIST_LEN ((MAX_ADDRESS_LEN + 1) * MAX_ADDRESSES)
|
|
||||||
|
|
||||||
extern int resolve_host(const char *host, char *addrstr);
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
diff -up cifs-utils-6.11/Makefile.am.orig cifs-utils-6.11/Makefile.am
|
|
||||||
--- cifs-utils-6.11/Makefile.am.orig 2020-11-02 10:12:50.076702518 +0200
|
|
||||||
+++ cifs-utils-6.11/Makefile.am 2020-11-02 10:13:41.966420633 +0200
|
|
||||||
@@ -119,11 +119,11 @@ endif
|
|
||||||
SUBDIRS = contrib
|
|
||||||
|
|
||||||
install-exec-hook:
|
|
||||||
- (cd $(ROOTSBINDIR) && ln -sf mount.cifs mount.smb3)
|
|
||||||
+ (cd $(DESTDIR)$(ROOTSBINDIR) && ln -sf mount.cifs mount.smb3)
|
|
||||||
|
|
||||||
install-data-hook:
|
|
||||||
- (cd $(man8dir) && ln -sf mount.cifs.8 mount.smb3.8)
|
|
||||||
+ (cd $(DESTDIR)$(man8dir) && ln -sf mount.cifs.8 mount.smb3.8)
|
|
||||||
|
|
||||||
uninstall-hook:
|
|
||||||
- (cd $(ROOTSBINDIR) && rm -f $(ROOTSBINDIR)/mount.smb3)
|
|
||||||
- (cd $(man8dir) && rm -f $(man8dir)/mount.smb3.8)
|
|
||||||
+ (cd $(DESTDIR)$(ROOTSBINDIR) && rm -f $(DESTDIR)$(ROOTSBINDIR)/mount.smb3)
|
|
||||||
+ (cd $(DESTDIR)$(man8dir) && rm -f $(DESTDIR)$(man8dir)/mount.smb3.8)
|
|
@ -1,8 +1,10 @@
|
|||||||
#% define pre_release rc1
|
#% define pre_release rc1
|
||||||
%define pre_release %nil
|
%define pre_release %nil
|
||||||
|
|
||||||
|
%global bash_completion_dir %(pkg-config --variable=completionsdir bash-completion || echo /etc/bash_completion.d)
|
||||||
|
|
||||||
Name: cifs-utils
|
Name: cifs-utils
|
||||||
Version: 7.0
|
Version: 7.1
|
||||||
Release: %autorelease
|
Release: %autorelease
|
||||||
Summary: Utilities for mounting and managing CIFS mounts
|
Summary: Utilities for mounting and managing CIFS mounts
|
||||||
|
|
||||||
@ -21,11 +23,8 @@ Requires(preun): /usr/sbin/alternatives
|
|||||||
Recommends: %{name}-info%{?_isa} = %{version}-%{release}
|
Recommends: %{name}-info%{?_isa} = %{version}-%{release}
|
||||||
|
|
||||||
Source0: https://download.samba.org/pub/linux-cifs/cifs-utils/%{name}-%{version}.tar.bz2
|
Source0: https://download.samba.org/pub/linux-cifs/cifs-utils/%{name}-%{version}.tar.bz2
|
||||||
Patch0: cifs.upcall-fix-UAF-in-get_cachename_from_process_en.patch
|
|
||||||
Patch1: pam_cifscreds-fix-warning-on-NULL-arg-passed-to-s-in.patch
|
Patch0: smbinfo-bash-completion.patch
|
||||||
Patch2: mount.cifs.rst-add-missing-reference-for-sssd.patch
|
|
||||||
Patch3: mount.cifs.rst-update-section-about-xattr-acl-suppor.patch
|
|
||||||
Patch4: Implement-CLDAP-Ping-to-find-the-closest-site.patch
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
The SMB/CIFS protocol is a standard file sharing protocol widely deployed
|
The SMB/CIFS protocol is a standard file sharing protocol widely deployed
|
||||||
@ -57,15 +56,10 @@ for each user from somewhere. The pam_cifscreds module can be used to
|
|||||||
provide these credentials to the kernel automatically at login.
|
provide these credentials to the kernel automatically at login.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}%{pre_release}
|
%autosetup -n %{name}-%{version}%{pre_release} -p1
|
||||||
%patch0 -p1
|
|
||||||
%patch1 -p1
|
|
||||||
%patch2 -p1
|
|
||||||
%patch3 -p1
|
|
||||||
%patch4 -p1
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
fgrep -r -l '/usr/bin/env python' | xargs -n1 sed -i 's@/usr/bin/env python.*@%python3@g'
|
grep -F -r -l '/usr/bin/env python' | xargs --no-run-if-empty -n1 sed -i 's@/usr/bin/env python.*@%python3@g'
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
%configure --prefix=/usr ROOTSBINDIR=%{_sbindir}
|
%configure --prefix=/usr ROOTSBINDIR=%{_sbindir}
|
||||||
make %{?_smp_mflags}
|
make %{?_smp_mflags}
|
||||||
@ -77,9 +71,11 @@ mkdir -p %{buildroot}%{_sysconfdir}/%{name}
|
|||||||
mkdir -p %{buildroot}%{_sysconfdir}/request-key.d
|
mkdir -p %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
install -m 644 contrib/request-key.d/cifs.idmap.conf %{buildroot}%{_sysconfdir}/request-key.d
|
install -m 644 contrib/request-key.d/cifs.idmap.conf %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
install -m 644 contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}/request-key.d
|
install -m 644 contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}/request-key.d
|
||||||
|
install -Dpm 644 bash-completion/smbinfo %{buildroot}%{_datadir}%{bash_completion_dir}/smbinfo
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%doc
|
%doc
|
||||||
|
%license COPYING
|
||||||
%{_bindir}/getcifsacl
|
%{_bindir}/getcifsacl
|
||||||
%{_bindir}/setcifsacl
|
%{_bindir}/setcifsacl
|
||||||
%{_bindir}/cifscreds
|
%{_bindir}/cifscreds
|
||||||
@ -97,6 +93,7 @@ install -m 644 contrib/request-key.d/cifs.spnego.conf %{buildroot}%{_sysconfdir}
|
|||||||
%{_mandir}/man8/mount.cifs.*
|
%{_mandir}/man8/mount.cifs.*
|
||||||
%{_mandir}/man8/mount.smb3.*
|
%{_mandir}/man8/mount.smb3.*
|
||||||
%{_mandir}/man8/idmapwb.*
|
%{_mandir}/man8/idmapwb.*
|
||||||
|
%{_datadir}%{bash_completion_dir}/smbinfo
|
||||||
%dir %{_sysconfdir}/cifs-utils
|
%dir %{_sysconfdir}/cifs-utils
|
||||||
%ghost %{_sysconfdir}/cifs-utils/idmap-plugin
|
%ghost %{_sysconfdir}/cifs-utils/idmap-plugin
|
||||||
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.idmap.conf
|
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.idmap.conf
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
From 73146385da0945c78af0fbdc08d2bf260db709d5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Paulo Alcantara <pc@manguebit.com>
|
|
||||||
Date: Fri, 8 Mar 2024 12:06:15 -0300
|
|
||||||
Subject: [PATCH] cifs.upcall: fix UAF in get_cachename_from_process_env()
|
|
||||||
|
|
||||||
Whether lseek(2) fails or @bufsize * 2 > ENV_BUF_MAX, then @buf would
|
|
||||||
end up being freed twice. For instance:
|
|
||||||
|
|
||||||
cifs-utils-7.0/cifs.upcall.c:501: freed_arg: "free" frees "buf".
|
|
||||||
cifs-utils-7.0/cifs.upcall.c:524: double_free: Calling "free" frees
|
|
||||||
pointer "buf" which has already been freed.
|
|
||||||
522| }
|
|
||||||
523| out_close:
|
|
||||||
524|-> free(buf);
|
|
||||||
525| close(fd);
|
|
||||||
526| return cachename;
|
|
||||||
|
|
||||||
Fix this by setting @buf to NULL after freeing it to prevent UAF.
|
|
||||||
|
|
||||||
Fixes: ed97e4ecab4e ("cifs.upcall: allow scraping of KRB5CCNAME out of initiating task's /proc/<pid>/environ file")
|
|
||||||
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
|
|
||||||
---
|
|
||||||
cifs.upcall.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/cifs.upcall.c b/cifs.upcall.c
|
|
||||||
index 52c03280dbe0..ff6f2bd271bc 100644
|
|
||||||
--- a/cifs.upcall.c
|
|
||||||
+++ b/cifs.upcall.c
|
|
||||||
@@ -498,10 +498,11 @@ retry:
|
|
||||||
/* We read to the end of the buffer. Double and try again */
|
|
||||||
syslog(LOG_DEBUG, "%s: read to end of buffer (%zu bytes)\n",
|
|
||||||
__func__, bufsize);
|
|
||||||
- free(buf);
|
|
||||||
- bufsize *= 2;
|
|
||||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
|
||||||
goto out_close;
|
|
||||||
+ free(buf);
|
|
||||||
+ buf = NULL;
|
|
||||||
+ bufsize *= 2;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
From e7ec0032898d855be144c0cdc9d9e3f78ae01bf2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Paulo Alcantara <pc@manguebit.com>
|
|
||||||
Date: Sun, 10 Mar 2024 22:24:24 -0300
|
|
||||||
Subject: [PATCH 1/2] mount.cifs.rst: add missing reference for sssd
|
|
||||||
|
|
||||||
Reference sssd in mount.cifs(8) as it can be used instead of winbind
|
|
||||||
via cifs.idmap utility. It's also enabled by default in most systems.
|
|
||||||
|
|
||||||
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
|
|
||||||
---
|
|
||||||
mount.cifs.rst | 14 +++++++-------
|
|
||||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mount.cifs.rst b/mount.cifs.rst
|
|
||||||
index 3becf200e038..64127b23cf17 100644
|
|
||||||
--- a/mount.cifs.rst
|
|
||||||
+++ b/mount.cifs.rst
|
|
||||||
@@ -773,10 +773,10 @@ specified in the following Microsoft TechNet document:
|
|
||||||
In order to map SIDs to/from UIDs and GIDs, the following is required:
|
|
||||||
|
|
||||||
- a kernel upcall to the ``cifs.idmap`` utility set up via request-key.conf(5)
|
|
||||||
-- winbind support configured via nsswitch.conf(5) and smb.conf(5)
|
|
||||||
+- winbind or sssd support configured via nsswitch.conf(5)
|
|
||||||
|
|
||||||
-Please refer to the respective manpages of cifs.idmap(8) and
|
|
||||||
-winbindd(8) for more information.
|
|
||||||
+Please refer to the respective manpages of cifs.idmap(8), winbindd(8)
|
|
||||||
+and sssd(8) for more information.
|
|
||||||
|
|
||||||
Security descriptors for a file object can be retrieved and set
|
|
||||||
directly using extended attribute named ``system.cifs_acl``. The
|
|
||||||
@@ -792,10 +792,10 @@ Some of the things to consider while using this mount option:
|
|
||||||
- The mapping between a CIFS/NTFS ACL and POSIX file permission bits
|
|
||||||
is imperfect and some ACL information may be lost in the
|
|
||||||
translation.
|
|
||||||
-- If either upcall to cifs.idmap is not setup correctly or winbind is
|
|
||||||
- not configured and running, ID mapping will fail. In that case uid
|
|
||||||
- and gid will default to either to those values of the share or to
|
|
||||||
- the values of uid and/or gid mount options if specified.
|
|
||||||
+- If either upcall to cifs.idmap is not setup correctly or winbind or
|
|
||||||
+ sssd is not configured and running, ID mapping will fail. In that
|
|
||||||
+ case uid and gid will default to either to those values of the share
|
|
||||||
+ or to the values of uid and/or gid mount options if specified.
|
|
||||||
|
|
||||||
**********************************
|
|
||||||
ACCESSING FILES WITH BACKUP INTENT
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
|||||||
From 4718e09e4b15b957bf9d729793bc3de7caad8134 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Paulo Alcantara <pc@manguebit.com>
|
|
||||||
Date: Sun, 10 Mar 2024 22:24:25 -0300
|
|
||||||
Subject: [PATCH 2/2] mount.cifs.rst: update section about xattr/acl support
|
|
||||||
|
|
||||||
Update section about required xattr/acl support for UID/GID mapping.
|
|
||||||
|
|
||||||
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
|
|
||||||
---
|
|
||||||
mount.cifs.rst | 26 +++++++++++++++++++-------
|
|
||||||
1 file changed, 19 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mount.cifs.rst b/mount.cifs.rst
|
|
||||||
index 64127b23cf17..d82a13c932b3 100644
|
|
||||||
--- a/mount.cifs.rst
|
|
||||||
+++ b/mount.cifs.rst
|
|
||||||
@@ -321,11 +321,12 @@ soft
|
|
||||||
noacl
|
|
||||||
Do not allow POSIX ACL operations even if server would support them.
|
|
||||||
|
|
||||||
- The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba
|
|
||||||
- servers version 3.0.10 and later. Setting POSIX ACLs requires enabling
|
|
||||||
- both ``CIFS_XATTR`` and then ``CIFS_POSIX`` support in the CIFS
|
|
||||||
- configuration options when building the cifs module. POSIX ACL support
|
|
||||||
- can be disabled on a per mount basis by specifying ``noacl`` on mount.
|
|
||||||
+ The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to
|
|
||||||
+ Samba servers version 3.0.10 and later. Setting POSIX ACLs requires
|
|
||||||
+ enabling both ``CONFIG_CIFS_XATTR`` and then ``CONFIG_CIFS_POSIX``
|
|
||||||
+ support in the CIFS configuration options when building the cifs
|
|
||||||
+ module. POSIX ACL support can be disabled on a per mount basis by
|
|
||||||
+ specifying ``noacl`` on mount.
|
|
||||||
|
|
||||||
cifsacl
|
|
||||||
This option is used to map CIFS/NTFS ACLs to/from Linux permission
|
|
||||||
@@ -762,8 +763,19 @@ bits, and POSIX ACL as user authentication model. This is the most
|
|
||||||
common authentication model for CIFS servers and is the one used by
|
|
||||||
Windows.
|
|
||||||
|
|
||||||
-Support for this requires both CIFS_XATTR and CIFS_ACL support in the
|
|
||||||
-CIFS configuration options when building the cifs module.
|
|
||||||
+Support for this requires cifs kernel module built with both
|
|
||||||
+``CONFIG_CIFS_XATTR`` and ``CONFIG_CIFS_ACL`` options enabled. Since
|
|
||||||
+Linux 5.3, ``CONFIG_CIFS_ACL`` option no longer exists as CIFS/NTFS
|
|
||||||
+ACL support is always built into cifs kernel module.
|
|
||||||
+
|
|
||||||
+Most distribution kernels will already have those options enabled by
|
|
||||||
+default, but you can still check if they are enabled with::
|
|
||||||
+
|
|
||||||
+ cat /lib/modules/$(uname -r)/build/.config
|
|
||||||
+
|
|
||||||
+Alternatively, if kernel is configured with ``CONFIG_IKCONFIG_PROC``::
|
|
||||||
+
|
|
||||||
+ zcat /proc/config.gz
|
|
||||||
|
|
||||||
A CIFS/NTFS ACL is mapped to file permission bits using an algorithm
|
|
||||||
specified in the following Microsoft TechNet document:
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
From dac330136368a9b8d9ccf8227f56ea35de57a4d2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Paulo Alcantara <pc@manguebit.com>
|
|
||||||
Date: Fri, 8 Mar 2024 13:25:22 -0300
|
|
||||||
Subject: [PATCH] pam_cifscreds: fix warning on NULL arg passed to %s in
|
|
||||||
pam_syslog()
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Fix the following compiler warning with -Wformat-overflow in
|
|
||||||
cifscreds_pam_update():
|
|
||||||
|
|
||||||
pam_cifscreds.c: In function ‘cifscreds_pam_update’:
|
|
||||||
pam_cifscreds.c:340:83: warning: ‘%s’ directive argument is null
|
|
||||||
[-Wformat-overflow=]
|
|
||||||
340 | pam_syslog(ph, LOG_ERR, "error: Update credential key for %s: %s",
|
|
||||||
| ^~
|
|
||||||
|
|
||||||
Fixes: cbbcd6e71c0a ("cifscreds: create PAM module to insert credentials at login")
|
|
||||||
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
|
|
||||||
---
|
|
||||||
pam_cifscreds.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/pam_cifscreds.c b/pam_cifscreds.c
|
|
||||||
index 5d99c2db3038..eb9851d52a7d 100644
|
|
||||||
--- a/pam_cifscreds.c
|
|
||||||
+++ b/pam_cifscreds.c
|
|
||||||
@@ -338,7 +338,7 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char *
|
|
||||||
key_serial_t key = key_add(currentaddress, user, password, keytype);
|
|
||||||
if (key <= 0) {
|
|
||||||
pam_syslog(ph, LOG_ERR, "error: Update credential key for %s: %s",
|
|
||||||
- currentaddress, strerror(errno));
|
|
||||||
+ (currentaddress ?: "(null)"), strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.44.0
|
|
||||||
|
|
47
smbinfo-bash-completion.patch
Normal file
47
smbinfo-bash-completion.patch
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
From d69d2129c6476afbcbbe8dc6e2ed17f233084d85 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@samba.org>
|
||||||
|
Date: Mon, 7 Oct 2024 21:48:31 +0200
|
||||||
|
Subject: [PATCH] smbinfo: add bash completion support for filestreaminfo,
|
||||||
|
keys, gettconinfo
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
|
||||||
|
---
|
||||||
|
bash-completion/smbinfo | 9 ++++++---
|
||||||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/bash-completion/smbinfo b/bash-completion/smbinfo
|
||||||
|
index d56b581..ec0d8a4 100644
|
||||||
|
--- a/bash-completion/smbinfo
|
||||||
|
+++ b/bash-completion/smbinfo
|
||||||
|
@@ -15,19 +15,22 @@ smb_info()
|
||||||
|
filemodeinfo
|
||||||
|
filepositioninfo
|
||||||
|
filestandardinfo
|
||||||
|
+ filestreaminfo
|
||||||
|
fsctl-getobjid
|
||||||
|
getcompression
|
||||||
|
setcompression
|
||||||
|
list-snapshots
|
||||||
|
quota
|
||||||
|
- secdesc"
|
||||||
|
+ secdesc
|
||||||
|
+ keys
|
||||||
|
+ gettconinfo"
|
||||||
|
case $prev in
|
||||||
|
'-v'|'-h')
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
'fileaccessinfo'|'filealigninfo'|'fileallinfo'|'filebasicinfo'|'fileeainfo'|'filefsfullsizeinfo'|\
|
||||||
|
- 'fileinternalinfo'|'filemodeinfo'|'filepositioninfo'|'filestandardinfo'|'fsctl-getobjid'|\
|
||||||
|
- 'getcompression'|'setcompression'|'list-snapshots'|'quota'|'secdesc')
|
||||||
|
+ 'fileinternalinfo'|'filemodeinfo'|'filepositioninfo'|'filestandardinfo'|'filestreaminfo'|'fsctl-getobjid'|\
|
||||||
|
+ 'getcompression'|'setcompression'|'list-snapshots'|'quota'|'secdesc'|'keys'|'gettconinfo')
|
||||||
|
local IFS=$'\n'
|
||||||
|
compopt -o filenames
|
||||||
|
COMPREPLY=( $(compgen -f -o dirnames -- ${cur:-""}) )
|
||||||
|
--
|
||||||
|
2.46.1
|
||||||
|
|
2
sources
2
sources
@ -1 +1 @@
|
|||||||
SHA512 (cifs-utils-7.0.tar.bz2) = 4c57741af0c4567a78f352c73caca998881666a5ed36536275cfa775efd66ff1a44ebe539a8ed96c409c5b08a1378266964ce667a27e9fc7f2d43999c63dd0eb
|
SHA512 (cifs-utils-7.1.tar.bz2) = 9eda85b2767cd19c7f69843750450c3862596debf47f41d9ce07f3d7438225b700b260be9585d2f7c9962d3f4dd8434b1b647c9ba670962cf136ce7ad86f92ab
|
||||||
|
Loading…
Reference in New Issue
Block a user