summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-20 04:07:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-20 04:07:27 +0000
commit31bdcfe4b647c8c783efa32da3c333b5f166a42d (patch)
tree2b868e2a40cde0854fa0f5466ea8990d3d38f93d /source3
parentAdding upstream version 2:4.20.1+dfsg. (diff)
downloadsamba-31bdcfe4b647c8c783efa32da3c333b5f166a42d.tar.xz
samba-31bdcfe4b647c8c783efa32da3c333b5f166a42d.zip
Adding upstream version 2:4.20.2+dfsg.upstream/2%4.20.2+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/include/fstring.h27
-rw-r--r--source3/include/includes.h5
-rw-r--r--source3/include/nameserv.h380
-rw-r--r--source3/include/session.h1
-rw-r--r--source3/include/smb.h26
-rw-r--r--source3/lib/sessionid_tdb.c8
-rw-r--r--source3/lib/util_tdb.c4
-rw-r--r--source3/libads/kerberos.c32
-rw-r--r--source3/libads/ldap.c16
-rw-r--r--source3/librpc/idl/ads.idl1
-rw-r--r--source3/libsmb/clidgram.c6
-rw-r--r--source3/libsmb/dsgetdcname.c29
-rw-r--r--source3/libsmb/libsmb_xattr.c14
-rw-r--r--source3/libsmb/namequery.c21
-rw-r--r--source3/libsmb/nmblib.c12
-rw-r--r--source3/libsmb/nmblib.h2
-rw-r--r--source3/libsmb/unexpected.c18
-rw-r--r--source3/libsmb/unexpected.h2
-rw-r--r--source3/locking/brlock.c7
-rw-r--r--source3/modules/posixacl_xattr.c6
-rw-r--r--source3/modules/vfs_default.c6
-rw-r--r--source3/modules/vfs_recycle.c176
-rw-r--r--source3/modules/vfs_vxfs.c6
-rw-r--r--source3/modules/vfs_widelinks.c13
-rw-r--r--source3/nmbd/nmbd.h382
-rw-r--r--source3/nmbd/nmbd_packets.c1
-rw-r--r--source3/rpc_server/wkssvc/srv_wkssvc_nt.c2
-rwxr-xr-xsource3/script/tests/test_recycle.sh5
-rwxr-xr-xsource3/script/tests/test_widelink_dfs_ci.sh72
-rwxr-xr-xsource3/selftest/tests.py11
-rw-r--r--source3/smbd/files.c18
-rw-r--r--source3/smbd/globals.h5
-rw-r--r--source3/smbd/smb2_server.c11
-rw-r--r--source3/smbd/smb2_sesssetup.c18
-rw-r--r--source3/smbd/smb2_tcon.c4
-rw-r--r--source3/utils/conn_tdb.c12
-rw-r--r--source3/utils/conn_tdb.h1
-rw-r--r--source3/utils/net_ads.c6
-rw-r--r--source3/utils/net_registry.c2
-rw-r--r--source3/utils/sharesec.c8
-rw-r--r--source3/utils/smbcacls.c15
-rw-r--r--source3/utils/status.c82
-rw-r--r--source3/utils/status.h1
-rw-r--r--source3/utils/status_json.c2
-rw-r--r--source3/winbindd/idmap_ad.c11
-rw-r--r--source3/wscript_build1
46 files changed, 944 insertions, 544 deletions
diff --git a/source3/include/fstring.h b/source3/include/fstring.h
new file mode 100644
index 0000000..dfc8f17
--- /dev/null
+++ b/source3/include/fstring.h
@@ -0,0 +1,27 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) 2002 by Martin Pool <mbp@samba.org>
+
+ 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/>.
+*/
+
+#ifndef _SAMBA_FSTRING_H
+#define _SAMBA_FSTRING_H
+
+#ifndef FSTRING_LEN
+#define FSTRING_LEN 256
+typedef char fstring[FSTRING_LEN];
+#endif
+
+#endif /* _SAMBA_FSTRING_H */
diff --git a/source3/include/includes.h b/source3/include/includes.h
index 1e7b79b..ee05b93 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -237,10 +237,7 @@ enum timestamp_set_resolution {
_________)/\\_//(\/(/\)/\//\/\///|_)_______
*/
-#ifndef FSTRING_LEN
-#define FSTRING_LEN 256
-typedef char fstring[FSTRING_LEN];
-#endif
+#include "fstring.h"
/* debug.h need to be included before samba_util.h for the macro SMB_ASSERT */
#include "../lib/util/debug.h"
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index 8fbe5a3..51efe82 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -20,18 +20,6 @@
*/
-#define INFO_VERSION "INFO/version"
-#define INFO_COUNT "INFO/num_entries"
-#define INFO_ID_HIGH "INFO/id_high"
-#define INFO_ID_LOW "INFO/id_low"
-#define ENTRY_PREFIX "ENTRY/"
-
-#define PERMANENT_TTL 0
-
-/* NTAS uses 2, NT uses 1, WfWg uses 0 */
-#define MAINTAIN_LIST 2
-#define ELECTION_VERSION 1
-
#define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */
#define MIN_DGRAM_SIZE 12
@@ -140,12 +128,6 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
-/* Workgroup state identifiers. */
-#define AM_POTENTIAL_MASTER_BROWSER(work) ((work)->mst_state == MST_POTENTIAL)
-#define AM_LOCAL_MASTER_BROWSER(work) ((work)->mst_state == MST_BROWSER)
-#define AM_DOMAIN_MASTER_BROWSER(work) ((work)->dom_state == DOMAIN_MST)
-#define AM_DOMAIN_MEMBER(work) ((work)->log_state == LOGON_SRV)
-
/* Microsoft browser NetBIOS name. */
#define MSBROWSE "\001\002__MSBROWSE__\002"
@@ -159,293 +141,33 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
#define FIND_ANY_NAME 0
#define FIND_SELF_NAME 1
-/*
- * The different name types that can be in namelists.
- *
- * SELF_NAME should only be on the broadcast and unicast subnets.
- * LMHOSTS_NAME should only be in the remote_broadcast_subnet.
- * REGISTER_NAME, DNS_NAME, DNSFAIL_NAME should only be in the wins_server_subnet.
- * WINS_PROXY_NAME should only be on the broadcast subnets.
- * PERMANENT_NAME can be on all subnets except remote_broadcast_subnet.
- *
- */
-
-enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
- DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
-enum master_state {
- MST_NONE,
- MST_POTENTIAL,
- MST_BACKUP,
- MST_MSB,
- MST_BROWSER,
- MST_UNBECOMING_MASTER
-};
-
-enum domain_state {
- DOMAIN_NONE,
- DOMAIN_WAIT,
- DOMAIN_MST
-};
-
-enum logon_state {
- LOGON_NONE,
- LOGON_WAIT,
- LOGON_SRV
-};
-
-struct subnet_record;
-
-struct nmb_data {
- uint16_t nb_flags; /* Netbios flags. */
- int num_ips; /* Number of ip entries. */
- struct in_addr *ip; /* The ip list for this name. */
-
- enum name_source source; /* Where the name came from. */
-
- time_t death_time; /* The time the record must be removed (do not remove if 0). */
- time_t refresh_time; /* The time the record should be refreshed. */
-
- uint64_t id; /* unique id */
- struct in_addr wins_ip; /* the address of the wins server this record comes from */
-
- int wins_flags; /* similar to the netbios flags but different ! */
-};
-
-/* This structure represents an entry in a local netbios name list. */
-struct name_record {
- struct name_record *prev, *next;
- struct subnet_record *subnet;
- struct nmb_name name; /* The netbios name. */
- struct nmb_data data; /* The netbios data. */
-};
-
-/* Browser cache for synchronising browse lists. */
-struct browse_cache_record {
- struct browse_cache_record *prev, *next;
- unstring lmb_name;
- unstring work_group;
- struct in_addr ip;
- time_t sync_time;
- time_t death_time; /* The time the record must be removed. */
-};
-
-/* used for server information: client, nameserv and ipc */
-struct server_info_struct {
- fstring name;
- uint32_t type;
- fstring comment;
- fstring domain; /* used ONLY in ipc.c NOT namework.c */
- bool server_added; /* used ONLY in ipc.c NOT namework.c */
-};
-
-/* This is used to hold the list of servers in my domain, and is
- contained within lists of domains. */
-
-struct server_record {
- struct server_record *next;
- struct server_record *prev;
-
- struct subnet_record *subnet;
-
- struct server_info_struct serv;
- time_t death_time;
-};
-
-/* A workgroup structure. It contains a list of servers. */
-struct work_record {
- struct work_record *next;
- struct work_record *prev;
-
- struct subnet_record *subnet;
-
- struct server_record *serverlist;
-
- /* Stage of development from non-local-master up to local-master browser. */
- enum master_state mst_state;
-
- /* Stage of development from non-domain-master to domain-master browser. */
- enum domain_state dom_state;
-
- /* Stage of development from non-logon-server to logon server. */
- enum logon_state log_state;
-
- /* Work group info. */
- unstring work_group;
- int token; /* Used when communicating with backup browsers. */
- unstring local_master_browser_name; /* Current local master browser. */
-
- /* Announce info. */
- time_t lastannounce_time;
- int announce_interval;
- bool needannounce;
-
- /* Timeout time for this workgroup. 0 means permanent. */
- time_t death_time;
-
- /* Election info */
- bool RunningElection;
- bool needelection;
- int ElectionCount;
- uint32_t ElectionCriterion;
-
- /* Domain master browser info. Used for efficient syncs. */
- struct nmb_name dmb_name;
- struct in_addr dmb_addr;
-};
-
-/* typedefs needed to define copy & free functions for userdata. */
-struct userdata_struct;
-
-typedef struct userdata_struct * (*userdata_copy_fn)(struct userdata_struct *);
-typedef void (*userdata_free_fn)(struct userdata_struct *);
-
-/* Structure to define any userdata passed around. */
-
-struct userdata_struct {
- userdata_copy_fn copy_fn;
- userdata_free_fn free_fn;
- unsigned int userdata_len;
- char data[16]; /* 16 is to ensure alignment/padding on all systems */
+#define MAX_NETBIOSNAME_LEN 16
+/* DOS character, NetBIOS namestring. Type used on the wire. */
+typedef char nstring[MAX_NETBIOSNAME_LEN];
+/* Unix character, NetBIOS namestring. Type used to manipulate name in nmbd. */
+typedef char unstring[MAX_NETBIOSNAME_LEN*4];
+
+/* A netbios name structure. */
+struct nmb_name {
+ nstring name;
+ char scope[64];
+ unsigned int name_type;
};
-struct response_record;
-struct packet_struct;
-struct res_rec;
-
-/* typedef to define the function called when this response packet comes in. */
-typedef void (*response_function)(struct subnet_record *, struct response_record *,
- struct packet_struct *);
-
-/* typedef to define the function called when this response record times out. */
-typedef void (*timeout_response_function)(struct subnet_record *,
- struct response_record *);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is successful. */
-typedef void (*success_function)(struct subnet_record *, struct userdata_struct *, ...);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is unsuccessful. */
-typedef void (*fail_function)(struct subnet_record *, struct response_record *, ...);
-
-/* List of typedefs for success and fail functions of the different query
- types. Used to catch any compile time prototype errors. */
-
-typedef void (*register_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16_t,
- int,
- struct in_addr);
-typedef void (*register_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*release_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr);
-typedef void (*release_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*refresh_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16_t,
- int,
- struct in_addr);
-typedef void (*refresh_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*query_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr,
- struct res_rec *answers);
-
-typedef void (*query_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *,
- int);
-
-typedef void (*node_status_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct res_rec *,
- struct in_addr);
-typedef void (*node_status_fail_function)( struct subnet_record *,
- struct response_record *);
-
-/* Initiated name queries are recorded in this list to track any responses. */
-
-struct response_record {
- struct response_record *next;
- struct response_record *prev;
-
- uint16_t response_id;
-
- /* Callbacks for packets received or not. */
- response_function resp_fn;
- timeout_response_function timeout_fn;
-
- /* Callbacks for the request succeeding or not. */
- success_function success_fn;
- fail_function fail_fn;
-
- struct packet_struct *packet;
-
- struct userdata_struct *userdata;
-
- int num_msgs;
-
- time_t repeat_time;
- time_t repeat_interval;
- int repeat_count;
-
- /* Recursion protection. */
- bool in_expiration_processing;
+/* A netbios node status array element. */
+struct node_status {
+ nstring name;
+ unsigned char type;
+ unsigned char flags;
};
-/* A subnet structure. It contains a list of workgroups and netbios names. */
-
-/*
- B nodes will have their own, totally separate subnet record, with their
- own netbios name set. These do NOT interact with other subnet records'
- netbios names.
-*/
-
-enum subnet_type {
- NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
- UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
- REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
- WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
-};
-
-struct subnet_record {
- struct subnet_record *next;
- struct subnet_record *prev;
-
- char *subnet_name; /* For Debug identification. */
- enum subnet_type type; /* To catagorize the subnet. */
-
- struct work_record *workgrouplist; /* List of workgroups. */
- struct name_record *namelist; /* List of netbios names. */
- struct response_record *responselist; /* List of responses expected. */
-
- bool namelist_changed;
- bool work_changed;
-
- struct in_addr bcast_ip;
- struct in_addr mask_ip;
- struct in_addr myip;
- int nmb_sock; /* socket to listen for unicast 137. */
- int nmb_bcast; /* socket to listen for broadcast 137. */
- int dgram_sock; /* socket to listen for unicast 138. */
- int dgram_bcast; /* socket to listen for broadcast 138. */
+/* The extra info from a NetBIOS node status query */
+struct node_status_extra {
+ unsigned char mac_addr[6];
+ /* There really is more here ... */
};
/* A resource record. */
@@ -564,66 +286,4 @@ struct packet_struct
#define ANN_ResetBrowserState 14
#define ANN_LocalMasterAnnouncement 15
-
-/* Broadcast packet announcement intervals, in minutes. */
-
-/* Attempt to add domain logon and domain master names. */
-#define CHECK_TIME_ADD_DOM_NAMES 5
-
-/* Search for master browsers of workgroups samba knows about,
- except default. */
-#define CHECK_TIME_MST_BROWSE 5
-
-/* Request backup browser announcements from other servers. */
-#define CHECK_TIME_ANNOUNCE_BACKUP 15
-
-/* Request host announcements from other servers: min and max of interval. */
-#define CHECK_TIME_MIN_HOST_ANNCE 3
-#define CHECK_TIME_MAX_HOST_ANNCE 12
-
-/* Announce as master to WINS server and any Primary Domain Controllers. */
-#define CHECK_TIME_MST_ANNOUNCE 15
-
-/* Time between syncs from domain master browser to local master browsers. */
-#define CHECK_TIME_DMB_TO_LMB_SYNC 15
-
-/* Do all remote announcements this often. */
-#define REMOTE_ANNOUNCE_INTERVAL 180
-
-/* what is the maximum period between name refreshes. Note that this only
- affects non-permanent self names (in seconds) */
-#define MAX_REFRESH_TIME (60*20)
-
-/* The Extinction interval: 4 days, time a node will stay in released state */
-#define EXTINCTION_INTERVAL (4*24*60*60)
-
-/* The Extinction time-out: 1 day, time a node will stay in deleted state */
-#define EXTINCTION_TIMEOUT (24*60*60)
-
-/* Macro's to enumerate subnets either with or without
- the UNICAST subnet. */
-
-extern struct subnet_record *subnetlist;
-extern struct subnet_record *unicast_subnet;
-extern struct subnet_record *wins_server_subnet;
-extern struct subnet_record *remote_broadcast_subnet;
-
-#define FIRST_SUBNET subnetlist
-#define NEXT_SUBNET_EXCLUDING_UNICAST(x) ((x)->next)
-#define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
-
-/* wins replication record used between nmbd and wrepld */
-typedef struct _WINS_RECORD {
- char name[17];
- char type;
- int nb_flags;
- int wins_flags;
- uint64_t id;
- int num_ips;
- struct in_addr ip[25];
- struct in_addr wins_ip;
-} WINS_RECORD;
-
-/* To be removed. */
-enum state_type { TEST };
#endif /* _NAMESERV_H_ */
diff --git a/source3/include/session.h b/source3/include/session.h
index 40c25e5..903208e 100644
--- a/source3/include/session.h
+++ b/source3/include/session.h
@@ -39,6 +39,7 @@ struct sessionid {
fstring ip_addr_str;
time_t connect_start;
uint16_t connection_dialect;
+ bool authenticated;
uint8_t encryption_flags;
uint16_t cipher;
uint16_t signing;
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 81d761d..ce18872 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -625,31 +625,7 @@ struct kernel_oplocks_ops {
#include "smb_macros.h"
-#define MAX_NETBIOSNAME_LEN 16
-/* DOS character, NetBIOS namestring. Type used on the wire. */
-typedef char nstring[MAX_NETBIOSNAME_LEN];
-/* Unix character, NetBIOS namestring. Type used to manipulate name in nmbd. */
-typedef char unstring[MAX_NETBIOSNAME_LEN*4];
-
-/* A netbios name structure. */
-struct nmb_name {
- nstring name;
- char scope[64];
- unsigned int name_type;
-};
-
-/* A netbios node status array element. */
-struct node_status {
- nstring name;
- unsigned char type;
- unsigned char flags;
-};
-
-/* The extra info from a NetBIOS node status query */
-struct node_status_extra {
- unsigned char mac_addr[6];
- /* There really is more here ... */
-};
+#include "nameserv.h"
#define SAFE_NETBIOS_CHARS ". -_"
diff --git a/source3/lib/sessionid_tdb.c b/source3/lib/sessionid_tdb.c
index 2376fd4..54bb895 100644
--- a/source3/lib/sessionid_tdb.c
+++ b/source3/lib/sessionid_tdb.c
@@ -24,6 +24,7 @@
#include "session.h"
#include "util_tdb.h"
#include "smbd/globals.h"
+#include "../libcli/security/session.h"
struct sessionid_traverse_read_state {
int (*fn)(const char *key, struct sessionid *session,
@@ -48,11 +49,18 @@ static int sessionid_traverse_read_fn(struct smbXsrv_session_global0 *global,
};
if (session_info != NULL) {
+ enum security_user_level ul;
+
session.uid = session_info->unix_token->uid;
session.gid = session_info->unix_token->gid;
strncpy(session.username,
session_info->unix_info->unix_name,
sizeof(fstring)-1);
+
+ ul = security_session_user_level(session_info, NULL);
+ if (ul >= SECURITY_USER) {
+ session.authenticated = true;
+ }
}
strncpy(session.remote_machine,
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index d85f676..3c7c194 100644
--- a/source3/lib/util_tdb.c
+++ b/source3/lib/util_tdb.c
@@ -324,11 +324,11 @@ int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2)
return 1;
}
if (t1.dptr == t2.dptr) {
- return t1.dsize - t2.dsize;
+ return NUMERIC_CMP(t1.dsize, t2.dsize);
}
ret = memcmp(t1.dptr, t2.dptr, MIN(t1.dsize, t2.dsize));
if (ret == 0) {
- return t1.dsize - t2.dsize;
+ return NUMERIC_CMP(t1.dsize, t2.dsize);
}
return ret;
}
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index f76c566..6c6d23c 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -437,23 +437,23 @@ static char *get_kdc_ip_string(char *mem_ctx,
char *kdc_str = NULL;
char *canon_sockaddr = NULL;
- SMB_ASSERT(pss != NULL);
-
- canon_sockaddr = print_canonical_sockaddr_with_port(frame, pss);
- if (canon_sockaddr == NULL) {
- goto out;
- }
+ if (pss != NULL) {
+ canon_sockaddr = print_canonical_sockaddr_with_port(frame, pss);
+ if (canon_sockaddr == NULL) {
+ goto out;
+ }
- kdc_str = talloc_asprintf(frame,
- "\t\tkdc = %s\n",
- canon_sockaddr);
- if (kdc_str == NULL) {
- goto out;
- }
+ kdc_str = talloc_asprintf(frame,
+ "\t\tkdc = %s\n",
+ canon_sockaddr);
+ if (kdc_str == NULL) {
+ goto out;
+ }
- ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
- if (!ok) {
- goto out;
+ ok = sockaddr_storage_to_samba_sockaddr(&sa, pss);
+ if (!ok) {
+ goto out;
+ }
}
/*
@@ -704,7 +704,7 @@ bool create_local_private_krb5_conf_for_domain(const char *realm,
return false;
}
- if (domain == NULL || pss == NULL) {
+ if (domain == NULL) {
return false;
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index b5139e5..d467079 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -275,12 +275,12 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
/* Fill in the ads->config values */
+ ADS_TALLOC_CONST_FREE(ads->config.workgroup);
ADS_TALLOC_CONST_FREE(ads->config.realm);
ADS_TALLOC_CONST_FREE(ads->config.bind_path);
ADS_TALLOC_CONST_FREE(ads->config.ldap_server_name);
ADS_TALLOC_CONST_FREE(ads->config.server_site_name);
ADS_TALLOC_CONST_FREE(ads->config.client_site_name);
- ADS_TALLOC_CONST_FREE(ads->server.workgroup);
if (!check_cldap_reply_required_flags(cldap_reply->server_type,
ads->config.flags)) {
@@ -296,6 +296,13 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
goto out;
}
+ ads->config.workgroup = talloc_strdup(ads, cldap_reply->domain_name);
+ if (ads->config.workgroup == NULL) {
+ DBG_WARNING("Out of memory\n");
+ ret = false;
+ goto out;
+ }
+
ads->config.realm = talloc_asprintf_strupper_m(ads,
"%s",
cldap_reply->dns_domain);
@@ -334,13 +341,6 @@ static bool ads_fill_cldap_reply(ADS_STRUCT *ads,
}
}
- ads->server.workgroup = talloc_strdup(ads, cldap_reply->domain_name);
- if (ads->server.workgroup == NULL) {
- DBG_WARNING("Out of memory\n");
- ret = false;
- goto out;
- }
-
ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
ads->ldap.ss = *ss;
diff --git a/source3/librpc/idl/ads.idl b/source3/librpc/idl/ads.idl
index 4f3a387..d10e5b4 100644
--- a/source3/librpc/idl/ads.idl
+++ b/source3/librpc/idl/ads.idl
@@ -59,6 +59,7 @@ interface ads
typedef [nopull,nopush] struct {
nbt_server_type flags; /* cldap flags identifying the services. */
+ string workgroup;
string realm;
string bind_path;
string ldap_server_name;
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index a45bdac..c87c870 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -349,7 +349,11 @@ struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1,
+ subreq = nb_packet_reader_send(state,
+ ev,
+ global_nmbd_socket_dir(),
+ DGRAM_PACKET,
+ -1,
state->my_mailslot);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 09a6e66..654893c 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -196,7 +196,29 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
/* FIXME */
r->sockaddr_size = 0x10; /* the w32 winsock addr size */
r->sockaddr.sockaddr_family = 2; /* AF_INET */
- r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
+ if (is_ipaddress_v4(addr)) {
+ r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
+ if (r->sockaddr.pdc_ip == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ /*
+ * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX will
+ * fail with an ipv6 address.
+ *
+ * This matches windows behaviour in the CLDAP
+ * response when NETLOGON_NT_VERSION_5EX_WITH_IP
+ * is used.
+ *
+ * Windows returns the ipv4 address of the ipv6
+ * server interface and falls back to 127.0.0.1
+ * if there's no ipv4 address.
+ */
+ r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, "127.0.0.1");
+ if (r->sockaddr.pdc_ip == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
(ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
@@ -930,6 +952,11 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
name_type = NBT_NAME_PDC;
}
+ /*
+ * It's 2024 we always want an AD style response!
+ */
+ nt_version |= NETLOGON_NT_VERSION_AVOID_NT4EMUL;
+
nt_version |= map_ds_flags_to_nt_version(flags);
snprintf(my_acct_name,
diff --git a/source3/libsmb/libsmb_xattr.c b/source3/libsmb/libsmb_xattr.c
index dcb2f9e..a902341 100644
--- a/source3/libsmb/libsmb_xattr.c
+++ b/source3/libsmb/libsmb_xattr.c
@@ -121,7 +121,13 @@ ace_compare(struct security_ace *ace1,
*/
if (ace1->type != ace2->type) {
- return ace2->type - ace1->type;
+ /*
+ * ace2 and ace1 are reversed here, so that
+ * ACCESS_DENIED_ACE_TYPE (1) sorts before
+ * ACCESS_ALLOWED_ACE_TYPE (0), which is the order you
+ * usually want.
+ */
+ return NUMERIC_CMP(ace2->type, ace1->type);
}
if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) {
@@ -129,15 +135,15 @@ ace_compare(struct security_ace *ace1,
}
if (ace1->flags != ace2->flags) {
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
}
if (ace1->access_mask != ace2->access_mask) {
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
}
if (ace1->size != ace2->size) {
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
}
return memcmp(ace1, ace2, sizeof(struct security_ace));
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index e6c0c7d..8f6a9b5 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -34,6 +34,7 @@
#include "lib/gencache.h"
#include "librpc/gen_ndr/dns.h"
#include "lib/util/util_net.h"
+#include "lib/util/tsort.h"
#include "lib/util/string_wrappers.h"
/* nmbd.c sets this to True. */
@@ -644,7 +645,12 @@ static struct tevent_req *nb_trans_send(
return tevent_req_post(req, ev);
}
- subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
+ subreq = nb_packet_reader_send(state,
+ ev,
+ global_nmbd_socket_dir(),
+ type,
+ state->trn_id,
+ NULL);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -1082,8 +1088,15 @@ bool name_status_find(const char *q_name,
}
/*
- comparison function used by sort_addr_list
-*/
+ * comparison function used by sort_addr_list
+ *
+ * This comparison is intransitive in sort if a socket has an invalid
+ * family (i.e., not IPv4 or IPv6), or an interface doesn't support
+ * the family. Say we have sockaddrs with IP versions {4,5,6}, of
+ * which 5 is invalid. By this function, 4 == 5 and 6 == 5, but 4 !=
+ * 6. This is of course a consequence of cmp() being unable to
+ * communicate error.
+ */
static int addr_compare(const struct sockaddr_storage *ss1,
const struct sockaddr_storage *ss2)
@@ -1171,7 +1184,7 @@ static int addr_compare(const struct sockaddr_storage *ss1,
max_bits2 += 128;
}
}
- return max_bits2 - max_bits1;
+ return NUMERIC_CMP(max_bits2, max_bits1);
}
/*
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index c90e92e..2297dd9 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -23,6 +23,12 @@
#include "libsmb/nmblib.h"
#include "lib/util/string_wrappers.h"
+const char *global_nmbd_socket_dir(void)
+{
+ return lp_parm_const_string(-1, "nmbd", "socket dir",
+ get_dyn_NMBDSOCKETDIR());
+}
+
static const struct opcode_names {
const char *nmb_opcode_name;
int opcode;
@@ -1229,8 +1235,10 @@ static unsigned char sort_ip[4];
static int name_query_comp(unsigned char *p1, unsigned char *p2)
{
- return matching_len_bits(p2+2, sort_ip, 4) -
- matching_len_bits(p1+2, sort_ip, 4);
+ int a = matching_len_bits(p1+2, sort_ip, 4);
+ int b = matching_len_bits(p2+2, sort_ip, 4);
+ /* reverse sort -- p2 derived value comes first */
+ return NUMERIC_CMP(b, a);
}
/****************************************************************************
diff --git a/source3/libsmb/nmblib.h b/source3/libsmb/nmblib.h
index 52600a4..5171a26 100644
--- a/source3/libsmb/nmblib.h
+++ b/source3/libsmb/nmblib.h
@@ -29,6 +29,8 @@
/* The following definitions come from libsmb/nmblib.c */
+const char *global_nmbd_socket_dir(void);
+
void debug_nmb_packet(struct packet_struct *p);
void put_name(char *dest, const char *name, int pad, unsigned int name_type);
char *nmb_namestr(const struct nmb_name *n);
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index b81d379..10ceac7 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -26,12 +26,6 @@
#include "lib/tsocket/tsocket.h"
#include "lib/util/sys_rw.h"
-static const char *nmbd_socket_dir(void)
-{
- return lp_parm_const_string(-1, "nmbd", "socket dir",
- get_dyn_NMBDSOCKETDIR());
-}
-
struct nb_packet_query {
enum packet_type type;
size_t mailslot_namelen;
@@ -74,6 +68,7 @@ static void nb_packet_server_listener(struct tevent_context *ev,
NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
int max_clients,
struct nb_packet_server **presult)
{
@@ -90,7 +85,7 @@ NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
result->max_clients = max_clients;
result->listen_sock = create_pipe_sock(
- nmbd_socket_dir(), "unexpected", 0755);
+ nmbd_socket_dir, "unexpected", 0755);
if (result->listen_sock == -1) {
status = map_nt_error_from_unix(errno);
goto fail;
@@ -248,7 +243,7 @@ static void nb_packet_got_query(struct tevent_req *req)
ssize_t nread;
int err;
- nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, client, &buf, &err);
TALLOC_FREE(req);
if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
DEBUG(10, ("read_packet_recv returned %d (%s)\n",
@@ -280,6 +275,8 @@ static void nb_packet_got_query(struct tevent_req *req)
}
}
+ TALLOC_FREE(buf);
+
client->ack.byte = 0;
client->ack.iov[0].iov_base = &client->ack.byte;
client->ack.iov[0].iov_len = 1;
@@ -333,7 +330,7 @@ static void nb_packet_client_read_done(struct tevent_req *req)
uint8_t *buf;
int err;
- nread = tstream_read_packet_recv(req, talloc_tos(), &buf, &err);
+ nread = tstream_read_packet_recv(req, client, &buf, &err);
TALLOC_FREE(req);
if (nread == 1) {
DEBUG(10, ("Protocol error, received data on write-only "
@@ -495,6 +492,7 @@ static void nb_packet_reader_got_ack(struct tevent_req *subreq);
struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
enum packet_type type,
int trn_id,
const char *mailslot_name)
@@ -530,7 +528,7 @@ struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
tevent_req_nterror(req, map_nt_error_from_unix(errno));
return tevent_req_post(req, ev);
}
- rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir(),
+ rpath = talloc_asprintf(state, "%s/%s", nmbd_socket_dir,
"unexpected");
if (tevent_req_nomem(rpath, req)) {
return tevent_req_post(req, ev);
diff --git a/source3/libsmb/unexpected.h b/source3/libsmb/unexpected.h
index 270976b..4ae9b20 100644
--- a/source3/libsmb/unexpected.h
+++ b/source3/libsmb/unexpected.h
@@ -29,12 +29,14 @@ struct nb_packet_reader;
NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
int max_clients,
struct nb_packet_server **presult);
void nb_packet_dispatch(struct nb_packet_server *server,
struct packet_struct *p);
struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ const char *nmbd_socket_dir,
enum packet_type type,
int trn_id,
const char *mailslot_name);
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 905da04..328a9bf 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -408,12 +408,9 @@ static int lock_compare(const struct lock_struct *lck1,
const struct lock_struct *lck2)
{
if (lck1->start != lck2->start) {
- return (lck1->start - lck2->start);
+ return NUMERIC_CMP(lck1->start, lck2->start);
}
- if (lck2->size != lck1->size) {
- return ((int)lck1->size - (int)lck2->size);
- }
- return 0;
+ return NUMERIC_CMP(lck1->size, lck2->size);
}
#endif
diff --git a/source3/modules/posixacl_xattr.c b/source3/modules/posixacl_xattr.c
index 365cdc7..5d0516c 100644
--- a/source3/modules/posixacl_xattr.c
+++ b/source3/modules/posixacl_xattr.c
@@ -226,14 +226,14 @@ static int posixacl_xattr_entry_compare(const void *left, const void *right)
tag_left = SVAL(left, 0);
tag_right = SVAL(right, 0);
- ret = (tag_left - tag_right);
- if (!ret) {
+ ret = NUMERIC_CMP(tag_left, tag_right);
+ if (ret == 0) {
/* ID is the third element in the entry, after two short
integers (tag and perm), i.e at offset 4.
*/
id_left = IVAL(left, 4);
id_right = IVAL(right, 4);
- ret = id_left - id_right;
+ ret = NUMERIC_CMP(id_left, id_right);
}
return ret;
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 62ad506..7380598 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2147,6 +2147,12 @@ static struct tevent_req *vfswrap_offload_write_send(
.remaining = to_copy,
};
+ status = vfs_offload_token_ctx_init(handle->conn->sconn->client,
+ &vfswrap_offload_ctx);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+
tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
switch (fsctl) {
diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c
index 327a7ee..ea0417d 100644
--- a/source3/modules/vfs_recycle.c
+++ b/source3/modules/vfs_recycle.c
@@ -55,10 +55,14 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
const char *service,
const char *user)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
struct recycle_config_data *config = NULL;
int ret;
int t;
- const char *buff;
+ const char *buff = NULL;
+ const char **tmplist = NULL;
+ char *repository = NULL;
ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
if (ret < 0) {
@@ -75,10 +79,30 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
errno = ENOMEM;
return -1;
}
- config->repository = lp_parm_const_string(SNUM(handle->conn),
- "recycle",
- "repository",
- ".recycle");
+ buff = lp_parm_const_string(SNUM(handle->conn),
+ "recycle",
+ "repository",
+ ".recycle");
+ repository = talloc_sub_full(
+ config,
+ lp_servicename(talloc_tos(), lp_sub, SNUM(handle->conn)),
+ handle->conn->session_info->unix_info->unix_name,
+ handle->conn->connectpath,
+ handle->conn->session_info->unix_token->gid,
+ handle->conn->session_info->unix_info->sanitized_username,
+ handle->conn->session_info->info->domain_name,
+ buff);
+ if (repository == NULL) {
+ DBG_ERR("talloc_sub_full() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ /* shouldn't we allow absolute path names here? --metze */
+ /* Yes :-). JRA. */
+ trim_char(repository, '\0', '/');
+ config->repository = repository;
+
config->keeptree = lp_parm_bool(SNUM(handle->conn),
"recycle",
"keeptree",
@@ -95,18 +119,48 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
"recycle",
"touch_mtime",
False);
- config->exclude = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "exclude",
- NULL);
- config->exclude_dir = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "exclude_dir",
- NULL);
- config->noversions = lp_parm_string_list(SNUM(handle->conn),
- "recycle",
- "noversions",
- NULL);
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "exclude",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->exclude = discard_const_p(const char *, tmpcpy);
+ }
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "exclude_dir",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->exclude_dir = discard_const_p(const char *, tmpcpy);
+ }
+ tmplist = lp_parm_string_list(SNUM(handle->conn),
+ "recycle",
+ "noversions",
+ NULL);
+ if (tmplist != NULL) {
+ char **tmpcpy = str_list_copy(config, tmplist);
+ if (tmpcpy == NULL) {
+ DBG_ERR("str_list_copy() failed\n");
+ TALLOC_FREE(config);
+ errno = ENOMEM;
+ return -1;
+ }
+ config->noversions = discard_const_p(const char *, tmpcpy);
+ }
config->minsize = conv_str_size(lp_parm_const_string(
SNUM(handle->conn), "recycle", "minsize", NULL));
config->maxsize = conv_str_size(lp_parm_const_string(
@@ -421,42 +475,27 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
int flags)
{
- const struct loadparm_substitution *lp_sub =
- loadparm_s3_global_substitution();
- connection_struct *conn = handle->conn;
+ TALLOC_CTX *frame = NULL;
struct smb_filename *full_fname = NULL;
char *path_name = NULL;
- char *temp_name = NULL;
- char *final_name = NULL;
+ const char *temp_name = NULL;
+ const char *final_name = NULL;
struct smb_filename *smb_fname_final = NULL;
- const char *base;
- char *repository = NULL;
+ const char *base = NULL;
int i = 1;
off_t file_size; /* space_avail; */
bool exist;
int rc = -1;
- struct recycle_config_data *config;
+ struct recycle_config_data *config = NULL;
SMB_VFS_HANDLE_GET_DATA(handle,
config,
struct recycle_config_data,
- return true);
+ return -1);
- repository = talloc_sub_full(
- NULL,
- lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
- conn->session_info->unix_info->unix_name,
- conn->connectpath,
- conn->session_info->unix_token->gid,
- conn->session_info->unix_info->sanitized_username,
- conn->session_info->info->domain_name,
- config->repository);
- ALLOC_CHECK(repository, done);
- /* shouldn't we allow absolute path names here? --metze */
- /* Yes :-). JRA. */
- trim_char(repository, '\0', '/');
+ frame = talloc_stackframe();
- if(!repository || *(repository) == '\0') {
+ if (config->repository[0] == '\0') {
DEBUG(3, ("recycle: repository path not set, purging %s...\n",
smb_fname_str_dbg(smb_fname)));
rc = SMB_VFS_NEXT_UNLINKAT(handle,
@@ -466,16 +505,18 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
goto done;
}
- full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ full_fname = full_path_from_dirfsp_atname(frame,
dirfsp,
smb_fname);
if (full_fname == NULL) {
- return -1;
+ rc = -1;
+ errno = ENOMEM;
+ goto done;
}
/* we don't recycle the recycle bin... */
- if (strncmp(full_fname->base_name, repository,
- strlen(repository)) == 0) {
+ if (strncmp(full_fname->base_name, config->repository,
+ strlen(config->repository)) == 0) {
DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n"));
rc = SMB_VFS_NEXT_UNLINKAT(handle,
dirfsp,
@@ -539,7 +580,7 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
*/
/* extract filename and path */
- if (!parent_dirname(talloc_tos(), full_fname->base_name, &path_name, &base)) {
+ if (!parent_dirname(frame, full_fname->base_name, &path_name, &base)) {
rc = -1;
errno = ENOMEM;
goto done;
@@ -571,13 +612,16 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
}
if (config->keeptree) {
- if (asprintf(&temp_name, "%s/%s", repository, path_name) == -1) {
- ALLOC_CHECK(temp_name, done);
+ temp_name = talloc_asprintf(frame, "%s/%s",
+ config->repository,
+ path_name);
+ if (temp_name == NULL) {
+ rc = -1;
+ goto done;
}
} else {
- temp_name = SMB_STRDUP(repository);
+ temp_name = config->repository;
}
- ALLOC_CHECK(temp_name, done);
exist = recycle_directory_exist(handle, temp_name);
if (exist) {
@@ -600,12 +644,15 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
}
}
- if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) {
- ALLOC_CHECK(final_name, done);
+ final_name = talloc_asprintf(frame, "%s/%s",
+ temp_name, base);
+ if (final_name == NULL) {
+ rc = -1;
+ goto done;
}
/* Create smb_fname with final base name and orig stream name. */
- smb_fname_final = synthetic_smb_fname(talloc_tos(),
+ smb_fname_final = synthetic_smb_fname(frame,
final_name,
full_fname->stream_name,
NULL,
@@ -641,20 +688,16 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
/* rename file we move to recycle bin */
i = 1;
while (recycle_file_exist(handle, smb_fname_final)) {
- SAFE_FREE(final_name);
- if (asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base) == -1) {
- ALLOC_CHECK(final_name, done);
- }
+ char *copy = NULL;
+
TALLOC_FREE(smb_fname_final->base_name);
- smb_fname_final->base_name = talloc_strdup(smb_fname_final,
- final_name);
- if (smb_fname_final->base_name == NULL) {
- rc = SMB_VFS_NEXT_UNLINKAT(handle,
- dirfsp,
- smb_fname,
- flags);
+ copy = talloc_asprintf(smb_fname_final, "%s/Copy #%d of %s",
+ temp_name, i++, base);
+ if (copy == NULL) {
+ rc = -1;
goto done;
}
+ smb_fname_final->base_name = copy;
}
DEBUG(10, ("recycle: Moving %s to %s\n", smb_fname_str_dbg(full_fname),
@@ -681,12 +724,7 @@ static int recycle_unlink_internal(vfs_handle_struct *handle,
recycle_do_touch(handle, smb_fname_final, config->touch_mtime);
done:
- TALLOC_FREE(path_name);
- SAFE_FREE(temp_name);
- SAFE_FREE(final_name);
- TALLOC_FREE(full_fname);
- TALLOC_FREE(smb_fname_final);
- TALLOC_FREE(repository);
+ TALLOC_FREE(frame);
return rc;
}
diff --git a/source3/modules/vfs_vxfs.c b/source3/modules/vfs_vxfs.c
index aae2ca1..ecc53d0 100644
--- a/source3/modules/vfs_vxfs.c
+++ b/source3/modules/vfs_vxfs.c
@@ -111,13 +111,13 @@ static int vxfs_ace_cmp(const void *ace1, const void *ace2)
type_a1 = SVAL(ace1, 0);
type_a2 = SVAL(ace2, 0);
- ret = (type_a1 - type_a2);
- if (!ret) {
+ ret = NUMERIC_CMP(type_a1, type_a2);
+ if (ret == 0) {
/* Compare ID under type */
/* skip perm thus take offset as 4*/
id_a1 = IVAL(ace1, 4);
id_a2 = IVAL(ace2, 4);
- ret = id_a1 - id_a2;
+ ret = NUMERIC_CMP(id_a1, id_a2);
}
return ret;
diff --git a/source3/modules/vfs_widelinks.c b/source3/modules/vfs_widelinks.c
index c5b5084..4339f6d 100644
--- a/source3/modules/vfs_widelinks.c
+++ b/source3/modules/vfs_widelinks.c
@@ -383,8 +383,17 @@ static int widelinks_openat(vfs_handle_struct *handle,
}
lstat_ret = SMB_VFS_NEXT_LSTAT(handle,
full_fname);
- if (lstat_ret != -1 &&
- VALID_STAT(full_fname->st) &&
+ if (lstat_ret == -1) {
+ /*
+ * Path doesn't exist. We must
+ * return errno from LSTAT.
+ */
+ int saved_errno = errno;
+ TALLOC_FREE(full_fname);
+ errno = saved_errno;
+ return -1;
+ }
+ if (VALID_STAT(full_fname->st) &&
S_ISLNK(full_fname->st.st_ex_mode)) {
fsp->fsp_name->st = full_fname->st;
}
diff --git a/source3/nmbd/nmbd.h b/source3/nmbd/nmbd.h
index f207eb9..0a8e345 100644
--- a/source3/nmbd/nmbd.h
+++ b/source3/nmbd/nmbd.h
@@ -26,6 +26,388 @@
#endif
#include "libsmb/nmblib.h"
+
+#define INFO_VERSION "INFO/version"
+#define INFO_COUNT "INFO/num_entries"
+#define INFO_ID_HIGH "INFO/id_high"
+#define INFO_ID_LOW "INFO/id_low"
+#define ENTRY_PREFIX "ENTRY/"
+
+#define PERMANENT_TTL 0
+
+/* NTAS uses 2, NT uses 1, WfWg uses 0 */
+#define MAINTAIN_LIST 2
+#define ELECTION_VERSION 1
+
+#define REFRESH_TIME (15*60)
+#define NAME_POLL_REFRESH_TIME (5*60)
+#define NAME_POLL_INTERVAL 15
+
+/* Workgroup state identifiers. */
+#define AM_POTENTIAL_MASTER_BROWSER(work) ((work)->mst_state == MST_POTENTIAL)
+#define AM_LOCAL_MASTER_BROWSER(work) ((work)->mst_state == MST_BROWSER)
+#define AM_DOMAIN_MASTER_BROWSER(work) ((work)->dom_state == DOMAIN_MST)
+#define AM_DOMAIN_MEMBER(work) ((work)->log_state == LOGON_SRV)
+
+/* Microsoft browser NetBIOS name. */
+#define MSBROWSE "\001\002__MSBROWSE__\002"
+
+/* Mail slots. */
+#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
+#define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON"
+#define NT_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NTLOGON"
+#define LANMAN_MAILSLOT "\\MAILSLOT\\LANMAN"
+
+/* Samba definitions for find_name_on_subnet(). */
+#define FIND_ANY_NAME 0
+#define FIND_SELF_NAME 1
+
+/*
+ * The different name types that can be in namelists.
+ *
+ * SELF_NAME should only be on the broadcast and unicast subnets.
+ * LMHOSTS_NAME should only be in the remote_broadcast_subnet.
+ * REGISTER_NAME, DNS_NAME, DNSFAIL_NAME should only be in the wins_server_subnet.
+ * WINS_PROXY_NAME should only be on the broadcast subnets.
+ * PERMANENT_NAME can be on all subnets except remote_broadcast_subnet.
+ *
+ */
+
+enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
+ DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
+
+enum master_state {
+ MST_NONE,
+ MST_POTENTIAL,
+ MST_BACKUP,
+ MST_MSB,
+ MST_BROWSER,
+ MST_UNBECOMING_MASTER
+};
+
+enum domain_state {
+ DOMAIN_NONE,
+ DOMAIN_WAIT,
+ DOMAIN_MST
+};
+
+enum logon_state {
+ LOGON_NONE,
+ LOGON_WAIT,
+ LOGON_SRV
+};
+
+struct subnet_record;
+
+struct nmb_data {
+ uint16_t nb_flags; /* Netbios flags. */
+ int num_ips; /* Number of ip entries. */
+ struct in_addr *ip; /* The ip list for this name. */
+
+ enum name_source source; /* Where the name came from. */
+
+ time_t death_time; /* The time the record must be removed (do not remove if 0). */
+ time_t refresh_time; /* The time the record should be refreshed. */
+
+ uint64_t id; /* unique id */
+ struct in_addr wins_ip; /* the address of the wins server this record comes from */
+
+ int wins_flags; /* similar to the netbios flags but different ! */
+};
+
+/* This structure represents an entry in a local netbios name list. */
+struct name_record {
+ struct name_record *prev, *next;
+ struct subnet_record *subnet;
+ struct nmb_name name; /* The netbios name. */
+ struct nmb_data data; /* The netbios data. */
+};
+
+/* Browser cache for synchronising browse lists. */
+struct browse_cache_record {
+ struct browse_cache_record *prev, *next;
+ unstring lmb_name;
+ unstring work_group;
+ struct in_addr ip;
+ time_t sync_time;
+ time_t death_time; /* The time the record must be removed. */
+};
+
+/* used for server information: client, nameserv and ipc */
+struct server_info_struct {
+ fstring name;
+ uint32_t type;
+ fstring comment;
+ fstring domain; /* used ONLY in ipc.c NOT namework.c */
+ bool server_added; /* used ONLY in ipc.c NOT namework.c */
+};
+
+/* This is used to hold the list of servers in my domain, and is
+ contained within lists of domains. */
+
+struct server_record {
+ struct server_record *next;
+ struct server_record *prev;
+
+ struct subnet_record *subnet;
+
+ struct server_info_struct serv;
+ time_t death_time;
+};
+
+/* A workgroup structure. It contains a list of servers. */
+struct work_record {
+ struct work_record *next;
+ struct work_record *prev;
+
+ struct subnet_record *subnet;
+
+ struct server_record *serverlist;
+
+ /* Stage of development from non-local-master up to local-master browser. */
+ enum master_state mst_state;
+
+ /* Stage of development from non-domain-master to domain-master browser. */
+ enum domain_state dom_state;
+
+ /* Stage of development from non-logon-server to logon server. */
+ enum logon_state log_state;
+
+ /* Work group info. */
+ unstring work_group;
+ int token; /* Used when communicating with backup browsers. */
+ unstring local_master_browser_name; /* Current local master browser. */
+
+ /* Announce info. */
+ time_t lastannounce_time;
+ int announce_interval;
+ bool needannounce;
+
+ /* Timeout time for this workgroup. 0 means permanent. */
+ time_t death_time;
+
+ /* Election info */
+ bool RunningElection;
+ bool needelection;
+ int ElectionCount;
+ uint32_t ElectionCriterion;
+
+ /* Domain master browser info. Used for efficient syncs. */
+ struct nmb_name dmb_name;
+ struct in_addr dmb_addr;
+};
+
+/* typedefs needed to define copy & free functions for userdata. */
+struct userdata_struct;
+
+typedef struct userdata_struct * (*userdata_copy_fn)(struct userdata_struct *);
+typedef void (*userdata_free_fn)(struct userdata_struct *);
+
+/* Structure to define any userdata passed around. */
+
+struct userdata_struct {
+ userdata_copy_fn copy_fn;
+ userdata_free_fn free_fn;
+ unsigned int userdata_len;
+ char data[16]; /* 16 is to ensure alignment/padding on all systems */
+};
+
+struct response_record;
+struct packet_struct;
+struct res_rec;
+
+/* typedef to define the function called when this response packet comes in. */
+typedef void (*response_function)(struct subnet_record *, struct response_record *,
+ struct packet_struct *);
+
+/* typedef to define the function called when this response record times out. */
+typedef void (*timeout_response_function)(struct subnet_record *,
+ struct response_record *);
+
+/* typedef to define the function called when the request that caused this
+ response record to be created is successful. */
+typedef void (*success_function)(struct subnet_record *, struct userdata_struct *, ...);
+
+/* typedef to define the function called when the request that caused this
+ response record to be created is unsuccessful. */
+typedef void (*fail_function)(struct subnet_record *, struct response_record *, ...);
+
+/* List of typedefs for success and fail functions of the different query
+ types. Used to catch any compile time prototype errors. */
+
+typedef void (*register_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ uint16_t,
+ int,
+ struct in_addr);
+typedef void (*register_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*release_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ struct in_addr);
+typedef void (*release_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*refresh_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ uint16_t,
+ int,
+ struct in_addr);
+typedef void (*refresh_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *);
+
+typedef void (*query_name_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct nmb_name *,
+ struct in_addr,
+ struct res_rec *answers);
+
+typedef void (*query_name_fail_function)( struct subnet_record *,
+ struct response_record *,
+ struct nmb_name *,
+ int);
+
+typedef void (*node_status_success_function)( struct subnet_record *,
+ struct userdata_struct *,
+ struct res_rec *,
+ struct in_addr);
+typedef void (*node_status_fail_function)( struct subnet_record *,
+ struct response_record *);
+
+/* Initiated name queries are recorded in this list to track any responses. */
+
+struct response_record {
+ struct response_record *next;
+ struct response_record *prev;
+
+ uint16_t response_id;
+
+ /* Callbacks for packets received or not. */
+ response_function resp_fn;
+ timeout_response_function timeout_fn;
+
+ /* Callbacks for the request succeeding or not. */
+ success_function success_fn;
+ fail_function fail_fn;
+
+ struct packet_struct *packet;
+
+ struct userdata_struct *userdata;
+
+ int num_msgs;
+
+ time_t repeat_time;
+ time_t repeat_interval;
+ int repeat_count;
+
+ /* Recursion protection. */
+ bool in_expiration_processing;
+};
+
+/* A subnet structure. It contains a list of workgroups and netbios names. */
+
+/*
+ B nodes will have their own, totally separate subnet record, with their
+ own netbios name set. These do NOT interact with other subnet records'
+ netbios names.
+*/
+
+enum subnet_type {
+ NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
+ UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
+ REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
+ WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
+};
+
+struct subnet_record {
+ struct subnet_record *next;
+ struct subnet_record *prev;
+
+ char *subnet_name; /* For Debug identification. */
+ enum subnet_type type; /* To catagorize the subnet. */
+
+ struct work_record *workgrouplist; /* List of workgroups. */
+ struct name_record *namelist; /* List of netbios names. */
+ struct response_record *responselist; /* List of responses expected. */
+
+ bool namelist_changed;
+ bool work_changed;
+
+ struct in_addr bcast_ip;
+ struct in_addr mask_ip;
+ struct in_addr myip;
+ int nmb_sock; /* socket to listen for unicast 137. */
+ int nmb_bcast; /* socket to listen for broadcast 137. */
+ int dgram_sock; /* socket to listen for unicast 138. */
+ int dgram_bcast; /* socket to listen for broadcast 138. */
+};
+
+/* Broadcast packet announcement intervals, in minutes. */
+
+/* Attempt to add domain logon and domain master names. */
+#define CHECK_TIME_ADD_DOM_NAMES 5
+
+/* Search for master browsers of workgroups samba knows about,
+ except default. */
+#define CHECK_TIME_MST_BROWSE 5
+
+/* Request backup browser announcements from other servers. */
+#define CHECK_TIME_ANNOUNCE_BACKUP 15
+
+/* Request host announcements from other servers: min and max of interval. */
+#define CHECK_TIME_MIN_HOST_ANNCE 3
+#define CHECK_TIME_MAX_HOST_ANNCE 12
+
+/* Announce as master to WINS server and any Primary Domain Controllers. */
+#define CHECK_TIME_MST_ANNOUNCE 15
+
+/* Time between syncs from domain master browser to local master browsers. */
+#define CHECK_TIME_DMB_TO_LMB_SYNC 15
+
+/* Do all remote announcements this often. */
+#define REMOTE_ANNOUNCE_INTERVAL 180
+
+/* what is the maximum period between name refreshes. Note that this only
+ affects non-permanent self names (in seconds) */
+#define MAX_REFRESH_TIME (60*20)
+
+/* The Extinction interval: 4 days, time a node will stay in released state */
+#define EXTINCTION_INTERVAL (4*24*60*60)
+
+/* The Extinction time-out: 1 day, time a node will stay in deleted state */
+#define EXTINCTION_TIMEOUT (24*60*60)
+
+/* Macro's to enumerate subnets either with or without
+ the UNICAST subnet. */
+
+extern struct subnet_record *subnetlist;
+extern struct subnet_record *unicast_subnet;
+extern struct subnet_record *wins_server_subnet;
+extern struct subnet_record *remote_broadcast_subnet;
+
+#define FIRST_SUBNET subnetlist
+#define NEXT_SUBNET_EXCLUDING_UNICAST(x) ((x)->next)
+#define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
+
+/* wins replication record used between nmbd and wrepld */
+typedef struct _WINS_RECORD {
+ char name[17];
+ char type;
+ int nb_flags;
+ int wins_flags;
+ uint64_t id;
+ int num_ips;
+ struct in_addr ip[25];
+ struct in_addr wins_ip;
+} WINS_RECORD;
+
#include "nmbd/nmbd_proto.h"
#define NMBD_WAIT_INTERFACES_TIME_USEC (250 * 1000)
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index a1d8dee..1da3657 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -43,6 +43,7 @@ bool nmbd_init_packet_server(void)
status = nb_packet_server_create(
NULL, nmbd_event_context(),
+ global_nmbd_socket_dir(),
lp_parm_int(-1, "nmbd", "unexpected_clients", 200),
&packet_server);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
index 0724dd0..ed16278 100644
--- a/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
+++ b/source3/rpc_server/wkssvc/srv_wkssvc_nt.c
@@ -50,7 +50,7 @@ static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
/* Called from qsort to compare two domain users in a dom_usr_t array
* for sorting by login time. Return >0 if usr1 login time was later
* than usr2 login time, <0 if it was earlier */
- return (usr1->login_time - usr2->login_time);
+ return NUMERIC_CMP(usr1->login_time, usr2->login_time);
}
/*******************************************************************
diff --git a/source3/script/tests/test_recycle.sh b/source3/script/tests/test_recycle.sh
index 8c9291f..ba1d0a5 100755
--- a/source3/script/tests/test_recycle.sh
+++ b/source3/script/tests/test_recycle.sh
@@ -90,11 +90,16 @@ quit
return 0
}
+panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG)
testit "recycle" \
test_recycle ||
failed=$((failed + 1))
+panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG)
+
+testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1)
+
#
# Cleanup.
do_cleanup
diff --git a/source3/script/tests/test_widelink_dfs_ci.sh b/source3/script/tests/test_widelink_dfs_ci.sh
new file mode 100755
index 0000000..6ae5cf5
--- /dev/null
+++ b/source3/script/tests/test_widelink_dfs_ci.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# regression test for dfs access with wide links enabled on dfs share
+# Ensure we still maintain case insensitivity.
+
+if [ $# -lt 7 ]; then
+ cat <<EOF
+Usage: test_widelink_dfs_ci.sh SERVER SERVER_IP SHARE USERNAME PASSWORD PREFIX SMBCLIENT <smbclient arguments>
+EOF
+ exit 1
+fi
+
+SERVER="$1"
+SERVER_IP="$2"
+SHARE="$3"
+USERNAME="$4"
+PASSWORD="$5"
+PREFIX="$6"
+SMBCLIENT="$7"
+shift 7
+ADDARGS="$@"
+
+incdir=$(dirname "$0")"/../../../testprogs/blackbox"
+. "$incdir/subunit.sh"
+. "$incdir/common_test_fns.inc"
+
+failed=0
+
+# Do not let deprecated option warnings muck this up
+SAMBA_DEPRECATED_SUPPRESS=1
+export SAMBA_DEPRECATED_SUPPRESS
+
+# Test chdir'ing into a lowercase directory with upper case.
+test_ci()
+{
+ tmpfile="$PREFIX/smbclient_ci_commands"
+
+ cat >"$tmpfile" <<EOF
+mkdir x
+cd X
+cd ..
+rmdir x
+quit
+EOF
+
+ cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/msdfs-share-wl -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
+ eval echo "$cmd"
+ out=$(eval "$cmd")
+ ret=$?
+ rm -f "$tmpfile"
+
+ if [ $ret != 0 ]; then
+ echo "$out"
+ echo "failed create x then chdir into X with error $ret"
+ return 1
+ fi
+
+ echo "$out" | grep 'NT_STATUS_'
+ ret="$?"
+ if [ "$ret" -eq 0 ]; then
+ echo "$out"
+ echo "Error create x then chdir into X"
+ return 1
+ fi
+ return 0
+}
+
+testit "creating a directory x and chdir into it" \
+ test_ci ||
+ failed=$((failed + 1))
+
+testok "$0" "$failed"
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 0901c24..0648797 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1808,6 +1808,17 @@ plantestsuite("samba3.blackbox.smbclient-bug15435",
smbclient3,
configuration])
+plantestsuite("samba3.blackbox.widelink_dfs_ci",
+ "fileserver",
+ [os.path.join(samba3srcdir, "script/tests/test_widelink_dfs_ci.sh"),
+ "$SERVER",
+ "$SERVER_IP",
+ "msdfs-share-wl",
+ "$USERNAME",
+ "$PASSWORD",
+ "$PREFIX",
+ smbclient3])
+
if have_cluster_support:
t = "readdir-timestamp"
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 6aad76a..42bb323 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -1312,6 +1312,24 @@ next:
}
if (fd == -1) {
+ /*
+ * vfs_widelink widelink_openat will update stat for fsp
+ * and return ELOOP for non-existing link, we can report
+ * the link here and let calling code decide what to do.
+ */
+ if ((errno == ELOOP) && S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+ status = create_open_symlink_err(mem_ctx,
+ dirfsp,
+ &rel_fname,
+ &symlink_err);
+ if (NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_STOPPED_ON_SYMLINK;
+ } else {
+ DBG_ERR("read_symlink_reparse failed: %s\n",
+ nt_errstr(status));
+ }
+ goto fail;
+ }
status = map_nt_error_from_unix(errno);
DBG_DEBUG("SMB_VFS_OPENAT() failed: %s\n",
strerror(errno));
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 4928d1f..a954499 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -522,6 +522,11 @@ struct smbXsrv_connection {
} smbtorture;
bool signing_mandatory;
+ /*
+ * This is ConstrainedConnection in MS-SMB2,
+ * but with reversed value...
+ */
+ bool got_authenticated_session;
} smb2;
};
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index afb86ab..5b83d4d 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -494,6 +494,17 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *xconn,
goto inval;
}
+ if (!xconn->smb2.got_authenticated_session) {
+ D_INFO("Got SMB2_TRANSFORM header, "
+ "but not no authenticated session yet "
+ "client[%s] server[%s]\n",
+ tsocket_address_string(
+ xconn->remote_address, talloc_tos()),
+ tsocket_address_string(
+ xconn->local_address, talloc_tos()));
+ goto inval;
+ }
+
if (len < SMB2_TF_HDR_SIZE) {
DEBUG(1, ("%d bytes left, expected at least %d\n",
(int)len, SMB2_TF_HDR_SIZE));
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index ac71e55..d3b21ea 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -271,6 +271,13 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
/* we map anonymous to guest internally */
guest = true;
+ } else {
+ /*
+ * Remember we got one authenticated session on the connection
+ * in order to allow SMB3 decryption to happen
+ * (sadly even for future anonymous connections).
+ */
+ xconn->smb2.got_authenticated_session = true;
}
if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
@@ -288,7 +295,10 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
}
x->global->signing_algo = xconn->smb2.server.sign_algo;
x->global->encryption_cipher = xconn->smb2.server.cipher;
- if (guest) {
+ if (*out_session_flags & SMB2_SESSION_FLAG_IS_GUEST) {
+ /*
+ * A fallback to guest can't do any encryption
+ */
x->global->encryption_cipher = SMB2_ENCRYPTION_NONE;
}
@@ -642,6 +652,12 @@ static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
return NT_STATUS_LOGON_FAILURE;
}
+ /*
+ * Remember we got one authenticated session on the connection
+ * in order to allow SMB3 decryption to happen
+ */
+ xconn->smb2.got_authenticated_session = true;
+
*out_session_id = session->global->session_wire_id;
return NT_STATUS_OK;
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
index b228036..20d8967 100644
--- a/source3/smbd/smb2_tcon.c
+++ b/source3/smbd/smb2_tcon.c
@@ -331,6 +331,10 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
}
}
+ if (guest_session) {
+ /* make sure we don't ask for optional encryption */
+ encryption_desired = false;
+ }
if (encryption_desired) {
encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
}
diff --git a/source3/utils/conn_tdb.c b/source3/utils/conn_tdb.c
index 3724bd4..3f4ef00 100644
--- a/source3/utils/conn_tdb.c
+++ b/source3/utils/conn_tdb.c
@@ -27,6 +27,7 @@
#include "conn_tdb.h"
#include "util_tdb.h"
#include "lib/util/string_wrappers.h"
+#include "../libcli/security/session.h"
struct connections_forall_state {
struct db_context *session_by_pid;
@@ -44,7 +45,7 @@ struct connections_forall_session {
uint16_t cipher;
uint16_t dialect;
uint16_t signing;
- uint8_t signing_flags;
+ bool authenticated;
};
static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
@@ -56,6 +57,7 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
uint32_t id = global->session_global_id;
struct connections_forall_session sess;
+ enum security_user_level ul;
if (global->auth_session_info == NULL) {
sess.uid = -1;
@@ -69,7 +71,12 @@ static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
sess.cipher = global->channels[0].encryption_cipher;
sess.signing = global->channels[0].signing_algo;
sess.dialect = global->connection_dialect;
- sess.signing_flags = global->signing_flags;
+ ul = security_session_user_level(global->auth_session_info, NULL);
+ if (ul >= SECURITY_USER) {
+ sess.authenticated = true;
+ } else {
+ sess.authenticated = false;
+ }
status = dbwrap_store(state->session_by_pid,
make_tdb_data((void*)&id, sizeof(id)),
@@ -134,6 +141,7 @@ static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
data.dialect = sess.dialect;
data.signing = sess.signing;
data.signing_flags = global->signing_flags;
+ data.authenticated = sess.authenticated;
state->count++;
diff --git a/source3/utils/conn_tdb.h b/source3/utils/conn_tdb.h
index 2a6e04e..23a5e21 100644
--- a/source3/utils/conn_tdb.h
+++ b/source3/utils/conn_tdb.h
@@ -36,6 +36,7 @@ struct connections_data {
uint16_t dialect;
uint8_t signing_flags;
uint16_t signing;
+ bool authenticated;
};
/* The following definitions come from lib/conn_tdb.c */
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index d95a209..43fa026 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -521,6 +521,11 @@ static int net_ads_info_json(ADS_STRUCT *ads)
goto failure;
}
+ ret = json_add_string (&jsobj, "Workgroup", ads->config.workgroup);
+ if (ret != 0) {
+ goto failure;
+ }
+
ret = json_add_string (&jsobj, "Realm", ads->config.realm);
if (ret != 0) {
goto failure;
@@ -627,6 +632,7 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
d_printf(_("LDAP server: %s\n"), addr);
d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
+ d_printf(_("Workgroup: %s\n"), ads->config.workgroup);
d_printf(_("Realm: %s\n"), ads->config.realm);
d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
d_printf(_("LDAP port: %d\n"), ads->ldap.port);
diff --git a/source3/utils/net_registry.c b/source3/utils/net_registry.c
index 5d1314e..b47a8ff 100644
--- a/source3/utils/net_registry.c
+++ b/source3/utils/net_registry.c
@@ -1146,7 +1146,7 @@ static int registry_value_cmp(
if (v1->type == v2->type) {
return data_blob_cmp(&v1->data, &v2->data);
}
- return v1->type - v2->type;
+ return NUMERIC_CMP(v1->type, v2->type);
}
static WERROR precheck_create_val(struct precheck_ctx *ctx,
diff --git a/source3/utils/sharesec.c b/source3/utils/sharesec.c
index a6481e2..4175729 100644
--- a/source3/utils/sharesec.c
+++ b/source3/utils/sharesec.c
@@ -120,19 +120,19 @@ static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
return 0;
if (ace1->type != ace2->type)
- return ace2->type - ace1->type;
+ return NUMERIC_CMP(ace2->type, ace1->type);
if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
return dom_sid_compare(&ace1->trustee, &ace2->trustee);
if (ace1->flags != ace2->flags)
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
if (ace1->access_mask != ace2->access_mask)
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
if (ace1->size != ace2->size)
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
return memcmp(ace1, ace2, sizeof(struct security_ace));
}
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index e0591ac..5df7158 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -510,22 +510,23 @@ static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
return -1;
if ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) &&
(ace2->flags & SEC_ACE_FLAG_INHERITED_ACE))
- return ace1 - ace2;
-
- if (ace1->type != ace2->type)
- return ace2->type - ace1->type;
+ return NUMERIC_CMP(ace2->type, ace1->type);
+ if (ace1->type != ace2->type) {
+ /* note the reverse order */
+ return NUMERIC_CMP(ace2->type, ace1->type);
+ }
if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
return dom_sid_compare(&ace1->trustee, &ace2->trustee);
if (ace1->flags != ace2->flags)
- return ace1->flags - ace2->flags;
+ return NUMERIC_CMP(ace1->flags, ace2->flags);
if (ace1->access_mask != ace2->access_mask)
- return ace1->access_mask - ace2->access_mask;
+ return NUMERIC_CMP(ace1->access_mask, ace2->access_mask);
if (ace1->size != ace2->size)
- return ace1->size - ace2->size;
+ return NUMERIC_CMP(ace1->size, ace2->size);
return memcmp(ace1, ace2, sizeof(struct security_ace));
}
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 4102b41..02a5f6d 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -483,9 +483,33 @@ static int traverse_connections_stdout(struct traverse_state *state,
char *server_id,
const char *machine,
const char *timestr,
- const char *encryption,
- const char *signing)
+ const char *encryption_cipher,
+ enum crypto_degree encryption_degree,
+ const char *signing_cipher,
+ enum crypto_degree signing_degree)
{
+ fstring encryption;
+ fstring signing;
+
+ if (encryption_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
+ } else {
+ fstr_sprintf(encryption, "-");
+ }
+ if (signing_degree == CRYPTO_DEGREE_FULL) {
+ fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
+ fstr_sprintf(signing, "partial(%s)", signing_cipher);
+ } else {
+ fstr_sprintf(signing, "-");
+ }
+
d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
servicename, server_id, machine, timestr, encryption, signing);
@@ -538,7 +562,9 @@ static int traverse_connections(const struct connections_data *crec,
return -1;
}
- if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ if (smbXsrv_is_encrypted(crec->encryption_flags) ||
+ smbXsrv_is_partially_encrypted(crec->encryption_flags))
+ {
switch (crec->cipher) {
case SMB_ENCRYPTION_GSSAPI:
encryption = "GSSAPI";
@@ -549,14 +575,31 @@ static int traverse_connections(const struct connections_data *crec,
case SMB2_ENCRYPTION_AES128_GCM:
encryption = "AES-128-GCM";
break;
+ case SMB2_ENCRYPTION_AES256_CCM:
+ encryption = "AES-256-CCM";
+ break;
+ case SMB2_ENCRYPTION_AES256_GCM:
+ encryption = "AES-256-GCM";
+ break;
default:
encryption = "???";
break;
}
- encryption_degree = CRYPTO_DEGREE_FULL;
+ if (smbXsrv_is_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_encrypted(crec->encryption_flags)) {
+ encryption_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
- if (smbXsrv_is_signed(crec->signing_flags)) {
+ if (smbXsrv_is_signed(crec->signing_flags) ||
+ smbXsrv_is_partially_signed(crec->signing_flags))
+ {
switch (crec->signing) {
case SMB2_SIGNING_MD5_SMB1:
signing = "HMAC-MD5";
@@ -574,7 +617,16 @@ static int traverse_connections(const struct connections_data *crec,
signing = "???";
break;
}
- signing_degree = CRYPTO_DEGREE_FULL;
+ if (smbXsrv_is_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_FULL;
+ } else if (smbXsrv_is_partially_signed(crec->signing_flags)) {
+ signing_degree = CRYPTO_DEGREE_PARTIAL;
+ }
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !crec->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
if (!state->json_output) {
@@ -584,7 +636,9 @@ static int traverse_connections(const struct connections_data *crec,
crec->machine,
timestr,
encryption,
- signing);
+ encryption_degree,
+ signing,
+ signing_degree);
} else {
result = traverse_connections_json(state,
crec,
@@ -615,6 +669,8 @@ static int traverse_sessionid_stdout(struct traverse_state *state,
if (encryption_degree == CRYPTO_DEGREE_FULL) {
fstr_sprintf(encryption, "%s", encryption_cipher);
+ } else if (encryption_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(encryption, "anonymous(%s)", encryption_cipher);
} else if (encryption_degree == CRYPTO_DEGREE_PARTIAL) {
fstr_sprintf(encryption, "partial(%s)", encryption_cipher);
} else {
@@ -622,6 +678,8 @@ static int traverse_sessionid_stdout(struct traverse_state *state,
}
if (signing_degree == CRYPTO_DEGREE_FULL) {
fstr_sprintf(signing, "%s", signing_cipher);
+ } else if (signing_degree == CRYPTO_DEGREE_ANONYMOUS) {
+ fstr_sprintf(signing, "anonymous(%s)", signing_cipher);
} else if (signing_degree == CRYPTO_DEGREE_PARTIAL) {
fstr_sprintf(signing, "partial(%s)", signing_cipher);
} else {
@@ -756,6 +814,11 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
encryption_degree = CRYPTO_DEGREE_PARTIAL;
}
+ if (encryption_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ encryption_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
if (smbXsrv_is_signed(session->signing_flags) ||
@@ -783,6 +846,11 @@ static int traverse_sessionid(const char *key, struct sessionid *session,
} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
signing_degree = CRYPTO_DEGREE_PARTIAL;
}
+ if (signing_degree != CRYPTO_DEGREE_NONE &&
+ !session->authenticated)
+ {
+ signing_degree = CRYPTO_DEGREE_ANONYMOUS;
+ }
}
diff --git a/source3/utils/status.h b/source3/utils/status.h
index c08aba4..6674f0d 100644
--- a/source3/utils/status.h
+++ b/source3/utils/status.h
@@ -38,6 +38,7 @@ struct traverse_state {
enum crypto_degree {
CRYPTO_DEGREE_NONE,
CRYPTO_DEGREE_PARTIAL,
+ CRYPTO_DEGREE_ANONYMOUS,
CRYPTO_DEGREE_FULL
};
diff --git a/source3/utils/status_json.c b/source3/utils/status_json.c
index ee24a3b..f558c91 100644
--- a/source3/utils/status_json.c
+++ b/source3/utils/status_json.c
@@ -258,6 +258,8 @@ static int add_crypto_to_json(struct json_object *parent_json,
if (degree == CRYPTO_DEGREE_NONE) {
degree_str = "none";
+ } else if (degree == CRYPTO_DEGREE_ANONYMOUS) {
+ degree_str = "anonymous";
} else if (degree == CRYPTO_DEGREE_PARTIAL) {
degree_str = "partial";
} else {
diff --git a/source3/winbindd/idmap_ad.c b/source3/winbindd/idmap_ad.c
index 5c9fe07..b800282 100644
--- a/source3/winbindd/idmap_ad.c
+++ b/source3/winbindd/idmap_ad.c
@@ -320,7 +320,10 @@ static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
struct tldap_context **pld)
{
struct netr_DsRGetDCNameInfo *dcinfo;
- struct sockaddr_storage dcaddr;
+ struct sockaddr_storage dcaddr = {
+ .ss_family = AF_UNSPEC,
+ };
+ struct sockaddr_storage *pdcaddr = NULL;
struct cli_credentials *creds;
struct loadparm_context *lp_ctx;
struct tldap_context *ld;
@@ -362,9 +365,13 @@ static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
* create_local_private_krb5_conf_for_domain() can deal with
* sitename==NULL
*/
+ if (strequal(domname, lp_realm()) || strequal(domname, lp_workgroup()))
+ {
+ pdcaddr = &dcaddr;
+ }
ok = create_local_private_krb5_conf_for_domain(
- lp_realm(), lp_workgroup(), sitename, &dcaddr);
+ lp_realm(), lp_workgroup(), sitename, pdcaddr);
TALLOC_FREE(sitename);
if (!ok) {
DBG_DEBUG("Could not create private krb5.conf\n");
diff --git a/source3/wscript_build b/source3/wscript_build
index ff8de1e..3fcdb55 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -901,6 +901,7 @@ bld.SAMBA3_SUBSYSTEM('LIBNMB',
LIBTSOCKET
LIBCLI_NETLOGON
samba3util
+ smbconf
addns
lmhosts
resolv