From 5f0615a601e014ed2da5c8117a9bc6df0bc6aad8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 20 Jun 2024 06:07:29 +0200 Subject: Merging upstream version 2:4.20.2+dfsg. Signed-off-by: Daniel Baumann --- source3/include/fstring.h | 27 ++ source3/include/includes.h | 5 +- source3/include/nameserv.h | 380 ++------------------------ source3/include/session.h | 1 + source3/include/smb.h | 26 +- source3/lib/sessionid_tdb.c | 8 + source3/lib/util_tdb.c | 4 +- source3/libads/kerberos.c | 32 +-- source3/libads/ldap.c | 16 +- source3/librpc/idl/ads.idl | 1 + source3/libsmb/clidgram.c | 6 +- source3/libsmb/dsgetdcname.c | 29 +- source3/libsmb/libsmb_xattr.c | 14 +- source3/libsmb/namequery.c | 21 +- source3/libsmb/nmblib.c | 12 +- source3/libsmb/nmblib.h | 2 + source3/libsmb/unexpected.c | 18 +- source3/libsmb/unexpected.h | 2 + source3/locking/brlock.c | 7 +- source3/modules/posixacl_xattr.c | 6 +- source3/modules/vfs_default.c | 6 + source3/modules/vfs_recycle.c | 176 +++++++----- source3/modules/vfs_vxfs.c | 6 +- source3/modules/vfs_widelinks.c | 13 +- source3/nmbd/nmbd.h | 382 +++++++++++++++++++++++++++ source3/nmbd/nmbd_packets.c | 1 + source3/rpc_server/wkssvc/srv_wkssvc_nt.c | 2 +- source3/script/tests/test_recycle.sh | 5 + source3/script/tests/test_widelink_dfs_ci.sh | 72 +++++ source3/selftest/tests.py | 11 + source3/smbd/files.c | 18 ++ source3/smbd/globals.h | 5 + source3/smbd/smb2_server.c | 11 + source3/smbd/smb2_sesssetup.c | 18 +- source3/smbd/smb2_tcon.c | 4 + source3/utils/conn_tdb.c | 12 +- source3/utils/conn_tdb.h | 1 + source3/utils/net_ads.c | 6 + source3/utils/net_registry.c | 2 +- source3/utils/sharesec.c | 8 +- source3/utils/smbcacls.c | 15 +- source3/utils/status.c | 82 +++++- source3/utils/status.h | 1 + source3/utils/status_json.c | 2 + source3/winbindd/idmap_ad.c | 11 +- source3/wscript_build | 1 + 46 files changed, 944 insertions(+), 544 deletions(-) create mode 100644 source3/include/fstring.h create mode 100755 source3/script/tests/test_widelink_dfs_ci.sh (limited to 'source3') 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 + + 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 . +*/ + +#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 + 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" <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 -- cgit v1.2.3