summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in21
-rw-r--r--source3/auth/auth_domain.c4
-rw-r--r--source3/auth/auth_util.c9
-rw-r--r--source3/auth/auth_winbind.c4
-rw-r--r--source3/auth/token_util.c20
-rw-r--r--source3/client/client.c115
-rw-r--r--source3/client/smbspool.c21
-rw-r--r--source3/configure.in19
-rw-r--r--source3/include/ads_protos.h4
-rw-r--r--source3/include/client.h26
-rw-r--r--source3/include/debug.h27
-rw-r--r--source3/include/doserr.h2
-rw-r--r--source3/include/libsmb_internal.h7
-rw-r--r--source3/include/memcache.h57
-rw-r--r--source3/include/passdb.h9
-rw-r--r--source3/include/popt_common.h1
-rw-r--r--source3/include/smb.h10
-rw-r--r--source3/include/smb_macros.h11
-rw-r--r--source3/include/trans2.h27
-rw-r--r--source3/lib/debug.c11
-rw-r--r--source3/lib/dummysmbd.c1
-rw-r--r--source3/lib/gencache.c15
-rw-r--r--source3/lib/interfaces.c1
-rw-r--r--source3/lib/memcache.c2
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/logo-small.pngbin0 -> 4485 bytes
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c98
-rw-r--r--source3/lib/netapi/examples/netdomjoin/netdomjoin.c12
-rw-r--r--source3/lib/netapi/joindomain.c43
-rw-r--r--source3/lib/netapi/serverinfo.c5
-rw-r--r--source3/lib/popt_common.c6
-rw-r--r--source3/lib/replace/system/network.h4
-rw-r--r--source3/lib/secace.c4
-rw-r--r--source3/lib/secdesc.c87
-rw-r--r--source3/lib/sharesec.c2
-rw-r--r--source3/lib/util.c52
-rw-r--r--source3/lib/util_reg_smbconf.c4
-rw-r--r--source3/lib/util_sid.c18
-rw-r--r--source3/lib/util_sock.c214
-rw-r--r--source3/lib/winbind_util.c49
-rw-r--r--source3/libads/ads_status.c9
-rw-r--r--source3/libads/ldap.c97
-rw-r--r--source3/libnet/libnet_conf.c746
-rw-r--r--source3/libnet/libnet_join.c162
-rw-r--r--source3/libnet/libnet_join.h12
-rw-r--r--source3/libsmb/cliconnect.c22
-rw-r--r--source3/libsmb/clidfs.c109
-rw-r--r--source3/libsmb/clidgram.c2
-rw-r--r--source3/libsmb/clientgen.c119
-rw-r--r--source3/libsmb/clifile.c44
-rw-r--r--source3/libsmb/clifsinfo.c366
-rw-r--r--source3/libsmb/clilist.c4
-rw-r--r--source3/libsmb/climessage.c6
-rw-r--r--source3/libsmb/clioplock.c2
-rw-r--r--source3/libsmb/cliprint.c4
-rw-r--r--source3/libsmb/cliquota.c4
-rw-r--r--source3/libsmb/clireadwrite.c31
-rw-r--r--source3/libsmb/clisecdesc.c45
-rw-r--r--source3/libsmb/clitrans.c8
-rw-r--r--source3/libsmb/doserr.c4
-rw-r--r--source3/libsmb/errormap.c105
-rw-r--r--source3/libsmb/libsmbclient.c98
-rw-r--r--source3/libsmb/ntlm_check.c5
-rw-r--r--source3/libsmb/ntlmssp.c7
-rw-r--r--source3/libsmb/smb_seal.c497
-rw-r--r--source3/libsmb/smb_signing.c8
-rw-r--r--source3/libsmb/smbencrypt.c20
-rw-r--r--source3/locking/locking.c5
-rw-r--r--source3/modules/nfs4_acls.c2
-rw-r--r--source3/modules/vfs_solarisacl.c4
-rw-r--r--source3/nmbd/nmbd_elections.c4
-rw-r--r--source3/nmbd/nmbd_packets.c7
-rw-r--r--source3/nmbd/nmbd_responserecordsdb.c24
-rw-r--r--source3/nsswitch/libwbclient/wbc_pam.c4
-rw-r--r--source3/nsswitch/libwbclient/wbc_pwd.c8
-rw-r--r--source3/nsswitch/libwbclient/wbc_sid.c35
-rw-r--r--source3/nsswitch/libwbclient/wbc_util.c16
-rw-r--r--source3/nsswitch/libwbclient/wbclient.h2
-rw-r--r--source3/param/loadparm.c8
-rw-r--r--source3/passdb/pdb_interface.c176
-rw-r--r--source3/passdb/pdb_ldap.c106
-rw-r--r--source3/passdb/pdb_smbpasswd.c190
-rw-r--r--source3/passdb/pdb_tdb.c283
-rw-r--r--source3/printing/nt_printing.c12
-rw-r--r--source3/printing/printing.c24
-rw-r--r--source3/registry/reg_api.c4
-rw-r--r--source3/registry/reg_cachehook.c10
-rw-r--r--source3/registry/reg_db.c24
-rw-r--r--source3/registry/regfio.c5
-rw-r--r--source3/rpc_client/cli_netlogon.c10
-rw-r--r--source3/rpc_parse/parse_buffer.c2
-rw-r--r--source3/rpc_parse/parse_prs.c14
-rw-r--r--source3/rpc_parse/parse_sec.c6
-rw-r--r--source3/rpc_parse/parse_spoolss.c4
-rw-r--r--source3/rpc_parse/parse_srv.c5
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c14
-rw-r--r--source3/rpc_server/srv_svcctl_nt.c2
-rw-r--r--source3/rpcclient/rpcclient.c12
-rwxr-xr-xsource3/script/tests/selftest.sh13
-rwxr-xr-xsource3/script/tests/test_smbclient_s3.sh12
-rwxr-xr-xsource3/script/tests/test_smbtorture_s3.sh2
-rwxr-xr-xsource3/script/tests/tests_all.sh7
-rw-r--r--source3/smbd/aio.c29
-rw-r--r--source3/smbd/blocking.c58
-rw-r--r--source3/smbd/dosmode.c18
-rw-r--r--source3/smbd/error.c69
-rw-r--r--source3/smbd/ipc.c59
-rw-r--r--source3/smbd/lanman.c2
-rw-r--r--source3/smbd/mangle_hash.c12
-rw-r--r--source3/smbd/message.c8
-rw-r--r--source3/smbd/negprot.c2
-rw-r--r--source3/smbd/notify.c45
-rw-r--r--source3/smbd/nttrans.c58
-rw-r--r--source3/smbd/open.c34
-rw-r--r--source3/smbd/oplock.c20
-rw-r--r--source3/smbd/pipes.c2
-rw-r--r--source3/smbd/process.c181
-rw-r--r--source3/smbd/reply.c371
-rw-r--r--source3/smbd/seal.c726
-rw-r--r--source3/smbd/service.c2
-rw-r--r--source3/smbd/sesssetup.c46
-rw-r--r--source3/smbd/trans2.c294
-rw-r--r--source3/smbd/vfs.c8
-rw-r--r--source3/torture/pdbtest.c18
-rw-r--r--source3/torture/torture.c61
-rw-r--r--source3/utils/net.c62
-rw-r--r--source3/utils/net_conf.c451
-rw-r--r--source3/utils/net_help.c1
-rw-r--r--source3/utils/net_rpc.c24
-rw-r--r--source3/utils/net_sam.c2
-rw-r--r--source3/utils/pdbedit.c201
-rw-r--r--source3/utils/smbcacls.c37
-rw-r--r--source3/utils/smbcquotas.c35
-rw-r--r--source3/utils/smbfilter.c28
-rw-r--r--source3/utils/smbget.c12
-rw-r--r--source3/winbindd/winbindd_ads.c12
-rw-r--r--source3/winbindd/winbindd_cm.c49
-rw-r--r--source3/winbindd/winbindd_group.c11
-rw-r--r--source3/winbindd/winbindd_rpc.c6
-rw-r--r--source3/winbindd/winbindd_util.c10
139 files changed, 5384 insertions, 2294 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index ec28b3bb22..2214292854 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -375,7 +375,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clistr.o libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \
- $(DOSERR_OBJ) \
+ libsmb/smb_seal.o $(DOSERR_OBJ) \
$(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
RPC_CLIENT_OBJ1 = rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o
@@ -552,7 +552,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \
- smbd/vfs.o smbd/statcache.o \
+ smbd/vfs.o smbd/statcache.o smbd/seal.o \
smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \
smbd/process.o smbd/service.o smbd/error.o \
printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
@@ -677,7 +677,7 @@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \
$(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) \
$(SECRETS_OBJ) $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(LDB_OBJ)
-LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o $(TDB_BASE_OBJ)
+LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o $(TDBBASE_OBJ)
# This shared library is intended for linking with unit test programs
# to test Samba internals. It's called libbigballofmud.so to
@@ -1415,7 +1415,7 @@ bin/libaddns.a: $(BINARY_PREREQS) $(LIBADDNS_OBJ)
bin/libnetapi.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBNETAPI_OBJ)
@echo Linking shared library $@
- @$(SHLD_DSO) $(LIBNETAPI_OBJ) $(LIBS) \
+ @$(SHLD_DSO) $(LIBNETAPI_OBJ) @LIBWBCLIENT_SHARED@ $(LIBS) \
$(LDAP_LIBS) $(KRB5LIBS) $(NSCD_LIBS) \
@SONAMEFLAG@`basename $@`.$(SONAME_VER)
@@ -1425,7 +1425,7 @@ bin/libnetapi.a: $(BINARY_PREREQS) $(LIBNETAPI_OBJ)
bin/libsmbclient.@SHLIBEXT@: $(BINARY_PREREQS) $(LIBSMBCLIENT_OBJ)
@echo Linking shared library $@
- @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) $(LIBS) \
+ @$(SHLD_DSO) $(LIBSMBCLIENT_OBJ) @LIBWBCLIENT_SHARED@ $(LIBS) \
$(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) \
@SONAMEFLAG@`basename $@`.$(SONAME_VER)
@@ -1532,7 +1532,7 @@ bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@ @LIBWBCLIEN
@POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) \
@WINBIND_LIBS@
-bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ)
+bin/vlp@EXEEXT@: $(BINARY_PREREQS) $(VLP_OBJ) @LIBWBCLIENT_SHARED@
@echo "Linking $@"
@$(CC) $(FLAGS) -o $@ $(VLP_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ \
$(KRB5LIBS) $(LDAP_LIBS) $(NSCD_LIBS) @LIBWBCLIENT_SHARED@
@@ -1997,6 +1997,7 @@ clean: delheaders
$(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(ROOT_SBIN_PROGS) \
$(MODULES) $(TORTURE_PROGS) $(LIBSMBCLIENT) $(LIBADDNS) \
$(LIBSMBSHAREMODES) $(EVERYTHING_PROGS) $(LIBNETAPI) \
+ bin/libwbclient.so.0 bin/timelimit \
.headers.stamp */src/*.o proto_exists
-rm -rf t_dir
@@ -2129,6 +2130,14 @@ Makefile: $(srcdir)/Makefile.in config.status
######################################################################
# Samba Testing Framework
+# Check shared libs for unresolved symbols
+test_shlibs: $(SHLIBS)
+ @echo "Testing $(SHLIBS) "
+ @for module in $(SHLIBS); do \
+ ./script/tests/dlopen.sh bin/$${module}.@SHLIBEXT@ \
+ || exit 1; \
+ done
+
# Check for NSS module problems.
test_nss_modules: nss_modules
@echo "Testing $(NSS_MODULES) "
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index b2c87174fd..1de9869f90 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -270,7 +270,9 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
&info3);
if (NT_STATUS_IS_OK(nt_status)) {
- (*server_info)->was_mapped |= user_info->was_mapped;
+ if (user_info->was_mapped) {
+ (*server_info)->was_mapped = user_info->was_mapped;
+ }
if ( ! (*server_info)->guest) {
/* if a real user check pam account restrictions */
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 3f65e6b126..fea1b2d761 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1103,7 +1103,7 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf
struct samu *sampass = NULL;
DOM_SID guest_sid;
bool ret;
- static const char zeros[16] = { 0, };
+ char zeros[16];
if ( !(sampass = samu_new( NULL )) ) {
return NT_STATUS_NO_MEMORY;
@@ -1138,6 +1138,7 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf
/* annoying, but the Guest really does have a session key, and it is
all zeros! */
+ ZERO_STRUCT(zeros);
(*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
(*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
@@ -1420,7 +1421,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
auth_serversupplied_info **server_info,
NET_USER_INFO_3 *info3)
{
- static const char zeros[16] = { 0, };
+ char zeros[16];
NTSTATUS nt_status = NT_STATUS_OK;
char *found_username = NULL;
@@ -1624,7 +1625,9 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
&(info3->uni_logon_srv));
/* ensure we are never given NULL session keys */
-
+
+ ZERO_STRUCT(zeros);
+
if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
result->user_session_key = data_blob_null;
} else {
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index 959c550524..b24aa3a75b 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -134,7 +134,9 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
}
if (NT_STATUS_IS_OK(nt_status)) {
- (*server_info)->was_mapped |= user_info->was_mapped;
+ if (user_info->was_mapped) {
+ (*server_info)->was_mapped = user_info->was_mapped;
+ }
}
}
} else if (NT_STATUS_IS_OK(nt_status)) {
diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c
index 27c98c9581..9ca5216af0 100644
--- a/source3/auth/token_util.c
+++ b/source3/auth/token_util.c
@@ -77,12 +77,19 @@ bool nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
NT_USER_TOKEN *get_root_nt_token( void )
{
- static NT_USER_TOKEN *token = NULL;
+ struct nt_user_token *token = NULL;
DOM_SID u_sid, g_sid;
struct passwd *pw;
+ void *cache_data;
- if ( token )
- return token;
+ cache_data = memcache_lookup_talloc(
+ NULL, SINGLETON_CACHE_TALLOC,
+ data_blob_string_const("root_nt_token"));
+
+ if (cache_data != NULL) {
+ return talloc_get_type_abort(
+ cache_data, struct nt_user_token);
+ }
if ( !(pw = sys_getpwnam( "root" )) ) {
DEBUG(0,("get_root_nt_token: getpwnam(\"root\") failed!\n"));
@@ -97,6 +104,11 @@ NT_USER_TOKEN *get_root_nt_token( void )
token = create_local_nt_token(NULL, &u_sid, False,
1, &global_sid_Builtin_Administrators);
+
+ memcache_add_talloc(
+ NULL, SINGLETON_CACHE_TALLOC,
+ data_blob_string_const("root_nt_token"), token);
+
return token;
}
@@ -284,7 +296,7 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
DEBUG(10, ("Create local NT token for %s\n",
sid_string_dbg(user_sid)));
- if (!(result = TALLOC_ZERO_P(mem_ctx, NT_USER_TOKEN))) {
+ if (!(result = TALLOC_ZERO_P(mem_ctx, struct nt_user_token))) {
DEBUG(0, ("talloc failed\n"));
return NULL;
}
diff --git a/source3/client/client.c b/source3/client/client.c
index f761d92bac..46f056021e 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -93,6 +93,9 @@ static unsigned int put_total_time_ms = 0;
/* totals globals */
static double dir_total;
+/* encrypted state. */
+static bool smb_encrypt;
+
/* root cli_state connection */
struct cli_state *cli;
@@ -2178,6 +2181,49 @@ static int cmd_open(void)
return 0;
}
+static int cmd_posix_encrypt(void)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+ if (cli->use_kerberos) {
+ status = cli_gss_smb_encryption_start(cli);
+ } else {
+ char *domain = NULL;
+ char *user = NULL;
+ char *password = NULL;
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ status = cli_raw_ntlm_smb_encryption_start(cli,
+ user,
+ password,
+ domain);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
+ } else {
+ d_printf("encryption on\n");
+ smb_encrypt = true;
+ }
+
+ return 0;
+}
+
/****************************************************************************
****************************************************************************/
@@ -2424,17 +2470,30 @@ static int cmd_posix(void)
return 1;
}
}
+ if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
+ caps = talloc_asprintf_append(caps, "posix_encrypt ");
+ if (!caps) {
+ return 1;
+ }
+ }
+ if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
+ caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
+ if (!caps) {
+ return 1;
+ }
+ }
if (*caps && caps[strlen(caps)-1] == ' ') {
caps[strlen(caps)-1] = '\0';
}
+
+ d_printf("Server supports CIFS capabilities %s\n", caps);
+
if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
return 1;
}
- d_printf("Selecting server supported CIFS capabilities %s\n", caps);
-
if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
CLI_DIRSEP_CHAR = '/';
*CLI_DIRSEP_STR = '/';
@@ -3731,16 +3790,28 @@ int cmd_iosize(void)
int iosize;
if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
- d_printf("iosize <n> or iosize 0x<n>. "
- "Minimum is 16384 (0x4000), "
- "max is 16776960 (0xFFFF00)\n");
+ if (!smb_encrypt) {
+ d_printf("iosize <n> or iosize 0x<n>. "
+ "Minimum is 16384 (0x4000), "
+ "max is 16776960 (0xFFFF00)\n");
+ } else {
+ d_printf("iosize <n> or iosize 0x<n>. "
+ "(Encrypted connection) ,"
+ "Minimum is 16384 (0x4000), "
+ "max is 130048 (0x1FC00)\n");
+ }
return 1;
}
iosize = strtol(buf,NULL,0);
- if (iosize < 0 || iosize > 0xFFFF00) {
+ if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
+ d_printf("iosize out of range for encrypted "
+ "connection (min = 16384 (0x4000), "
+ "max = 130048 (0x1FC00)");
+ return 1;
+ } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
d_printf("iosize out of range (min = 16384 (0x4000), "
- "max = 16776960 (0x0xFFFF00)");
+ "max = 16776960 (0xFFFF00)");
return 1;
}
@@ -3803,6 +3874,7 @@ static struct {
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
{"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+ {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
{"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
{"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
{"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
@@ -3915,7 +3987,8 @@ static int process_command_string(const char *cmd_in)
/* establish the connection if not already */
if (!cli) {
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL, desthost,
+ service, true, smb_encrypt);
if (!cli) {
return 1;
}
@@ -4255,16 +4328,22 @@ static void readline_callback(void)
timeout.tv_usec = 0;
sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
- /* We deliberately use receive_smb instead of
+ /* We deliberately use receive_smb_raw instead of
client_receive_smb as we want to receive
session keepalives and then drop them here.
*/
if (FD_ISSET(cli->fd,&fds)) {
- if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
+ if (receive_smb_raw(cli->fd,cli->inbuf,0,0,&cli->smb_rw_error) == -1) {
DEBUG(0, ("Read from server failed, maybe it closed the "
"connection\n"));
return;
}
+ if(CVAL(cli->inbuf,0) != SMBkeepalive) {
+ DEBUG(0, ("Read from server "
+ "returned unexpected packet!\n"));
+ return;
+ }
+
goto again;
}
@@ -4340,7 +4419,8 @@ static int process(const char *base_directory)
{
int rc = 0;
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ desthost, service, true, smb_encrypt);
if (!cli) {
return 1;
}
@@ -4369,7 +4449,8 @@ static int process(const char *base_directory)
static int do_host_query(const char *query_host)
{
- cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ query_host, "IPC$", true, smb_encrypt);
if (!cli)
return 1;
@@ -4382,7 +4463,8 @@ static int do_host_query(const char *query_host)
cli_cm_shutdown();
cli_cm_set_port( 139 );
- cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ query_host, "IPC$", true, smb_encrypt);
}
if (cli == NULL) {
@@ -4407,7 +4489,8 @@ static int do_tar_op(const char *base_directory)
/* do we already have a connection? */
if (!cli) {
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ desthost, service, true, smb_encrypt);
if (!cli)
return 1;
}
@@ -4657,6 +4740,9 @@ static int do_message_op(void)
case 'g':
grepable=true;
break;
+ case 'e':
+ smb_encrypt=true;
+ break;
case 'B':
return(do_smb_browse());
@@ -4747,6 +4833,7 @@ static int do_message_op(void)
calling_name = talloc_strdup(frame, global_myname() );
}
+ smb_encrypt = get_cmdline_auth_info_smb_encrypt();
init_names();
if(new_name_resolve_order)
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
index 4270eb4272..e7df22c2bc 100644
--- a/source3/client/smbspool.c
+++ b/source3/client/smbspool.c
@@ -47,7 +47,9 @@ static struct cli_state *smb_complete_connection(const char *, const char *,int
static struct cli_state *smb_connect(const char *, const char *, int, const char *, const char *, const char *, const char *);
static int smb_print(struct cli_state *, char *, FILE *);
static char * uri_unescape_alloc(const char *);
-
+#if 0
+static bool smb_encrypt;
+#endif
/*
* 'main()' - Main entry for SMB backend.
@@ -468,6 +470,23 @@ static struct cli_state
return NULL;
}
+#if 0
+ /* Need to work out how to specify this on the URL. */
+ if (smb_encrypt)
+ {
+ if (!cli_cm_force_encryption(cli,
+ username,
+ password,
+ workgroup,
+ share))
+ {
+ fprintf(stderr, "ERROR: encryption setup failed\n");
+ cli_shutdown(cli);
+ return NULL;
+ }
+ }
+#endif
+
return cli;
}
diff --git a/source3/configure.in b/source3/configure.in
index 0036133230..5eb85c727d 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -455,7 +455,7 @@ AC_ARG_ENABLE(krb5developer, [ --enable-krb5developer Turn on developer warnin
# DEVELOPER_CFLAGS, so that you can turn them on and off with a simple
# Makefile edit, avoiding the need to re-run configure.
if test x"$ac_cv_prog_gcc" = x"yes" ; then
- DEVELOPER_CFLAGS="-gstabs -Wall -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER"
+ DEVELOPER_CFLAGS="-g -Wall -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER"
# Add -Wdeclaration-after-statement if compiler supports it
AC_CACHE_CHECK(
[that the C compiler understands -Wdeclaration-after-statement],
@@ -3014,6 +3014,7 @@ AC_TRY_RUN([
#define NO_CONFIG_H 1
#define HAVE_IFACE_IFCONF 1
#define AUTOCONF_TEST 1
+#define SOCKET_WRAPPER_NOT_REPLACE
#include "${srcdir-.}/lib/replace/replace.c"
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)])
@@ -3031,7 +3032,10 @@ AC_TRY_RUN([
#define NO_CONFIG_H 1
#define HAVE_IFACE_IFREQ 1
#define AUTOCONF_TEST 1
+#define SOCKET_WRAPPER_NOT_REPLACE
#include "${srcdir-.}/lib/replace/replace.c"
+#include "${srcdir-.}/lib/replace/getaddrinfo.c"
+#include "${srcdir-.}/lib/replace/snprintf.c"
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)])
CPPFLAGS="$SAVE_CPPFLAGS"
@@ -3040,6 +3044,15 @@ if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
fi
fi
+dnl AIX 5.3.0.0
+AC_TRY_COMPILE([#include <sys/socket.h>],[
+struct sockaddr_storage s; s.__ss_family = 0],
+samba_cv_have_aix_sockaddr_storage=yes,samba_cv_have_aix_sockaddr_storage=no)
+
+if test x"$samba_cv_have_aix_sockaddr_storage" = x"yes"; then
+ AC_DEFINE(HAVE_AIX_SOCKADDR_STORAGE, 1, [Whether struct sockaddr_storage has __sa_family])
+fi
+
if test $iface = no; then
AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
SAVE_CPPFLAGS="$CPPFLAGS"
@@ -3049,7 +3062,9 @@ AC_TRY_RUN([
#define HAVE_IFACE_AIX 1
#define AUTOCONF_TEST 1
#undef _XOPEN_SOURCE_EXTENDED
+#define SOCKET_WRAPPER_NOT_REPLACE
#include "${srcdir-.}/lib/replace/replace.c"
+#include "${srcdir-.}/lib/replace/snprintf.c"
#include "${srcdir-.}/lib/interfaces.c"],
samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)])
CPPFLAGS="$SAVE_CPPFLAGS"
@@ -5089,7 +5104,7 @@ LIBNETAPI_SHARED=
LIBNETAPI=
AC_MSG_CHECKING(whether to build the libnetapi shared library)
AC_ARG_WITH(libnetapi,
-[ --with-libnetapi Build the libnetapi shared library (default=no undefined API)],
+[ --with-libnetapi Build the libnetapi shared library (default=yes if shared libs supported)],
[ case "$withval" in
*)
AC_MSG_RESULT(no)
diff --git a/source3/include/ads_protos.h b/source3/include/ads_protos.h
index 0292d91f4f..738df3ed40 100644
--- a/source3/include/ads_protos.h
+++ b/source3/include/ads_protos.h
@@ -114,3 +114,7 @@ ADS_STATUS ads_get_tokensids(ADS_STRUCT *ads,
DOM_SID *primary_group_sid,
DOM_SID **sids,
size_t *num_sids);
+ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ char ***ous,
+ size_t *num_ous);
diff --git a/source3/include/client.h b/source3/include/client.h
index 0047b2bf23..f8adf567de 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -27,7 +27,9 @@
will be a multiple of the page size on almost any system */
#define CLI_BUFFER_SIZE (0xFFFF)
#define CLI_SAMBA_MAX_LARGE_READX_SIZE (127*1024) /* Works for Samba servers */
+#define CLI_SAMBA_MAX_LARGE_WRITEX_SIZE (127*1024) /* Works for Samba servers */
#define CLI_WINDOWS_MAX_LARGE_READX_SIZE ((64*1024)-2) /* Windows servers are broken.... */
+#define CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE ((64*1024)-2) /* Windows servers are broken.... */
#define CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE (0xFFFF00) /* 24-bit len. */
#define CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE (0xFFFF00) /* 24-bit len. */
@@ -79,6 +81,28 @@ struct rpc_pipe_client {
struct dcinfo *dc;
};
+/* Transport encryption state. */
+enum smb_trans_enc_type { SMB_TRANS_ENC_NTLM, SMB_TRANS_ENC_GSS };
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+struct smb_tran_enc_state_gss {
+ gss_ctx_id_t gss_ctx;
+ gss_cred_id_t creds;
+};
+#endif
+
+struct smb_trans_enc_state {
+ enum smb_trans_enc_type smb_enc_type;
+ uint16 enc_ctx_num;
+ bool enc_on;
+ union {
+ NTLMSSP_STATE *ntlmssp_state;
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ struct smb_tran_enc_state_gss *gss_state;
+#endif
+ } s;
+};
+
struct cli_state {
int port;
int fd;
@@ -142,6 +166,8 @@ struct cli_state {
smb_sign_info sign_info;
+ struct smb_trans_enc_state *trans_enc_state; /* Setup if we're encrypting SMB's. */
+
/* the session key for this CLI, outside
any per-pipe authenticaion */
DATA_BLOB user_session_key;
diff --git a/source3/include/debug.h b/source3/include/debug.h
index 46e5620cc7..284671c730 100644
--- a/source3/include/debug.h
+++ b/source3/include/debug.h
@@ -161,9 +161,24 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
* will remove the extra conditional test.
*/
+/*
+ * From talloc.c:
+ */
+
+/* these macros gain us a few percent of speed on gcc */
+#if (__GNUC__ >= 3)
+/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
+ as its first argument */
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) (x)
+#define unlikely(x) (x)
+#endif
+
#define DEBUGLVL( level ) \
( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ DBGC_CLASS ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& dbghdr( level, DBGC_CLASS, __FILE__, FUNCTION_MACRO, (__LINE__) ) )
@@ -171,7 +186,7 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
#define DEBUGLVLC( dbgc_class, level ) \
( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ dbgc_class ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& dbghdr( level, DBGC_CLASS, __FILE__, FUNCTION_MACRO, (__LINE__) ) )
@@ -179,7 +194,7 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
#define DEBUG( level, body ) \
(void)( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ DBGC_CLASS ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& (dbghdr( level, DBGC_CLASS, __FILE__, FUNCTION_MACRO, (__LINE__) )) \
@@ -187,7 +202,7 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
#define DEBUGC( dbgc_class, level, body ) \
(void)( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ dbgc_class ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& (dbghdr( level, DBGC_CLASS, __FILE__, FUNCTION_MACRO, (__LINE__) )) \
@@ -195,14 +210,14 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
#define DEBUGADD( level, body ) \
(void)( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ DBGC_CLASS ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& (dbgtext body) )
#define DEBUGADDC( dbgc_class, level, body ) \
(void)( ((level) <= MAX_DEBUG_LEVEL) && \
- ((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
+ unlikely((DEBUGLEVEL_CLASS[ dbgc_class ] >= (level))|| \
(!DEBUGLEVEL_CLASS_ISSET[ dbgc_class ] && \
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& (dbgtext body) )
diff --git a/source3/include/doserr.h b/source3/include/doserr.h
index 079a5664dd..08f5b3e39d 100644
--- a/source3/include/doserr.h
+++ b/source3/include/doserr.h
@@ -216,12 +216,14 @@
#define WERR_BUF_TOO_SMALL W_ERROR(2123)
#define WERR_JOB_NOT_FOUND W_ERROR(2151)
#define WERR_DEST_NOT_FOUND W_ERROR(2152)
+#define WERR_USER_EXISTS W_ERROR(2224)
#define WERR_NOT_LOCAL_DOMAIN W_ERROR(2320)
#define WERR_DOMAIN_CONTROLLER_NOT_FOUND W_ERROR(2453)
#define WERR_SETUP_ALREADY_JOINED W_ERROR(2691)
#define WERR_SETUP_NOT_JOINED W_ERROR(2692)
#define WERR_SETUP_DOMAIN_CONTROLLER W_ERROR(2693)
+#define WERR_DEFAULT_JOIN_REQUIRED W_ERROR(2694)
#define WERR_DEVICE_NOT_AVAILABLE W_ERROR(4319)
#define WERR_STATUS_MORE_ENTRIES W_ERROR(0x0105)
diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h
index 19a3edc9bf..dbc115429b 100644
--- a/source3/include/libsmb_internal.h
+++ b/source3/include/libsmb_internal.h
@@ -106,6 +106,13 @@ struct smbc_internal_data {
* and retrieved with smbc_option_set() and smbc_option_get().
*/
void * _user_data;
+
+ /*
+ * Should we attempt UNIX smb encryption ?
+ * Set to 0 if we should never attempt, set to 1 if
+ * encryption requested, set to 2 if encryption required.
+ */
+ int _smb_encryption_level;
};
diff --git a/source3/include/memcache.h b/source3/include/memcache.h
index c4a2974b62..0a596b91a5 100644
--- a/source3/include/memcache.h
+++ b/source3/include/memcache.h
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
In-memory cache
- Copyright (C) Volker Lendecke 2005-2007
+ Copyright (C) Volker Lendecke 2007-2008
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
@@ -24,6 +24,15 @@
struct memcache;
+/*
+ * A memcache can store different subkeys with overlapping keys, the
+ * memcache_number becomes part of the key. Feel free to add caches of your
+ * own here.
+ *
+ * If you add talloc type caches, also note this in the switch statement in
+ * memcache_is_talloc().
+ */
+
enum memcache_number {
STAT_CACHE,
UID_SID_CACHE,
@@ -33,28 +42,74 @@ enum memcache_number {
GETWD_CACHE,
GETPWNAM_CACHE, /* talloc */
MANGLE_HASH2_CACHE,
+ PDB_GETPWSID_CACHE, /* talloc */
+ SINGLETON_CACHE_TALLOC, /* talloc */
SINGLETON_CACHE
};
+/*
+ * Create a memcache structure. max_size is in bytes, if you set it 0 it will
+ * not forget anything.
+ */
+
struct memcache *memcache_init(TALLOC_CTX *mem_ctx, size_t max_size);
+/*
+ * If you set this global memcache, use it as the default cache when NULL is
+ * passed to the memcache functions below. This is a workaround for many
+ * situations where passing the cache everywhere would be a big hassle.
+ */
+
void memcache_set_global(struct memcache *cache);
+/*
+ * Add a data blob to the cache
+ */
+
void memcache_add(struct memcache *cache, enum memcache_number n,
DATA_BLOB key, DATA_BLOB value);
+/*
+ * Add a talloc object to the cache. The difference to memcache_add() is that
+ * when the objects is to be discared, talloc_free is called for it. Also
+ * talloc_move() ownership of the object to the cache.
+ *
+ * Please note that the current implementation has a fixed relationship
+ * between what cache subtypes store talloc objects and which ones store plain
+ * blobs. We can fix this, but for now we don't have a mixed use of blobs vs
+ * talloc objects in the cache types.
+ */
+
void memcache_add_talloc(struct memcache *cache, enum memcache_number n,
DATA_BLOB key, void *ptr);
+/*
+ * Delete an object from the cache
+ */
+
void memcache_delete(struct memcache *cache, enum memcache_number n,
DATA_BLOB key);
+/*
+ * Look up an object from the cache. Memory still belongs to the cache, so
+ * make a copy of it if needed.
+ */
+
bool memcache_lookup(struct memcache *cache, enum memcache_number n,
DATA_BLOB key, DATA_BLOB *value);
+/*
+ * Look up an object from the cache. Memory still belongs to the cache, so
+ * make a copy of it if needed.
+ */
+
void *memcache_lookup_talloc(struct memcache *cache, enum memcache_number n,
DATA_BLOB key);
+/*
+ * Flush a complete cache subset.
+ */
+
void memcache_flush(struct memcache *cache, enum memcache_number n);
#endif
diff --git a/source3/include/passdb.h b/source3/include/passdb.h
index bb8a336b8c..b72ec6b0ba 100644
--- a/source3/include/passdb.h
+++ b/source3/include/passdb.h
@@ -242,20 +242,15 @@ struct pdb_search {
* changed to version 14 to move lookup_rids and lookup_names to return
* enum lsa_SidType rather than uint32.
* Changed to 16 for access to the trusted domain passwords (obnox).
+ * Changed to 17, the sampwent interface is gone.
*/
-#define PASSDB_INTERFACE_VERSION 16
+#define PASSDB_INTERFACE_VERSION 17
struct pdb_methods
{
const char *name; /* What name got this module */
- NTSTATUS (*setsampwent)(struct pdb_methods *, bool update, uint32 acb_mask);
-
- void (*endsampwent)(struct pdb_methods *);
-
- NTSTATUS (*getsampwent)(struct pdb_methods *, struct samu *user);
-
NTSTATUS (*getsampwnam)(struct pdb_methods *, struct samu *sam_acct, const char *username);
NTSTATUS (*getsampwsid)(struct pdb_methods *, struct samu *sam_acct, const DOM_SID *sid);
diff --git a/source3/include/popt_common.h b/source3/include/popt_common.h
index 1d3cc57acd..9e5503f270 100644
--- a/source3/include/popt_common.h
+++ b/source3/include/popt_common.h
@@ -49,6 +49,7 @@ struct user_auth_info {
bool got_pass;
bool use_kerberos;
int signing_state;
+ bool smb_encrypt;
};
#endif /* _POPT_COMMON_H */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 63ae51ecd4..49245eaa83 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -27,7 +27,7 @@
#define _SMB_H
/* logged when starting the various Samba daemons */
-#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2007"
+#define COPYRIGHT_STARTUP_MESSAGE "Copyright Andrew Tridgell and the Samba Team 1992-2008"
#if defined(LARGE_SMB_OFF_T)
@@ -80,7 +80,8 @@ enum smb_read_errors {
SMB_WRITE_ERROR, /* This error code can go into the client smb_rw_error. */
SMB_READ_BAD_SIG,
SMB_NO_MEMORY,
- SMB_DO_NOT_DO_TDIS /* cli_close_connection() check for this when smbfs wants to keep tree connected */
+ SMB_DO_NOT_DO_TDIS, /* cli_close_connection() check for this when smbfs wants to keep tree connected */
+ SMB_READ_BAD_DECRYPT
};
#define DIR_STRUCT_SIZE 43
@@ -657,6 +658,8 @@ typedef struct connection_struct {
bool used;
int num_files_open;
unsigned int num_smb_operations; /* Count of smb operations on this tree. */
+ int encrypt_level;
+ bool encrypted_tid;
/* Semantics requested by the client or forced by the server config. */
bool case_sensitive;
@@ -692,6 +695,8 @@ struct smb_request {
const uint8 *inbuf;
uint8 *outbuf;
size_t unread_bytes;
+ bool encrypted;
+ connection_struct *conn;
};
/* Defines for the sent_oplock_break field above. */
@@ -755,6 +760,7 @@ struct pending_message_list {
struct pending_message_list *next, *prev;
struct timeval request_time; /* When was this first issued? */
struct timeval end_time; /* When does this time out? */
+ bool encrypted;
DATA_BLOB buf;
DATA_BLOB private_data;
};
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 0dfb596994..3324f3fc02 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -160,7 +160,6 @@
#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__)
#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__)
-#define ERROR_OPEN(status) error_open(outbuf,status,__LINE__,__FILE__)
#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__)
#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__)
@@ -170,9 +169,6 @@
#define reply_botherror(req,status,eclass,ecode) reply_both_error(req,eclass,ecode,status,__LINE__,__FILE__)
#define reply_unixerror(req,defclass,deferror) reply_unix_error(req,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__)
-/* this is how errors are generated */
-#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__)
-
/* these are the datagram types */
#define DGRAM_DIRECT_UNIQUE 0x10
@@ -189,13 +185,16 @@
#define smb_offset(p,buf) (PTR_DIFF(p,buf+4) + chain_size)
#define smb_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|((PVAL(buf,1)&1)<<16))
-#define _smb_setlen(buf,len) do { buf[0] = 0; buf[1] = (len&0x10000)>>16; \
- buf[2] = (len&0xFF00)>>8; buf[3] = len&0xFF; } while (0)
+#define _smb_setlen(buf,len) do { buf[0] = 0; buf[1] = ((len)&0x10000)>>16; \
+ buf[2] = ((len)&0xFF00)>>8; buf[3] = (len)&0xFF; } while (0)
#define smb_len_large(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
#define _smb_setlen_large(buf,len) do { buf[0] = 0; buf[1] = ((len)&0xFF0000)>>16; \
buf[2] = ((len)&0xFF00)>>8; buf[3] = (len)&0xFF; } while (0)
+#define ENCRYPTION_REQUIRED(conn) ((conn) ? ((conn)->encrypt_level == Required) : false)
+#define IS_CONN_ENCRYPTED(conn) ((conn) ? (conn)->encrypted_tid : false)
+
/*******************************************************************
find the difference in milliseconds between two struct timeval
values
diff --git a/source3/include/trans2.h b/source3/include/trans2.h
index f7f3ef2149..3759d59681 100644
--- a/source3/include/trans2.h
+++ b/source3/include/trans2.h
@@ -530,7 +530,8 @@ findfirst/findnext is SMB_FIND_FILE_UNIX_INFO2.
#define CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP 0x20 /* We can cope with POSIX open/mkdir/unlink etc. */
#define CIFS_UNIX_LARGE_READ_CAP 0x40 /* We can cope with 24 bit reads in readX. */
#define CIFS_UNIX_LARGE_WRITE_CAP 0x80 /* We can cope with 24 bit writes in writeX. */
-
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x100 /* We can do SPNEGO negotiations for encryption. */
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x200 /* We *must* SPNEGO negotiations for encryption. */
#define SMB_QUERY_POSIX_FS_INFO 0x201
@@ -566,7 +567,6 @@ findfirst/findnext is SMB_FIND_FILE_UNIX_INFO2.
__u8 * psid_list may be empty
*/
-
/* ... more as we think of them :-). */
/* SMB POSIX ACL definitions. */
@@ -653,6 +653,29 @@ enum smb_whoami_flags {
DOM_SID[] - list of SIDs (may be empty)
*/
+/*
+ * The following trans2 is done between client and server
+ * as a FSINFO call to set up the encryption state for transport
+ * encryption.
+ * This is a subcommand of the TRANS2_QFSINFO.
+ *
+ * The request looks like :
+ *
+ * [data block] -> SPNEGO framed GSSAPI request.
+ *
+ * The reply looks like :
+ *
+ * [data block] -> SPNEGO framed GSSAPI reply - if error
+ * is NT_STATUS_OK then we're done, if it's
+ * NT_STATUS_MORE_PROCESSING_REQUIRED then the
+ * client needs to keep going. If it's an
+ * error it can be any NT_STATUS error.
+ *
+ */
+
+#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 /* QFSINFO */
+
+
/* The query/set info levels for POSIX ACLs. */
#define SMB_QUERY_POSIX_ACL 0x204
#define SMB_SET_POSIX_ACL 0x204
diff --git a/source3/lib/debug.c b/source3/lib/debug.c
index 87ec9ed8f5..9ea2dc151a 100644
--- a/source3/lib/debug.c
+++ b/source3/lib/debug.c
@@ -785,13 +785,13 @@ void check_log_size( void )
(void)x_vfprintf( dbf, format_str, ap );
va_end( ap );
errno = old_errno;
- return( 0 );
+ goto done;
}
/* prevent recursion by checking if reopen_logs() has temporaily
set the debugf string to NULL */
if( debugf == NULL)
- return( 0 );
+ goto done;
#ifdef WITH_SYSLOG
if( !lp_syslog_only() )
@@ -806,7 +806,7 @@ void check_log_size( void )
x_setbuf( dbf, NULL );
} else {
errno = old_errno;
- return(0);
+ goto done;
}
}
}
@@ -855,10 +855,11 @@ void check_log_size( void )
(void)x_fflush( dbf );
}
- errno = old_errno;
-
+ done:
TALLOC_FREE(tmp_debug_ctx);
+ errno = old_errno;
+
return( 0 );
}
diff --git a/source3/lib/dummysmbd.c b/source3/lib/dummysmbd.c
index e3b179b763..dbe886e3d1 100644
--- a/source3/lib/dummysmbd.c
+++ b/source3/lib/dummysmbd.c
@@ -51,4 +51,3 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
{
return NT_STATUS_OK;
}
-
diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c
index a50e5d01fa..663385cfe3 100644
--- a/source3/lib/gencache.c
+++ b/source3/lib/gencache.c
@@ -32,7 +32,6 @@
#define BLOB_TYPE_LEN 9
static TDB_CONTEXT *cache;
-static bool cache_readonly;
/**
* @file gencache.c
@@ -67,7 +66,6 @@ bool gencache_init(void)
if (!cache && (errno == EACCES)) {
cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDONLY, 0644);
if (cache) {
- cache_readonly = True;
DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname));
}
}
@@ -95,7 +93,6 @@ bool gencache_shutdown(void)
DEBUG(5, ("Closing cache file\n"));
ret = tdb_close(cache);
cache = NULL;
- cache_readonly = False;
return ret != -1;
}
@@ -123,10 +120,6 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout)
if (!gencache_init()) return False;
- if (cache_readonly) {
- return False;
- }
-
asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value);
if (!valstr)
return False;
@@ -161,10 +154,6 @@ bool gencache_del(const char *keystr)
if (!gencache_init()) return False;
- if (cache_readonly) {
- return False;
- }
-
DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr));
ret = tdb_delete_bystring(cache, keystr);
@@ -351,10 +340,6 @@ bool gencache_set_data_blob(const char *keystr, DATA_BLOB *blob, time_t timeout)
return False;
}
- if (cache_readonly) {
- return False;
- }
-
asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE);
if (!valstr) {
return False;
diff --git a/source3/lib/interfaces.c b/source3/lib/interfaces.c
index 722ab56abd..3797fc679d 100644
--- a/source3/lib/interfaces.c
+++ b/source3/lib/interfaces.c
@@ -84,6 +84,7 @@
#include <net/if.h>
#endif
+#define SOCKET_WRAPPER_NOT_REPLACE
#include "interfaces.h"
#include "lib/replace/replace.h"
diff --git a/source3/lib/memcache.c b/source3/lib/memcache.c
index 457586bd68..6dee61af50 100644
--- a/source3/lib/memcache.c
+++ b/source3/lib/memcache.c
@@ -46,6 +46,8 @@ static bool memcache_is_talloc(enum memcache_number n)
switch (n) {
case GETPWNAM_CACHE:
+ case PDB_GETPWSID_CACHE:
+ case SINGLETON_CACHE_TALLOC:
result = true;
break;
default:
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png b/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png
new file mode 100644
index 0000000000..f041198002
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/logo-small.png
Binary files differ
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
index beb12be8b1..d12e66bb26 100644
--- a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
+++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* Join Support (gtk + netapi)
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* 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
@@ -35,6 +35,7 @@
#define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
+#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
@@ -124,7 +125,6 @@ static void free_join_state(struct join_state *s)
SAFE_FREE(s->my_fqdn);
SAFE_FREE(s->my_dnsdomain);
SAFE_FREE(s->my_hostname);
-
}
static void do_cleanup(struct join_state *state)
@@ -225,7 +225,8 @@ static void callback_do_reboot(GtkWidget *widget,
gtk_widget_destroy(dialog);
#endif
- gtk_label_set_text(GTK_LABEL(state->label_reboot), "Changes will take effect after you restart this computer");
+ gtk_label_set_text(GTK_LABEL(state->label_reboot),
+ "Changes will take effect after you restart this computer");
debug("destroying do_change window\n");
gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
@@ -248,11 +249,14 @@ static void callback_do_reboot(GtkWidget *widget,
SAFE_FREE(buffer);
state->name_type_new = type;
#endif
- gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer), state->name_buffer_new);
- if (state->name_type_new == 3) {
- gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Domain:");
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
+ state->name_buffer_new);
+ if (state->name_type_new == NetSetupDomainName) {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Domain:");
} else {
- gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Workgroup:");
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
+ "Workgroup:");
}
}
}
@@ -365,7 +369,8 @@ static void callback_do_join(GtkWidget *widget,
uint32_t unjoin_flags = 0;
gboolean domain_join = FALSE;
gboolean try_unjoin = FALSE;
- const char *domain_or_workgroup = NULL;
+ const char *new_workgroup_type = NULL;
+ const char *initial_workgroup_type = NULL;
struct join_state *state = (struct join_state *)data;
@@ -376,14 +381,33 @@ static void callback_do_join(GtkWidget *widget,
gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
}
+ switch (state->name_type_initial) {
+ case NetSetupWorkgroupName:
+ initial_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ initial_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
+ switch (state->name_type_new) {
+ case NetSetupWorkgroupName:
+ new_workgroup_type = "workgroup";
+ break;
+ case NetSetupDomainName:
+ new_workgroup_type = "domain";
+ break;
+ default:
+ break;
+ }
+
if (state->name_type_new == NetSetupDomainName) {
domain_join = TRUE;
join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
- domain_or_workgroup = "domain";
- } else {
- domain_or_workgroup = "workgroup";
}
if ((state->name_type_initial == NetSetupDomainName) &&
@@ -394,7 +418,7 @@ static void callback_do_join(GtkWidget *widget,
}
debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
- domain_or_workgroup,
+ new_workgroup_type,
state->name_buffer_new,
join_flags);
if (domain_join) {
@@ -422,8 +446,8 @@ static void callback_do_join(GtkWidget *widget,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"The following error occured attempting to unjoin the %s: \"%s\": %s",
- domain_or_workgroup,
- state->name_buffer_new,
+ initial_workgroup_type,
+ state->name_buffer_initial,
err_str);
g_signal_connect_swapped(dialog, "response",
@@ -451,7 +475,7 @@ static void callback_do_join(GtkWidget *widget,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"The following error occured attempting to join the %s: \"%s\": %s",
- domain_or_workgroup,
+ new_workgroup_type,
state->name_buffer_new,
err_str);
@@ -465,7 +489,7 @@ static void callback_do_join(GtkWidget *widget,
}
debug("callback_do_join: Successfully joined %s\n",
- domain_or_workgroup);
+ new_workgroup_type);
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -473,7 +497,7 @@ static void callback_do_join(GtkWidget *widget,
GTK_BUTTONS_OK,
"Welcome to the %s %s.",
state->name_buffer_new,
- domain_or_workgroup);
+ new_workgroup_type);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -760,6 +784,8 @@ static void callback_do_change(GtkWidget *widget,
debug("callback_do_change called\n");
+#if 0
+ /* FIXME: add proper warnings for Samba as a DC */
if (state->server_role == 3) {
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
@@ -774,13 +800,14 @@ static void callback_do_change(GtkWidget *widget,
gtk_widget_show(dialog);
return;
}
+#endif
state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
- gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500); /* breite * höhe */
+ gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
g_signal_connect(G_OBJECT(window), "delete_event",
@@ -830,14 +857,17 @@ static void callback_do_change(GtkWidget *widget,
char *str = NULL;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
if (state->name_type_initial == NetSetupDomainName) {
- asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ asprintf(&str, "%s.%s", entry_text,
+ state->my_dnsdomain);
} else {
asprintf(&str, "%s.", entry_text);
}
- gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
+ str);
free(str);
gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
- gtk_box_pack_start(GTK_BOX(box1), state->label_full_computer_name, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(box1),
+ state->label_full_computer_name, TRUE, TRUE, 0);
gtk_widget_show(state->label_full_computer_name);
}
@@ -872,7 +902,8 @@ static void callback_do_change(GtkWidget *widget,
G_CALLBACK(callback_continue),
(gpointer)state);
if (state->name_type_initial == NetSetupDomainName) {
- gtk_entry_set_text(GTK_ENTRY(state->entry_domain), state->name_buffer_initial);
+ gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
+ state->name_buffer_initial);
gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
gtk_widget_set_sensitive(state->entry_domain, TRUE);
}
@@ -893,7 +924,8 @@ static void callback_do_change(GtkWidget *widget,
G_CALLBACK(callback_do_join_workgroup),
(gpointer)state);
{
- gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup), MAX_NETBIOS_NAME_LEN);
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
+ MAX_NETBIOS_NAME_LEN);
g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
G_CALLBACK(callback_enter_workgroup_and_unlock),
(gpointer)state);
@@ -902,7 +934,8 @@ static void callback_do_change(GtkWidget *widget,
(gpointer)state);
if (state->name_type_initial == NetSetupWorkgroupName) {
- gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup), state->name_buffer_initial);
+ gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
+ state->name_buffer_initial);
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
}
@@ -979,21 +1012,25 @@ static int draw_main_window(struct join_state *state)
icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
&error);
if (icon == NULL) {
- g_print("failed to load logo from %s : %s\n",
+ g_print("failed to load icon from %s : %s\n",
SAMBA_ICON_PATH, error->message);
}
#if 1
- image = gtk_image_new_from_file(SAMBA_IMAGE_PATH);
+ image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
#else
image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
#endif
+ if (image == NULL) {
+ g_print("failed to load logo from %s : %s\n",
+ SAMBA_IMAGE_PATH_SMALL, error->message);
+ }
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
state->window_main = window;
gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
- gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600); /* breite * höhe */
+ gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
@@ -1015,14 +1052,15 @@ static int draw_main_window(struct join_state *state)
{
/* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
- gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+/* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
gtk_widget_show(image);
/* Label */
label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
- gtk_widget_set_size_request(GTK_WIDGET(label), 500, 40);
+/* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
+ gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
diff --git a/source3/lib/netapi/examples/netdomjoin/netdomjoin.c b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
index e8b529927f..634d265597 100644
--- a/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
+++ b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* Join Support (cmdline + netapi)
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* 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
@@ -56,7 +56,10 @@ int main(int argc, char **argv)
if (argc < 2) {
printf("usage: netdomjoin\n");
- printf("\t[hostname=HOSTNAME] [domain=DOMAIN] <ou=OU> <usero=USERO> <passwordo=PASSWORDO> <userd=USERD> <passwordd=PASSWORDD>\n");
+ printf("\t[hostname] [domain=DOMAIN] <ou=OU> "
+ "<usero=USERO> <passwordo=PASSWORDO> "
+ "<userd=USERD> <passwordd=PASSWORDD> "
+ "<debug=DEBUGLEVEL>\n");
return 0;
}
@@ -87,6 +90,11 @@ int main(int argc, char **argv)
str = get_string_param(argv[i]);
libnetapi_set_password(ctx, str);
}
+ if (strncasecmp(argv[i], "debug", strlen("debug"))== 0) {
+ const char *str = NULL;
+ str = get_string_param(argv[i]);
+ libnetapi_set_debuglevel(ctx, str);
+ }
}
status = NetJoinDomain(server_name,
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index e3d5eada02..c7849c952f 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* NetApi Join Support
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* 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
@@ -54,8 +54,9 @@ static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx,
if (!NT_STATUS_IS_OK(status)) {
return ntstatus_to_werror(status);
}
- r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx,
+ info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
}
if (account_ou) {
@@ -69,8 +70,8 @@ static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx,
}
if (password) {
- r->in.password = talloc_strdup(mem_ctx, password);
- W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ r->in.admin_password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
}
r->in.join_flags = join_flags;
@@ -89,13 +90,11 @@ static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
- struct wkssvc_PasswordBuffer encrypted_password;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
NTSTATUS status;
WERROR werr;
unsigned int old_timeout = 0;
- ZERO_STRUCT(encrypted_password);
-
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
@@ -114,7 +113,7 @@ static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
if (!pipe_cli) {
werr = ntstatus_to_werror(status);
goto done;
- };
+ }
if (password) {
encode_wkssvc_join_password_buffer(ctx,
@@ -128,7 +127,7 @@ static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
server_name, domain_name,
account_ou, Account,
- &encrypted_password,
+ encrypted_password,
join_flags, &werr);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
@@ -224,8 +223,8 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
W_ERROR_NOT_OK_RETURN(werr);
if (server_name) {
- r->in.server_name = talloc_strdup(mem_ctx, server_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx, server_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
} else {
NTSTATUS status;
@@ -233,7 +232,6 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
DS_WRITABLE_REQUIRED |
- DS_IS_FLAT_NAME |
DS_RETURN_DNS_NAME;
if (lp_realm()) {
domain = lp_realm();
@@ -245,8 +243,9 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
if (!NT_STATUS_IS_OK(status)) {
return ntstatus_to_werror(status);
}
- r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
- W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ r->in.dc_name = talloc_strdup(mem_ctx,
+ info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
}
if (account) {
@@ -255,8 +254,8 @@ static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
}
if (password) {
- r->in.password = talloc_strdup(mem_ctx, password);
- W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ r->in.admin_password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
}
r->in.unjoin_flags = unjoin_flags;
@@ -276,13 +275,11 @@ static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
- struct wkssvc_PasswordBuffer encrypted_password;
+ struct wkssvc_PasswordBuffer *encrypted_password = NULL;
NTSTATUS status;
WERROR werr;
unsigned int old_timeout = 0;
- ZERO_STRUCT(encrypted_password);
-
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
@@ -301,7 +298,7 @@ static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
if (!pipe_cli) {
werr = ntstatus_to_werror(status);
goto done;
- };
+ }
if (password) {
encode_wkssvc_join_password_buffer(ctx,
@@ -315,7 +312,7 @@ static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
server_name,
account,
- &encrypted_password,
+ encrypted_password,
unjoin_flags,
&werr);
if (!NT_STATUS_IS_OK(status)) {
@@ -408,7 +405,7 @@ static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx,
if (!pipe_cli) {
werr = ntstatus_to_werror(status);
goto done;
- };
+ }
status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
server_name,
diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c
index 276a98c15e..0e356e0ee7 100644
--- a/source3/lib/netapi/serverinfo.c
+++ b/source3/lib/netapi/serverinfo.c
@@ -167,9 +167,8 @@ static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx,
return WERR_NOT_SUPPORTED;
}
- return libnet_smbconf_set_global_param(ctx,
- "server string",
- info1005->comment);
+ return libnet_conf_set_global_parameter("server string",
+ info1005->comment);
}
static WERROR NetServerSetInfoLocal(struct libnetapi_ctx *ctx,
diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c
index b3a84a6f7c..5a9d39d181 100644
--- a/source3/lib/popt_common.c
+++ b/source3/lib/popt_common.c
@@ -414,6 +414,7 @@ static void get_credentials_file(const char *file)
* -N,--no-pass
* -S,--signing
* -P --machine-pass
+ * -e --encrypt
*/
@@ -532,6 +533,10 @@ static void popt_common_credentials_callback(poptContext con,
case 'N':
set_cmdline_auth_info_password("");
break;
+ case 'e':
+ set_cmdline_auth_info_smb_encrypt();
+ break;
+
}
}
@@ -543,5 +548,6 @@ struct poptOption popt_common_credentials[] = {
{ "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" },
{ "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" },
{"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" },
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
POPT_TABLEEND
};
diff --git a/source3/lib/replace/system/network.h b/source3/lib/replace/system/network.h
index 9087c02da1..b6ae3c7c6f 100644
--- a/source3/lib/replace/system/network.h
+++ b/source3/lib/replace/system/network.h
@@ -233,6 +233,10 @@ typedef unsigned short int sa_family_t;
#endif
#endif
+#ifdef HAVE_AIX_SOCKADDR_STORAGE
+#define ss_family __ss_family
+#endif
+
#ifndef HAVE_STRUCT_ADDRINFO
#define HAVE_STRUCT_ADDRINFO
struct addrinfo {
diff --git a/source3/lib/secace.c b/source3/lib/secace.c
index 90ecc342cd..8760a6109a 100644
--- a/source3/lib/secace.c
+++ b/source3/lib/secace.c
@@ -59,7 +59,7 @@ void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, enum security_ace_type type,
{
t->type = type;
t->flags = flag;
- t->size = sid_size(sid) + 8;
+ t->size = ndr_size_dom_sid(sid, 0) + 8;
t->access_mask = mask;
ZERO_STRUCTP(&t->trustee);
@@ -86,7 +86,7 @@ NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsign
(*pp_new)[i].type = SEC_ACE_TYPE_ACCESS_ALLOWED;
(*pp_new)[i].flags = 0;
- (*pp_new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid);
+ (*pp_new)[i].size = SEC_ACE_HEADER_SIZE + ndr_size_dom_sid(sid, 0);
(*pp_new)[i].access_mask = mask;
sid_copy(&(*pp_new)[i].trustee, sid);
return NT_STATUS_OK;
diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c
index 123c3bcc9b..44ae23271e 100644
--- a/source3/lib/secdesc.c
+++ b/source3/lib/secdesc.c
@@ -32,35 +32,6 @@ const struct generic_mapping file_generic_mapping = {
};
/*******************************************************************
- Works out the linearization size of a SEC_DESC.
-********************************************************************/
-
-size_t sec_desc_size(SEC_DESC *psd)
-{
- size_t offset;
-
- if (!psd) return 0;
-
- offset = SEC_DESC_HEADER_SIZE;
-
- /* don't align */
-
- if (psd->owner_sid != NULL)
- offset += sid_size(psd->owner_sid);
-
- if (psd->group_sid != NULL)
- offset += sid_size(psd->group_sid);
-
- if (psd->sacl != NULL)
- offset += psd->sacl->size;
-
- if (psd->dacl != NULL)
- offset += psd->dacl->size;
-
- return offset;
-}
-
-/*******************************************************************
Compares two SEC_DESC structures
********************************************************************/
@@ -235,11 +206,11 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx,
}
if (dst->owner_sid != NULL) {
- offset += sid_size(dst->owner_sid);
+ offset += ndr_size_dom_sid(dst->owner_sid, 0);
}
if (dst->group_sid != NULL) {
- offset += sid_size(dst->group_sid);
+ offset += ndr_size_dom_sid(dst->group_sid, 0);
}
*sd_size = (size_t)offset;
@@ -274,25 +245,21 @@ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
struct security_descriptor *secdesc,
uint8 **data, size_t *len)
{
- prs_struct ps;
-
- if (!prs_init(&ps, sec_desc_size(secdesc), mem_ctx, MARSHALL)) {
- return NT_STATUS_NO_MEMORY;
- }
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
- if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
- prs_mem_free(&ps);
- return NT_STATUS_INVALID_PARAMETER;
- }
+ ndr_err = ndr_push_struct_blob(
+ &blob, mem_ctx, secdesc,
+ (ndr_push_flags_fn_t)ndr_push_security_descriptor);
- if (!(*data = (uint8 *)talloc_memdup(mem_ctx, ps.data_p,
- prs_offset(&ps)))) {
- prs_mem_free(&ps);
- return NT_STATUS_NO_MEMORY;
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
+ ndr_errstr(ndr_err)));
+ return ndr_map_error2ntstatus(ndr_err);;
}
- *len = prs_offset(&ps);
- prs_mem_free(&ps);
+ *data = blob.data;
+ *len = blob.length;
return NT_STATUS_OK;
}
@@ -302,25 +269,33 @@ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
struct security_descriptor **psecdesc)
{
- prs_struct ps;
- struct security_descriptor *secdesc = NULL;
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
+ struct security_descriptor *result;
- if (!(secdesc = TALLOC_ZERO_P(mem_ctx, struct security_descriptor))) {
- return NT_STATUS_NO_MEMORY;
+ if ((data == NULL) || (len == 0)) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- if (!prs_init(&ps, 0, secdesc, UNMARSHALL)) {
+ result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
+ if (result == NULL) {
return NT_STATUS_NO_MEMORY;
}
- prs_give_memory(&ps, (char *)data, len, False);
+ blob = data_blob_const(data, len);
- if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
- return NT_STATUS_INVALID_PARAMETER;
+ ndr_err = ndr_pull_struct_blob(
+ &blob, result, result,
+ (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
+ ndr_errstr(ndr_err)));
+ TALLOC_FREE(result);
+ return ndr_map_error2ntstatus(ndr_err);;
}
- prs_mem_free(&ps);
- *psecdesc = secdesc;
+ *psecdesc = result;
return NT_STATUS_OK;
}
diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c
index 0027a8813a..ba025dacc1 100644
--- a/source3/lib/sharesec.c
+++ b/source3/lib/sharesec.c
@@ -144,7 +144,7 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, const char *servicename,
}
if (psd)
- *psize = sec_desc_size(psd);
+ *psize = ndr_size_security_descriptor(psd, 0);
return psd;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 11c14ea538..c69a1450a0 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -289,7 +289,8 @@ static struct user_auth_info cmdline_auth_info = {
NULL, /* password */
false, /* got_pass */
false, /* use_kerberos */
- Undefined /* signing state */
+ Undefined, /* signing state */
+ false /* smb_encrypt */
};
const char *get_cmdline_auth_info_username(void)
@@ -362,11 +363,22 @@ void set_cmdline_auth_info_use_krb5_ticket(void)
cmdline_auth_info.got_pass = true;
}
+/* This should only be used by lib/popt_common.c JRA */
+void set_cmdline_auth_info_smb_encrypt(void)
+{
+ cmdline_auth_info.smb_encrypt = true;
+}
+
bool get_cmdline_auth_info_got_pass(void)
{
return cmdline_auth_info.got_pass;
}
+bool get_cmdline_auth_info_smb_encrypt(void)
+{
+ return cmdline_auth_info.smb_encrypt;
+}
+
bool get_cmdline_auth_info_copy(struct user_auth_info *info)
{
*info = cmdline_auth_info;
@@ -605,32 +617,30 @@ void show_msg(char *buf)
}
/*******************************************************************
- Set the length and marker of an smb packet.
+ Set the length and marker of an encrypted smb packet.
********************************************************************/
-void smb_setlen(char *buf,int len)
+void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
{
_smb_setlen(buf,len);
SCVAL(buf,4,0xFF);
- SCVAL(buf,5,'S');
- SCVAL(buf,6,'M');
- SCVAL(buf,7,'B');
+ SCVAL(buf,5,'E');
+ SSVAL(buf,6,enc_ctx_num);
}
/*******************************************************************
- Setup the word count and byte count for a smb message.
+ Set the length and marker of an smb packet.
********************************************************************/
-int set_message(char *buf,int num_words,int num_bytes,bool zero)
+void smb_setlen(char *buf,int len)
{
- if (zero && (num_words || num_bytes)) {
- memset(buf + smb_size,'\0',num_words*2 + num_bytes);
- }
- SCVAL(buf,smb_wct,num_words);
- SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
- smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
- return (smb_size + num_words*2 + num_bytes);
+ _smb_setlen(buf,len);
+
+ SCVAL(buf,4,0xFF);
+ SCVAL(buf,5,'S');
+ SCVAL(buf,6,'M');
+ SCVAL(buf,7,'B');
}
/*******************************************************************
@@ -641,21 +651,11 @@ int set_message_bcc(char *buf,int num_bytes)
{
int num_words = CVAL(buf,smb_wct);
SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
- smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+ _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
return (smb_size + num_words*2 + num_bytes);
}
/*******************************************************************
- Setup only the byte count for a smb message, using the end of the
- message as a marker.
-********************************************************************/
-
-int set_message_end(void *outbuf,void *end_ptr)
-{
- return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
-}
-
-/*******************************************************************
Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
Return the bytes added
********************************************************************/
diff --git a/source3/lib/util_reg_smbconf.c b/source3/lib/util_reg_smbconf.c
index 154c67ab8f..fa58f28d03 100644
--- a/source3/lib/util_reg_smbconf.c
+++ b/source3/lib/util_reg_smbconf.c
@@ -57,7 +57,7 @@ done:
*/
bool registry_init_regdb(void)
{
- bool ret = False;
+ bool ret = false;
int saved_errno = 0;
static REGISTRY_HOOK smbconf_reg_hook = {KEY_SMBCONF, &smbconf_reg_ops};
@@ -78,7 +78,7 @@ bool registry_init_regdb(void)
goto done;
}
- ret = True;
+ ret = true;
done:
return ret;
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index 52f65aa77d..222b32ed3a 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -382,7 +382,7 @@ bool sid_linearize(char *outbuf, size_t len, const DOM_SID *sid)
{
size_t i;
- if (len < sid_size(sid))
+ if (len < ndr_size_dom_sid(sid, 0))
return False;
SCVAL(outbuf,0,sid->sid_rev_num);
@@ -495,18 +495,6 @@ bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
}
/*****************************************************************
- Calculates size of a sid.
-*****************************************************************/
-
-size_t sid_size(const DOM_SID *sid)
-{
- if (sid == NULL)
- return 0;
-
- return sid->num_auths * sizeof(uint32) + 8;
-}
-
-/*****************************************************************
Returns true if SID is internal (and non-mappable).
*****************************************************************/
@@ -535,7 +523,7 @@ bool non_mappable_sid(DOM_SID *sid)
char *sid_binstring(const DOM_SID *sid)
{
char *buf, *s;
- int len = sid_size(sid);
+ int len = ndr_size_dom_sid(sid, 0);
buf = (char *)SMB_MALLOC(len);
if (!buf)
return NULL;
@@ -553,7 +541,7 @@ char *sid_binstring(const DOM_SID *sid)
char *sid_binstring_hex(const DOM_SID *sid)
{
char *buf, *s;
- int len = sid_size(sid);
+ int len = ndr_size_dom_sid(sid, 0);
buf = (char *)SMB_MALLOC(len);
if (!buf)
return NULL;
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 8f1bd9e686..945506ea77 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -1277,56 +1277,6 @@ ssize_t receive_smb_raw(int fd,
}
/****************************************************************************
- Wrapper for receive_smb_raw().
- Checks the MAC on signed packets.
-****************************************************************************/
-
-bool receive_smb(int fd, char *buffer, unsigned int timeout, enum smb_read_errors *pre)
-{
- if (receive_smb_raw(fd, buffer, timeout, 0, pre) < 0) {
- return false;
- }
-
- /* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(buffer, true)) {
- DEBUG(0, ("receive_smb: SMB Signature verification "
- "failed on incoming packet!\n"));
- cond_set_smb_read_error(pre,SMB_READ_BAD_SIG);
- return false;
- }
-
- return true;
-}
-
-/****************************************************************************
- Send an smb to a fd.
-****************************************************************************/
-
-bool send_smb(int fd, char *buffer)
-{
- size_t len;
- size_t nwritten=0;
- ssize_t ret;
-
- /* Sign the outgoing packet if required. */
- srv_calculate_sign_mac(buffer);
-
- len = smb_len(buffer) + 4;
-
- while (nwritten < len) {
- ret = write_data(fd,buffer+nwritten,len - nwritten);
- if (ret <= 0) {
- DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
- (int)len,(int)ret, strerror(errno) ));
- return false;
- }
- nwritten += ret;
- }
-
- return true;
-}
-
-/****************************************************************************
Open a socket of the specified type, port, and address for incoming data.
****************************************************************************/
@@ -1800,18 +1750,66 @@ static bool matchname(const char *remotehost,
return false;
}
-static struct {
- struct sockaddr_storage ss;
- char *name;
-} nc;
+/*******************************************************************
+ Deal with the singleton cache.
+******************************************************************/
+
+struct name_addr_pair {
+ struct sockaddr_storage ss;
+ const char *name;
+};
+
+/*******************************************************************
+ Lookup a name/addr pair. Returns memory allocated from memcache.
+******************************************************************/
+
+static bool lookup_nc(struct name_addr_pair *nc)
+{
+ DATA_BLOB tmp;
+
+ ZERO_STRUCTP(nc);
+
+ if (!memcache_lookup(
+ NULL, SINGLETON_CACHE,
+ data_blob_string_const("get_peer_name"),
+ &tmp)) {
+ return false;
+ }
+
+ memcpy(&nc->ss, tmp.data, sizeof(nc->ss));
+ nc->name = (const char *)tmp.data + sizeof(nc->ss);
+ return true;
+}
+
+/*******************************************************************
+ Save a name/addr pair.
+******************************************************************/
+
+static void store_nc(const struct name_addr_pair *nc)
+{
+ DATA_BLOB tmp;
+ size_t namelen = strlen(nc->name);
+
+ tmp = data_blob(NULL, sizeof(nc->ss) + namelen + 1);
+ if (!tmp.data) {
+ return;
+ }
+ memcpy(tmp.data, &nc->ss, sizeof(nc->ss));
+ memcpy(tmp.data+sizeof(nc->ss), nc->name, namelen+1);
+
+ memcache_add(NULL, SINGLETON_CACHE,
+ data_blob_string_const("get_peer_name"),
+ tmp);
+ data_blob_free(&tmp);
+}
/*******************************************************************
Return the DNS name of the remote end of a socket.
******************************************************************/
-const char *get_peer_name(int fd,
- bool force_lookup)
+const char *get_peer_name(int fd, bool force_lookup)
{
+ struct name_addr_pair nc;
char addr_buf[INET6_ADDRSTRLEN];
struct sockaddr_storage ss;
socklen_t length = sizeof(ss);
@@ -1826,13 +1824,15 @@ const char *get_peer_name(int fd,
possible */
if (!lp_hostname_lookups() && (force_lookup == false)) {
length = sizeof(nc.ss);
- p = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf),
+ nc.name = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf),
&nc.ss, &length);
- SAFE_FREE(nc.name);
- nc.name = SMB_STRDUP(p);
+ store_nc(&nc);
+ lookup_nc(&nc);
return nc.name ? nc.name : "UNKNOWN";
}
+ lookup_nc(&nc);
+
memset(&ss, '\0', sizeof(ss));
p = get_peer_addr_internal(fd, addr_buf, sizeof(addr_buf), &ss, &length);
@@ -1841,9 +1841,7 @@ const char *get_peer_name(int fd,
return nc.name ? nc.name : "UNKNOWN";
}
- /* Not the same. Reset the cache. */
- zero_addr(&nc.ss);
- SAFE_FREE(nc.name);
+ /* Not the same. We need to lookup. */
if (fd == -1) {
return "UNKNOWN";
}
@@ -1880,7 +1878,11 @@ const char *get_peer_name(int fd,
strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
}
- nc.name = SMB_STRDUP(name_buf);
+ nc.name = name_buf;
+ nc.ss = ss;
+
+ store_nc(&nc);
+ lookup_nc(&nc);
return nc.name ? nc.name : "UNKNOWN";
}
@@ -2002,50 +2004,68 @@ out_umask:
const char *get_mydnsfullname(void)
{
- static char *dnshostname_cache;
-
- if (dnshostname_cache == NULL || !*dnshostname_cache) {
- struct addrinfo *res = NULL;
- char my_hostname[HOST_NAME_MAX];
- bool ret;
+ struct addrinfo *res = NULL;
+ char my_hostname[HOST_NAME_MAX];
+ bool ret;
+ DATA_BLOB tmp;
- /* get my host name */
- if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
- DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
- return NULL;
- }
+ if (memcache_lookup(NULL, SINGLETON_CACHE,
+ data_blob_string_const("get_mydnsfullname"),
+ &tmp)) {
+ SMB_ASSERT(tmp.length > 0);
+ return (const char *)tmp.data;
+ }
- /* Ensure null termination. */
- my_hostname[sizeof(my_hostname)-1] = '\0';
+ /* get my host name */
+ if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
+ DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
+ return NULL;
+ }
- ret = interpret_string_addr_internal(&res,
- my_hostname,
- AI_ADDRCONFIG|AI_CANONNAME);
+ /* Ensure null termination. */
+ my_hostname[sizeof(my_hostname)-1] = '\0';
- if (!ret || res == NULL) {
- DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
- "name %s [%s]\n",
+ ret = interpret_string_addr_internal(&res,
my_hostname,
- gai_strerror(ret) ));
- return NULL;
- }
+ AI_ADDRCONFIG|AI_CANONNAME);
- /*
- * Make sure that getaddrinfo() returns the "correct" host name.
- */
+ if (!ret || res == NULL) {
+ DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
+ "name %s [%s]\n",
+ my_hostname,
+ gai_strerror(ret) ));
+ return NULL;
+ }
- if (res->ai_canonname == NULL) {
- DEBUG(3,("get_mydnsfullname: failed to get "
- "canonical name for %s\n",
- my_hostname));
- freeaddrinfo(res);
- return NULL;
- }
+ /*
+ * Make sure that getaddrinfo() returns the "correct" host name.
+ */
- dnshostname_cache = SMB_STRDUP(res->ai_canonname);
+ if (res->ai_canonname == NULL) {
+ DEBUG(3,("get_mydnsfullname: failed to get "
+ "canonical name for %s\n",
+ my_hostname));
freeaddrinfo(res);
+ return NULL;
+ }
+
+ /* This copies the data, so we must do a lookup
+ * afterwards to find the value to return.
+ */
+
+ memcache_add(NULL, SINGLETON_CACHE,
+ data_blob_string_const("get_mydnsfullname"),
+ data_blob_string_const(res->ai_canonname));
+
+ freeaddrinfo(res);
+
+ if (!memcache_lookup(NULL, SINGLETON_CACHE,
+ data_blob_string_const("get_mydnsfullname"),
+ &tmp)) {
+ return NULL;
}
- return dnshostname_cache;
+
+ return (const char *)tmp.data;
}
/************************************************************
diff --git a/source3/lib/winbind_util.c b/source3/lib/winbind_util.c
index f51a0171a2..3cf068a6e0 100644
--- a/source3/lib/winbind_util.c
+++ b/source3/lib/winbind_util.c
@@ -35,12 +35,12 @@ bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
result = wbcLookupName(dom_name, name, &dom_sid, &type);
if (result != WBC_ERR_SUCCESS)
- return False;
+ return false;
memcpy(sid, &dom_sid, sizeof(DOM_SID));
*name_type = (enum lsa_SidType)type;
- return True;
+ return true;
}
/* Call winbindd to convert sid to name */
@@ -59,7 +59,7 @@ bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
result = wbcLookupSid(&dom_sid, &domain_name, &account_name, &type);
if (result != WBC_ERR_SUCCESS)
- return False;
+ return false;
/* Copy out result */
@@ -74,16 +74,16 @@ bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
sid_string_dbg(sid), domain_name, account_name));
- SAFE_FREE(domain_name);
- SAFE_FREE(account_name);
+ wbcFreeMemory(domain_name);
+ wbcFreeMemory(account_name);
if ((domain && !*domain) || (name && !*name)) {
DEBUG(0,("winbind_lookup_sid: talloc() failed!\n"));
- return False;
+ return false;
}
- return True;
+ return true;
}
/* Ping winbindd to see it is alive */
@@ -192,8 +192,9 @@ bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
ret = wbcLookupRids(&dom_sid, num_rids, rids,
&dom_name, &namelist, &name_types);
- if (ret != WBC_ERR_SUCCESS)
- return False;
+ if (ret != WBC_ERR_SUCCESS) {
+ return false;
+ }
*domain_name = talloc_strdup(mem_ctx, dom_name);
*names = TALLOC_ARRAY(mem_ctx, const char*, num_rids);
@@ -202,13 +203,13 @@ bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
for(i=0; i<num_rids; i++) {
(*names)[i] = talloc_strdup(names, namelist[i]);
(*types)[i] = (enum lsa_SidType)name_types[i];
-
- free(CONST_DISCARD(char*, namelist[i]));
}
- free(namelist);
- free(name_types);
+
+ wbcFreeMemory(CONST_DISCARD(char*, dom_name));
+ wbcFreeMemory(namelist);
+ wbcFreeMemory(name_types);
- return True;
+ return true;
}
/* Ask Winbind to allocate a new uid for us */
@@ -238,7 +239,7 @@ bool winbind_allocate_gid(gid_t *gid)
bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
enum lsa_SidType *name_type)
{
- return False;
+ return false;
}
/* Call winbindd to convert sid to name */
@@ -247,42 +248,42 @@ bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **domain, const char **name,
enum lsa_SidType *name_type)
{
- return False;
+ return false;
}
/* Ping winbindd to see it is alive */
bool winbind_ping(void)
{
- return False;
+ return false;
}
/* Call winbindd to convert SID to uid */
bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
{
- return False;
+ return false;
}
/* Call winbindd to convert uid to sid */
bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
{
- return False;
+ return false;
}
/* Call winbindd to convert SID to gid */
bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
{
- return False;
+ return false;
}
/* Call winbindd to convert gid to sid */
bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
{
- return False;
+ return false;
}
/* Check for a trusted domain */
@@ -300,21 +301,21 @@ bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
const char **domain_name,
const char ***names, enum lsa_SidType **types)
{
- return False;
+ return false;
}
/* Ask Winbind to allocate a new uid for us */
bool winbind_allocate_uid(uid_t *uid)
{
- return False;
+ return false;
}
/* Ask Winbind to allocate a new gid for us */
bool winbind_allocate_gid(gid_t *gid)
{
- return False;
+ return false;
}
#endif /* WITH_WINBIND */
diff --git a/source3/libads/ads_status.c b/source3/libads/ads_status.c
index ecef9d224b..29148e8543 100644
--- a/source3/libads/ads_status.c
+++ b/source3/libads/ads_status.c
@@ -141,3 +141,12 @@ const char *ads_errstr(ADS_STATUS status)
}
}
+#ifdef HAVE_GSSAPI
+NTSTATUS gss_err_to_ntstatus(uint32 maj, uint32 min)
+{
+ ADS_STATUS adss = ADS_ERROR_GSS(maj, min);
+ DEBUG(10,("gss_err_to_ntstatus: Error %s\n",
+ ads_errstr(adss) ));
+ return ads_ntstatus(adss);
+}
+#endif
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 348ccacaee..975e926864 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -56,6 +56,10 @@ static void gotalarm_sig(void)
{
LDAP *ldp = NULL;
+
+ DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout "
+ "%u seconds\n", server, port, to));
+
/* Setup timeout */
gotalarm = 0;
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
@@ -65,8 +69,10 @@ static void gotalarm_sig(void)
ldp = ldap_open(server, port);
if (ldp == NULL) {
- DEBUG(2,("Could not open LDAP connection to %s:%d: %s\n",
+ DEBUG(2,("Could not open connection to LDAP server %s:%d: %s\n",
server, port, strerror(errno)));
+ } else {
+ DEBUG(10, ("Connected to LDAP server '%s:%d'\n", server, port));
}
/* Teardown timeout. */
@@ -400,7 +406,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
got_connection:
print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
- DEBUG(3,("Connected to LDAP server %s\n", addr));
+ DEBUG(3,("Successfully contacted LDAP server %s\n", addr));
if (!ads->auth.user_name) {
/* Must use the userPrincipalName value here or sAMAccountName
@@ -442,11 +448,12 @@ got_connection:
/* Otherwise setup the TCP LDAP session */
- if ( (ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
- LDAP_PORT, lp_ldap_timeout())) == NULL )
- {
+ ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
+ LDAP_PORT, lp_ldap_timeout());
+ if (ads->ldap.ld == NULL) {
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
}
+ DEBUG(3,("Connected to LDAP server %s\n", ads->config.ldap_server_name));
/* cache the successful connection for workgroup and realm */
if (ads_closest_dc(ads)) {
@@ -2384,20 +2391,22 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
LDAPMessage *msg, const char *field, SEC_DESC **sd)
{
struct berval **values;
- bool ret = False;
+ bool ret = true;
values = ldap_get_values_len(ads->ldap.ld, msg, field);
- if (!values) return False;
+ if (!values) return false;
if (values[0]) {
- prs_struct ps;
- prs_init(&ps, values[0]->bv_len, mem_ctx, UNMARSHALL);
- prs_copy_data_in(&ps, values[0]->bv_val, values[0]->bv_len);
- prs_set_offset(&ps,0);
-
- ret = sec_io_desc("sd", sd, &ps, 1);
- prs_mem_free(&ps);
+ NTSTATUS status;
+ status = unmarshall_sec_desc(mem_ctx,
+ (uint8 *)values[0]->bv_val,
+ values[0]->bv_len, sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("unmarshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
+ ret = false;
+ }
}
ldap_value_free_len(values);
@@ -2789,6 +2798,66 @@ ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char ***suffix
}
/**
+ * get the joinable ous for a domain
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param ous Pointer to an array of ous
+ * @param num_ous Pointer to the number of ous
+ * @return status of search
+ **/
+ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ char ***ous,
+ size_t *num_ous)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
+ const char *attrs[] = { "dn", NULL };
+ int count = 0;
+
+ status = ads_search(ads, &res,
+ "(|(objectClass=domain)(objectclass=organizationalUnit))",
+ attrs);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ count = ads_count_replies(ads, res);
+ if (count < 1) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ for (msg = ads_first_entry(ads, res); msg;
+ msg = ads_next_entry(ads, msg)) {
+
+ char *dn = NULL;
+
+ dn = ads_get_dn(ads, msg);
+ if (!dn) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (!add_string_to_array(mem_ctx, dn,
+ (const char ***)ous,
+ (int *)num_ous)) {
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ads_memfree(ads, dn);
+ }
+
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+
+/**
* pull a DOM_SID from an extended dn string
* @param mem_ctx TALLOC_CTX
* @param extended_dn string
diff --git a/source3/libnet/libnet_conf.c b/source3/libnet/libnet_conf.c
index 69a105f8f5..c8e55a70b2 100644
--- a/source3/libnet/libnet_conf.c
+++ b/source3/libnet/libnet_conf.c
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* libnet smbconf registry Support
- * Copyright (C) Michael Adam 2007
+ * Copyright (C) Michael Adam 2007-2008
* Copyright (C) Guenther Deschner 2007
*
* This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,12 @@
*/
#include "includes.h"
+#include "libnet/libnet.h"
+
+/*
+ * yuck - static variable to keep track of the registry initialization.
+ */
+static bool registry_initialized = false;
/**********************************************************************
*
@@ -27,116 +33,164 @@
**********************************************************************/
-/*
- * Open a subkey of KEY_SMBCONF (i.e a service)
- * - variant without error output (q = quiet)-
+/**
+ * add a string to a talloced array of strings.
*/
-static WERROR libnet_smbconf_open_path_q(TALLOC_CTX *ctx,
- const char *subkeyname,
- uint32 desired_access,
- struct registry_key **key)
+static WERROR libnet_conf_add_string_to_array(TALLOC_CTX *mem_ctx,
+ char ***array,
+ uint32_t count,
+ const char *string)
+{
+ char **new_array = NULL;
+
+ if ((array == NULL) || (string == NULL)) {
+ return WERR_INVALID_PARAM;
+ }
+
+ new_array = TALLOC_REALLOC_ARRAY(mem_ctx, *array, char *, count + 1);
+ if (new_array == NULL) {
+ return WERR_NOMEM;
+ }
+
+ new_array[count] = talloc_strdup(new_array, string);
+
+ *array = new_array;
+
+ return WERR_OK;
+}
+
+static WERROR libnet_conf_reg_initialize(void)
{
WERROR werr = WERR_OK;
- char *path = NULL;
- NT_USER_TOKEN *token;
- if (!(token = registry_create_admin_token(ctx))) {
- DEBUG(1, ("Error creating admin token\n"));
+ if (registry_initialized) {
goto done;
}
- if (subkeyname == NULL) {
- path = talloc_strdup(ctx, KEY_SMBCONF);
- } else {
- path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, subkeyname);
+ if (!registry_init_regdb()) {
+ werr = WERR_REG_IO_FAILURE;
+ goto done;
}
- werr = reg_open_path(ctx, path, desired_access,
- token, key);
+ registry_initialized = true;
done:
- TALLOC_FREE(path);
return werr;
}
-/*
- * check if a subkey of KEY_SMBCONF of a given name exists
+/**
+ * Open a registry key specified by "path"
*/
-bool libnet_smbconf_key_exists(TALLOC_CTX *ctx, const char *subkeyname)
+static WERROR libnet_conf_reg_open_path(TALLOC_CTX *mem_ctx,
+ const char *path,
+ uint32 desired_access,
+ struct registry_key **key)
{
- bool ret = False;
WERROR werr = WERR_OK;
- TALLOC_CTX *mem_ctx;
- struct registry_key *key;
+ NT_USER_TOKEN *token;
+ TALLOC_CTX *tmp_ctx = NULL;
- if (!(mem_ctx = talloc_new(ctx))) {
- d_fprintf(stderr, "ERROR: Out of memory...!\n");
+ if (path == NULL) {
+ DEBUG(1, ("Error: NULL path string given\n"));
+ werr = WERR_INVALID_PARAM;
goto done;
}
- werr = libnet_smbconf_open_path_q(mem_ctx, subkeyname, REG_KEY_READ, &key);
- if (W_ERROR_IS_OK(werr)) {
- ret = True;
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
}
-done:
- TALLOC_FREE(mem_ctx);
- return ret;
-}
+ werr = libnet_conf_reg_initialize();
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, ("Error initializing registry: %s\n",
+ dos_errstr(werr)));
+ goto done;
+ }
-static bool libnet_smbconf_value_exists(TALLOC_CTX *ctx,
- struct registry_key *key,
- const char *param)
-{
- bool ret = False;
- WERROR werr = WERR_OK;
- struct registry_value *value = NULL;
+ token = registry_create_admin_token(tmp_ctx);
+ if (token == NULL) {
+ DEBUG(1, ("Error creating admin token\n"));
+ /* what is the appropriate error code here? */
+ werr = WERR_CAN_NOT_COMPLETE;
+ goto done;
+ }
- werr = reg_queryvalue(ctx, key, param, &value);
- if (W_ERROR_IS_OK(werr)) {
- ret = True;
+ werr = reg_open_path(mem_ctx, path, desired_access, token, key);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(1, ("Error opening registry path '%s': %s\n",
+ path, dos_errstr(werr)));
}
- TALLOC_FREE(value);
- return ret;
+done:
+ TALLOC_FREE(tmp_ctx);
+ return werr;
}
-/*
+/**
* Open a subkey of KEY_SMBCONF (i.e a service)
- * - variant with error output -
*/
-WERROR libnet_smbconf_open_path(TALLOC_CTX *ctx, const char *subkeyname,
- uint32 desired_access,
- struct registry_key **key)
+static WERROR libnet_conf_reg_open_service_key(TALLOC_CTX *ctx,
+ const char *servicename,
+ uint32 desired_access,
+ struct registry_key **key)
{
WERROR werr = WERR_OK;
+ char *path = NULL;
- werr = libnet_smbconf_open_path_q(ctx, subkeyname, desired_access, key);
- if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr, "Error opening registry path '%s\\%s': %s\n",
- KEY_SMBCONF,
- (subkeyname == NULL) ? "" : subkeyname,
- dos_errstr(werr));
+ if (servicename == NULL) {
+ DEBUG(3, ("Error: NULL servicename given.\n"));
+ werr = WERR_INVALID_PARAM;
+ goto done;
}
+ path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, servicename);
+
+ werr = libnet_conf_reg_open_path(ctx, path, desired_access, key);
+
+done:
+ TALLOC_FREE(path);
return werr;
}
-/*
+/**
* open the base key KEY_SMBCONF
*/
-WERROR libnet_smbconf_open_basepath(TALLOC_CTX *ctx, uint32 desired_access,
- struct registry_key **key)
+static WERROR libnet_conf_reg_open_base_key(TALLOC_CTX *ctx,
+ uint32 desired_access,
+ struct registry_key **key)
{
- return libnet_smbconf_open_path(ctx, NULL, desired_access, key);
+ return libnet_conf_reg_open_path(ctx, KEY_SMBCONF, desired_access, key);
}
-/*
+/**
+ * check if a value exists in a given registry key
+ */
+static bool libnet_conf_value_exists(struct registry_key *key,
+ const char *param)
+{
+ bool ret = false;
+ WERROR werr = WERR_OK;
+ TALLOC_CTX *ctx = talloc_stackframe();
+ struct registry_value *value = NULL;
+
+ werr = reg_queryvalue(ctx, key, param, &value);
+ if (W_ERROR_IS_OK(werr)) {
+ ret = true;
+ }
+
+ TALLOC_FREE(ctx);
+ return ret;
+}
+
+/**
* create a subkey of KEY_SMBCONF
*/
-WERROR libnet_smbconf_reg_createkey_internal(TALLOC_CTX *ctx,
- const char * subkeyname,
- struct registry_key **newkey)
+static WERROR libnet_conf_reg_create_service_key(TALLOC_CTX *ctx,
+ const char * subkeyname,
+ struct registry_key **newkey)
{
WERROR werr = WERR_OK;
struct registry_key *create_parent = NULL;
@@ -151,7 +205,8 @@ WERROR libnet_smbconf_reg_createkey_internal(TALLOC_CTX *ctx,
goto done;
}
- werr = libnet_smbconf_open_basepath(create_ctx, REG_KEY_WRITE, &create_parent);
+ werr = libnet_conf_reg_open_base_key(create_ctx, REG_KEY_WRITE,
+ &create_parent);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
@@ -159,12 +214,12 @@ WERROR libnet_smbconf_reg_createkey_internal(TALLOC_CTX *ctx,
werr = reg_createkey(ctx, create_parent, subkeyname,
REG_KEY_WRITE, newkey, &action);
if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
- d_fprintf(stderr, "Key '%s' already exists.\n", subkeyname);
+ DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
werr = WERR_ALREADY_EXISTS;
}
if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr, "Error creating key %s: %s\n",
- subkeyname, dos_errstr(werr));
+ DEBUG(5, ("Error creating key %s: %s\n",
+ subkeyname, dos_errstr(werr)));
}
done:
@@ -172,12 +227,12 @@ done:
return werr;
}
-/*
+/**
* add a value to a key.
*/
-WERROR libnet_smbconf_reg_setvalue_internal(struct registry_key *key,
- const char *valname,
- const char *valstr)
+static WERROR libnet_conf_reg_set_value(struct registry_key *key,
+ const char *valname,
+ const char *valstr)
{
struct registry_value val;
WERROR werr = WERR_OK;
@@ -190,11 +245,11 @@ WERROR libnet_smbconf_reg_setvalue_internal(struct registry_key *key,
&canon_valstr))
{
if (canon_valname == NULL) {
- d_fprintf(stderr, "invalid parameter '%s' given\n",
- valname);
+ DEBUG(5, ("invalid parameter '%s' given\n",
+ valname));
} else {
- d_fprintf(stderr, "invalid value '%s' given for "
- "parameter '%s'\n", valstr, valname);
+ DEBUG(5, ("invalid value '%s' given for "
+ "parameter '%s'\n", valstr, valname));
}
werr = WERR_INVALID_PARAM;
goto done;
@@ -207,16 +262,16 @@ WERROR libnet_smbconf_reg_setvalue_internal(struct registry_key *key,
val.v.sz.len = strlen(canon_valstr) + 1;
if (registry_smbconf_valname_forbidden(canon_valname)) {
- d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
- canon_valname);
+ DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
+ canon_valname));
werr = WERR_INVALID_PARAM;
goto done;
}
subkeyname = strrchr_m(key->key->name, '\\');
if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
- d_fprintf(stderr, "Invalid registry key '%s' given as "
- "smbconf section.\n", key->key->name);
+ DEBUG(5, ("Invalid registry key '%s' given as "
+ "smbconf section.\n", key->key->name));
werr = WERR_INVALID_PARAM;
goto done;
}
@@ -224,22 +279,140 @@ WERROR libnet_smbconf_reg_setvalue_internal(struct registry_key *key,
if (!strequal(subkeyname, GLOBAL_NAME) &&
lp_parameter_is_global(valname))
{
- d_fprintf(stderr, "Global paramter '%s' not allowed in "
+ DEBUG(5, ("Global paramter '%s' not allowed in "
"service definition ('%s').\n", canon_valname,
- subkeyname);
+ subkeyname));
werr = WERR_INVALID_PARAM;
goto done;
}
werr = reg_setvalue(key, canon_valname, &val);
if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr,
- "Error adding value '%s' to "
+ DEBUG(5, ("Error adding value '%s' to "
"key '%s': %s\n",
- canon_valname, key->key->name, dos_errstr(werr));
+ canon_valname, key->key->name, dos_errstr(werr)));
+ }
+
+done:
+ return werr;
+}
+
+/**
+ * format a registry_value into a string.
+ *
+ * This is intended to be used for smbconf registry values,
+ * which are ar stored as REG_SZ values, so the incomplete
+ * handling should be ok.
+ */
+static char *libnet_conf_format_registry_value(TALLOC_CTX *mem_ctx,
+ struct registry_value *value)
+{
+ char *result = NULL;
+
+ /* alternatively, create a new talloc context? */
+ if (mem_ctx == NULL) {
+ return result;
+ }
+
+ switch (value->type) {
+ case REG_DWORD:
+ result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
+ break;
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
+ break;
+ case REG_MULTI_SZ: {
+ uint32 j;
+ for (j = 0; j < value->v.multi_sz.num_strings; j++) {
+ result = talloc_asprintf(mem_ctx, "\"%s\" ",
+ value->v.multi_sz.strings[j]);
+ }
+ break;
+ }
+ case REG_BINARY:
+ result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
+ (int)value->v.binary.length);
+ break;
+ default:
+ result = talloc_asprintf(mem_ctx, "<unprintable>");
+ break;
+ }
+ return result;
+}
+
+/**
+ * Get the values of a key as a list of value names
+ * and a list of value strings (ordered)
+ */
+static WERROR libnet_conf_reg_get_values(TALLOC_CTX *mem_ctx,
+ struct registry_key *key,
+ uint32_t *num_values,
+ char ***value_names,
+ char ***value_strings)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ WERROR werr = WERR_OK;
+ uint32_t count;
+ struct registry_value *valvalue = NULL;
+ char *valname = NULL;
+ char **tmp_valnames = NULL;
+ char **tmp_valstrings = NULL;
+
+ if ((num_values == NULL) || (value_names == NULL) ||
+ (value_strings == NULL))
+ {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (count = 0;
+ W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
+ &valvalue));
+ count++)
+ {
+ char *valstring;
+
+ werr = libnet_conf_add_string_to_array(tmp_ctx,
+ &tmp_valnames,
+ count, valname);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ valstring = libnet_conf_format_registry_value(tmp_ctx,
+ valvalue);
+ werr = libnet_conf_add_string_to_array(tmp_ctx,
+ &tmp_valstrings,
+ count,
+ valstring);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+ if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
+ goto done;
+ }
+
+ werr = WERR_OK;
+
+ *num_values = count;
+ if (count > 0) {
+ *value_names = talloc_move(mem_ctx, &tmp_valnames);
+ *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
+ } else {
+ *value_names = NULL;
+ *value_strings = NULL;
}
done:
+ TALLOC_FREE(tmp_ctx);
return werr;
}
@@ -249,63 +422,412 @@ done:
*
**********************************************************************/
-WERROR libnet_smbconf_setparm(TALLOC_CTX *mem_ctx,
- const char *service,
- const char *param,
- const char *valstr)
+/**
+ * Drop the whole configuration (restarting empty).
+ */
+WERROR libnet_conf_drop(void)
{
- WERROR werr;
+ char *path, *p;
+ WERROR werr = WERR_OK;
+ struct registry_key *parent_key = NULL;
+ struct registry_key *new_key = NULL;
+ TALLOC_CTX* mem_ctx = talloc_stackframe();
+ enum winreg_CreateAction action;
+
+ path = talloc_strdup(mem_ctx, KEY_SMBCONF);
+ if (path == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+ p = strrchr(path, '\\');
+ *p = '\0';
+ werr = libnet_conf_reg_open_path(mem_ctx, path, REG_KEY_WRITE,
+ &parent_key);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
+ &new_key, &action);
+
+done:
+ TALLOC_FREE(mem_ctx);
+ return werr;
+}
+
+/**
+ * Get the whole configuration as lists of strings with counts:
+ *
+ * num_shares : number of shares
+ * share_names : list of length num_shares of share names
+ * num_params : list of length num_shares of parameter counts for each share
+ * param_names : list of lists of parameter names for each share
+ * param_values : list of lists of parameter values for each share
+ */
+WERROR libnet_conf_get_config(TALLOC_CTX *mem_ctx, uint32_t *num_shares,
+ char ***share_names, uint32_t **num_params,
+ char ****param_names, char ****param_values)
+{
+ WERROR werr = WERR_OK;
+ TALLOC_CTX *tmp_ctx = NULL;
+ uint32_t tmp_num_shares;
+ char **tmp_share_names;
+ uint32_t *tmp_num_params;
+ char ***tmp_param_names;
+ char ***tmp_param_values;
+ uint32_t count;
+
+ if ((num_shares == NULL) || (share_names == NULL) ||
+ (num_params == NULL) || (param_names == NULL) ||
+ (param_values == NULL))
+ {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ werr = libnet_conf_get_share_names(tmp_ctx, &tmp_num_shares,
+ &tmp_share_names);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ tmp_num_params = TALLOC_ARRAY(tmp_ctx, uint32_t, tmp_num_shares);
+ tmp_param_names = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
+ tmp_param_values = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
+
+ if ((tmp_num_params == NULL) || (tmp_param_names == NULL) ||
+ (tmp_param_values == NULL))
+ {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ for (count = 0; count < tmp_num_shares; count++) {
+ werr = libnet_conf_get_share(mem_ctx, tmp_share_names[count],
+ &tmp_num_params[count],
+ &tmp_param_names[count],
+ &tmp_param_values[count]);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ }
+
+ werr = WERR_OK;
+
+ *num_shares = tmp_num_shares;
+ if (tmp_num_shares > 0) {
+ *share_names = talloc_move(mem_ctx, &tmp_share_names);
+ *num_params = talloc_move(mem_ctx, &tmp_num_params);
+ *param_names = talloc_move(mem_ctx, &tmp_param_names);
+ *param_values = talloc_move(mem_ctx, &tmp_param_values);
+ } else {
+ *share_names = NULL;
+ *num_params = NULL;
+ *param_names = NULL;
+ *param_values = NULL;
+ }
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return werr;
+}
+
+
+/**
+ * get the list of share names defined in the configuration.
+ */
+WERROR libnet_conf_get_share_names(TALLOC_CTX *mem_ctx, uint32_t *num_shares,
+ char ***share_names)
+{
+ uint32_t count;
+ uint32_t added_count = 0;
+ TALLOC_CTX *tmp_ctx = NULL;
+ WERROR werr = WERR_OK;
struct registry_key *key = NULL;
+ char *subkey_name = NULL;
+ char **tmp_share_names = NULL;
+
+ if ((num_shares == NULL) || (share_names == NULL)) {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ werr = WERR_NOMEM;
+ goto done;
+ }
+
+ /* make sure "global" is always listed first */
+ if (libnet_conf_share_exists(GLOBAL_NAME)) {
+ werr = libnet_conf_add_string_to_array(tmp_ctx,
+ &tmp_share_names,
+ 0, GLOBAL_NAME);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ added_count++;
+ }
+
+ werr = libnet_conf_reg_open_base_key(tmp_ctx, SEC_RIGHTS_ENUM_SUBKEYS,
+ &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ for (count = 0;
+ W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
+ &subkey_name, NULL));
+ count++)
+ {
+ if (strequal(subkey_name, GLOBAL_NAME)) {
+ continue;
+ }
+
+ werr = libnet_conf_add_string_to_array(tmp_ctx,
+ &tmp_share_names,
+ added_count,
+ subkey_name);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+ added_count++;
+ }
+ if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
+ goto done;
+ }
+ werr = WERR_OK;
- if (!libnet_smbconf_key_exists(mem_ctx, service)) {
- werr = libnet_smbconf_reg_createkey_internal(mem_ctx, service,
- &key);
+ *num_shares = added_count;
+ if (added_count > 0) {
+ *share_names = talloc_move(mem_ctx, &tmp_share_names);
} else {
- werr = libnet_smbconf_open_path(mem_ctx, service, REG_KEY_WRITE,
+ *share_names = NULL;
+ }
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return werr;
+}
+
+/**
+ * check if a share/service of a given name exists
+ */
+bool libnet_conf_share_exists(const char *servicename)
+{
+ bool ret = false;
+ WERROR werr = WERR_OK;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+ struct registry_key *key = NULL;
+
+ werr = libnet_conf_reg_open_service_key(mem_ctx, servicename,
+ REG_KEY_READ, &key);
+ if (W_ERROR_IS_OK(werr)) {
+ ret = true;
+ }
+
+ TALLOC_FREE(mem_ctx);
+ return ret;
+}
+
+/**
+ * Add a service if it does not already exist.
+ */
+WERROR libnet_conf_create_share(const char *servicename)
+{
+ WERROR werr;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+ struct registry_key *key = NULL;
+
+ if (libnet_conf_share_exists(servicename)) {
+ werr = WERR_ALREADY_EXISTS;
+ goto done;
+ }
+
+ werr = libnet_conf_reg_create_service_key(mem_ctx, servicename, &key);
+
+done:
+ TALLOC_FREE(mem_ctx);
+ return werr;
+}
+
+/**
+ * get a definition of a share (service) from configuration.
+ */
+WERROR libnet_conf_get_share(TALLOC_CTX *mem_ctx, const char *servicename,
+ uint32_t *num_params, char ***param_names,
+ char ***param_values)
+{
+ WERROR werr = WERR_OK;
+ struct registry_key *key = NULL;
+
+ werr = libnet_conf_reg_open_service_key(mem_ctx, servicename,
+ REG_KEY_READ, &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnet_conf_reg_get_values(mem_ctx, key, num_params,
+ param_names, param_values);
+
+done:
+ TALLOC_FREE(key);
+ return werr;
+}
+
+/**
+ * delete a service from configuration
+ */
+WERROR libnet_conf_delete_share(const char *servicename)
+{
+ WERROR werr = WERR_OK;
+ struct registry_key *key = NULL;
+ TALLOC_CTX *ctx = talloc_stackframe();
+
+ werr = libnet_conf_reg_open_base_key(ctx, REG_KEY_WRITE, &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = reg_deletekey_recursive(key, key, servicename);
+
+done:
+ TALLOC_FREE(ctx);
+ return werr;
+}
+
+/**
+ * set a configuration parameter to the value provided.
+ */
+WERROR libnet_conf_set_parameter(const char *service,
+ const char *param,
+ const char *valstr)
+{
+ WERROR werr;
+ struct registry_key *key = NULL;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+ if (!libnet_conf_share_exists(service)) {
+ werr = WERR_NO_SUCH_SERVICE;
+ goto done;
+ }
+
+ werr = libnet_conf_reg_open_service_key(mem_ctx, service, REG_KEY_WRITE,
+ &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnet_conf_reg_set_value(key, param, valstr);
+
+done:
+ TALLOC_FREE(mem_ctx);
+ return werr;
+}
+
+/**
+ * get the value of a configuration parameter as a string
+ */
+WERROR libnet_conf_get_parameter(TALLOC_CTX *mem_ctx,
+ const char *service,
+ const char *param,
+ char **valstr)
+{
+ WERROR werr = WERR_OK;
+ struct registry_key *key = NULL;
+ struct registry_value *value = NULL;
+
+ if (valstr == NULL) {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ if (!libnet_conf_share_exists(service)) {
+ werr = WERR_NO_SUCH_SERVICE;
+ goto done;
+ }
+
+ werr = libnet_conf_reg_open_service_key(mem_ctx, service, REG_KEY_READ,
&key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
}
- W_ERROR_NOT_OK_RETURN(werr);
- werr = libnet_smbconf_reg_setvalue_internal(key, param, valstr);
+ if (!libnet_conf_value_exists(key, param)) {
+ werr = WERR_INVALID_PARAM;
+ goto done;
+ }
+ werr = reg_queryvalue(mem_ctx, key, param, &value);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ *valstr = libnet_conf_format_registry_value(mem_ctx, value);
+
+ if (*valstr == NULL) {
+ werr = WERR_NOMEM;
+ }
+
+done:
+ TALLOC_FREE(key);
+ TALLOC_FREE(value);
return werr;
}
-WERROR libnet_smbconf_delparm(TALLOC_CTX *mem_ctx,
- const char *service,
- const char *param)
+/**
+ * delete a parameter from configuration
+ */
+WERROR libnet_conf_delete_parameter(const char *service, const char *param)
{
struct registry_key *key = NULL;
WERROR werr = WERR_OK;
+ TALLOC_CTX *mem_ctx = talloc_stackframe();
- if (!libnet_smbconf_key_exists(mem_ctx, service)) {
+ if (!libnet_conf_share_exists(service)) {
return WERR_NO_SUCH_SERVICE;
}
- werr = libnet_smbconf_open_path(mem_ctx, service, REG_KEY_READ, &key);
- W_ERROR_NOT_OK_RETURN(werr);
+ werr = libnet_conf_reg_open_service_key(mem_ctx, service, REG_KEY_ALL,
+ &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
- if (!libnet_smbconf_value_exists(mem_ctx, key, param)) {
- return WERR_INVALID_PARAM;
+ if (!libnet_conf_value_exists(key, param)) {
+ werr = WERR_INVALID_PARAM;
+ goto done;
}
werr = reg_deletevalue(key, param);
- W_ERROR_NOT_OK_RETURN(werr);
- return WERR_OK;
+done:
+ TALLOC_FREE(mem_ctx);
+ return werr;
}
/**********************************************************************
*
- * Convenience functions, that are also exportet.
+ * Convenience functions that are also exported.
*
**********************************************************************/
-WERROR libnet_smbconf_set_global_param(TALLOC_CTX *mem_ctx,
- const char *param,
- const char *val)
+WERROR libnet_conf_set_global_parameter(const char *param, const char *val)
{
- return libnet_smbconf_setparm(mem_ctx, GLOBAL_NAME, param, val);
+ return libnet_conf_set_parameter(GLOBAL_NAME, param, val);
}
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 68244e5156..95b643ffa6 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -2,7 +2,7 @@
* Unix SMB/CIFS implementation.
* libnet Join Support
* Copyright (C) Gerald (Jerry) Carter 2006
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* 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
@@ -22,12 +22,30 @@
#include "libnet/libnet_join.h"
#include "libnet/libnet_proto.h"
-static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
- struct libnet_JoinCtx *r)
+static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
+{
+ if (!secrets_store_domain_sid(r->out.netbios_domain_name,
+ r->out.domain_sid))
+ {
+ return false;
+ }
+
+ if (!secrets_store_machine_password(r->in.machine_password,
+ r->out.netbios_domain_name,
+ SEC_CHAN_WKSTA))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r)
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
- const char *password = NULL;
POLICY_HND sam_pol, domain_pol, user_pol, lsa_pol;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
char *acct_name;
@@ -46,17 +64,20 @@ static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
DATA_BLOB digested_session_key;
uchar md4_trust_password[16];
- password = talloc_strdup(mem_ctx,
- generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH));
- NT_STATUS_HAVE_NO_MEMORY(password);
+ if (!r->in.machine_password) {
+ r->in.machine_password = talloc_strdup(mem_ctx, generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH));
+ NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
+ }
- status = cli_full_connection(&cli, NULL, r->in.server_name,
+ status = cli_full_connection(&cli, NULL,
+ r->in.dc_name,
NULL, 0,
"IPC$", "IPC",
r->in.admin_account,
- NULL, //r->in.domain_name,
- r->in.password,
- 0, Undefined, NULL);
+ NULL,
+ r->in.admin_password,
+ 0,
+ Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
goto done;
@@ -152,15 +173,16 @@ static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
goto done;
}
- E_md4hash(r->in.password, md4_trust_password);
- encode_pw_buffer(pwbuf, r->in.password, STR_UNICODE);
+ E_md4hash(r->in.machine_password, md4_trust_password);
+ encode_pw_buffer(pwbuf, r->in.machine_password, STR_UNICODE);
generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
MD5Init(&md5ctx);
MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
- MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
+ MD5Update(&md5ctx, cli->user_session_key.data,
+ cli->user_session_key.length);
MD5Final(digested_session_key.data, &md5ctx);
SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
@@ -194,21 +216,6 @@ static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
cli_rpc_pipe_close(pipe_hnd);
- if (!secrets_store_domain_sid(r->out.netbios_domain_name,
- r->out.domain_sid))
- {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
- if (!secrets_store_machine_password(password,
- r->out.netbios_domain_name,
- SEC_CHAN_WKSTA))
- {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
status = NT_STATUS_OK;
done:
if (cli) {
@@ -218,8 +225,22 @@ static NTSTATUS do_DomainJoin(TALLOC_CTX *mem_ctx,
return status;
}
-static NTSTATUS do_DomainUnjoin(TALLOC_CTX *mem_ctx,
- struct libnet_UnjoinCtx *r)
+static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX *mem_ctx,
+ struct libnet_UnjoinCtx *r)
+{
+ if (!secrets_delete_machine_password_ex(lp_workgroup())) {
+ return false;
+ }
+
+ if (!secrets_delete_domain_sid(lp_workgroup())) {
+ return false;
+ }
+
+ return true;
+}
+
+static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
+ struct libnet_UnjoinCtx *r)
{
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
@@ -233,12 +254,13 @@ static NTSTATUS do_DomainUnjoin(TALLOC_CTX *mem_ctx,
SAM_USERINFO_CTR ctr, *qctr = NULL;
SAM_USER_INFO_16 p16;
- status = cli_full_connection(&cli, NULL, r->in.server_name,
+ status = cli_full_connection(&cli, NULL,
+ r->in.dc_name,
NULL, 0,
"IPC$", "IPC",
r->in.admin_account,
- NULL, //r->in.domain_name,
- r->in.password,
+ NULL,
+ r->in.admin_password,
0, Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
@@ -308,21 +330,12 @@ static NTSTATUS do_DomainUnjoin(TALLOC_CTX *mem_ctx,
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
- if (!secrets_delete_machine_password_ex(lp_workgroup())) {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
- if (!secrets_delete_domain_sid(lp_workgroup())) {
- status = NT_STATUS_INTERNAL_DB_ERROR;
- goto done;
- }
-
done:
- rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
- rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
-
- cli_rpc_pipe_close(pipe_hnd);
+ if (pipe_hnd) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+ rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
+ cli_rpc_pipe_close(pipe_hnd);
+ }
if (cli) {
cli_shutdown(cli);
@@ -331,20 +344,18 @@ done:
return status;
}
-static WERROR do_join_modify_vals_config(TALLOC_CTX *mem_ctx,
- struct libnet_JoinCtx *r)
+static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
{
WERROR werr;
bool is_ad = false;
if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) {
- werr = libnet_smbconf_set_global_param(mem_ctx, "security",
- "user");
+ werr = libnet_conf_set_global_parameter("security", "user");
W_ERROR_NOT_OK_RETURN(werr);
- werr = libnet_smbconf_set_global_param(mem_ctx, "workgroup",
- r->in.domain_name);
+ werr = libnet_conf_set_global_parameter("workgroup",
+ r->in.domain_name);
return werr;
}
@@ -352,19 +363,18 @@ static WERROR do_join_modify_vals_config(TALLOC_CTX *mem_ctx,
is_ad = true;
}
- werr = libnet_smbconf_set_global_param(mem_ctx, "security", "domain");
+ werr = libnet_conf_set_global_parameter("security", "domain");
W_ERROR_NOT_OK_RETURN(werr);
- werr = libnet_smbconf_set_global_param(mem_ctx, "workgroup",
- r->out.netbios_domain_name);
+ werr = libnet_conf_set_global_parameter("workgroup",
+ r->out.netbios_domain_name);
W_ERROR_NOT_OK_RETURN(werr);
if (is_ad) {
- werr = libnet_smbconf_set_global_param(mem_ctx, "security",
- "ads");
+ werr = libnet_conf_set_global_parameter("security", "ads");
W_ERROR_NOT_OK_RETURN(werr);
- werr = libnet_smbconf_set_global_param(mem_ctx, "realm",
+ werr = libnet_conf_set_global_parameter("realm",
r->out.dns_domain_name);
W_ERROR_NOT_OK_RETURN(werr);
}
@@ -372,26 +382,23 @@ static WERROR do_join_modify_vals_config(TALLOC_CTX *mem_ctx,
return werr;
}
-static WERROR do_unjoin_modify_vals_config(TALLOC_CTX *mem_ctx,
- struct libnet_UnjoinCtx *r)
+static WERROR do_unjoin_modify_vals_config(struct libnet_UnjoinCtx *r)
{
WERROR werr = WERR_OK;
if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- werr = libnet_smbconf_set_global_param(mem_ctx, "security",
- "user");
+ werr = libnet_conf_set_global_parameter("security", "user");
W_ERROR_NOT_OK_RETURN(werr);
}
- werr = libnet_smbconf_delparm(mem_ctx, "GLOBAL", "realm");
+ werr = libnet_conf_delete_parameter(GLOBAL_NAME, "realm");
return werr;
}
-static WERROR do_JoinConfig(TALLOC_CTX *mem_ctx,
- struct libnet_JoinCtx *r)
+static WERROR do_JoinConfig(struct libnet_JoinCtx *r)
{
WERROR werr;
@@ -403,7 +410,7 @@ static WERROR do_JoinConfig(TALLOC_CTX *mem_ctx,
return WERR_OK;
}
- werr = do_join_modify_vals_config(mem_ctx, r);
+ werr = do_join_modify_vals_config(r);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
@@ -414,8 +421,7 @@ static WERROR do_JoinConfig(TALLOC_CTX *mem_ctx,
return werr;
}
-static WERROR do_UnjoinConfig(TALLOC_CTX *mem_ctx,
- struct libnet_UnjoinCtx *r)
+static WERROR do_UnjoinConfig(struct libnet_UnjoinCtx *r)
{
WERROR werr;
@@ -427,7 +433,7 @@ static WERROR do_UnjoinConfig(TALLOC_CTX *mem_ctx,
return WERR_OK;
}
- werr = do_unjoin_modify_vals_config(mem_ctx, r);
+ werr = do_unjoin_modify_vals_config(r);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
@@ -488,16 +494,20 @@ WERROR libnet_Join(TALLOC_CTX *mem_ctx,
if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- status = do_DomainJoin(mem_ctx, r);
+ status = libnet_join_joindomain_rpc(mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
return WERR_SETUP_ALREADY_JOINED;
}
return ntstatus_to_werror(status);
}
+
+ if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) {
+ return WERR_SETUP_NOT_JOINED;
+ }
}
- werr = do_JoinConfig(mem_ctx, r);
+ werr = do_JoinConfig(r);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
@@ -517,16 +527,18 @@ WERROR libnet_Unjoin(TALLOC_CTX *mem_ctx,
if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
- status = do_DomainUnjoin(mem_ctx, r);
+ status = libnet_join_unjoindomain_rpc(mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
return WERR_SETUP_NOT_JOINED;
}
return ntstatus_to_werror(status);
}
+
+ libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
}
- werr = do_UnjoinConfig(mem_ctx, r);
+ werr = do_UnjoinConfig(r);
if (!W_ERROR_IS_OK(werr)) {
return werr;
}
diff --git a/source3/libnet/libnet_join.h b/source3/libnet/libnet_join.h
index 46ab27e8b0..9e7b8a9813 100644
--- a/source3/libnet/libnet_join.h
+++ b/source3/libnet/libnet_join.h
@@ -1,7 +1,7 @@
/*
* Unix SMB/CIFS implementation.
* libnet Join Support
- * Copyright (C) Guenther Deschner 2007
+ * Copyright (C) Guenther Deschner 2007-2008
*
* 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
@@ -22,11 +22,13 @@
struct libnet_JoinCtx {
struct {
- const char *server_name;
+ const char *dc_name;
+ const char *machine_name;
const char *domain_name;
const char *account_ou;
const char *admin_account;
- const char *password;
+ const char *admin_password;
+ const char *machine_password;
uint32_t join_flags;
const char *os_version;
const char *os_string;
@@ -47,10 +49,10 @@ struct libnet_JoinCtx {
struct libnet_UnjoinCtx {
struct {
- const char *server_name;
+ const char *dc_name;
const char *domain_name;
const char *admin_account;
- const char *password;
+ const char *admin_password;
uint32_t unjoin_flags;
bool modify_config;
struct dom_sid *domain_sid;
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 33110c803f..4560521d4a 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -98,7 +98,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,10, 0, True);
+ cli_set_message(cli->outbuf,10, 0, True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -168,7 +168,7 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
uint32 capabilities = cli_session_setup_capabilities(cli);
memset(cli->outbuf, '\0', smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -228,7 +228,7 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
memset(cli->outbuf, '\0', smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -377,7 +377,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,13,0,True);
+ cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -457,7 +457,7 @@ static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
/* send a session setup command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,12,0,True);
+ cli_set_message(cli->outbuf,12,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -1028,7 +1028,7 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
bool cli_ulogoff(struct cli_state *cli)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBulogoffX);
cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
@@ -1106,7 +1106,7 @@ bool cli_send_tconX(struct cli_state *cli,
slprintf(fullshare, sizeof(fullshare)-1,
"\\\\%s\\%s", cli->desthost, share);
- set_message(cli->outbuf,4, 0, True);
+ cli_set_message(cli->outbuf,4, 0, True);
SCVAL(cli->outbuf,smb_com,SMBtconX);
cli_setup_packet(cli);
@@ -1157,7 +1157,7 @@ bool cli_send_tconX(struct cli_state *cli,
bool cli_tdis(struct cli_state *cli)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBtdis);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1189,7 +1189,7 @@ void cli_negprot_send(struct cli_state *cli)
memset(cli->outbuf,'\0',smb_size);
/* setup the protocol strings */
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
p = smb_buf(cli->outbuf);
for (numprots=0;
@@ -1229,7 +1229,7 @@ bool cli_negprot(struct cli_state *cli)
numprots++)
plength += strlen(prots[numprots].name)+2;
- set_message(cli->outbuf,0,plength,True);
+ cli_set_message(cli->outbuf,0,plength,True);
p = smb_buf(cli->outbuf);
for (numprots=0;
@@ -1806,7 +1806,7 @@ NTSTATUS cli_raw_tcon(struct cli_state *cli,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 0, 0, True);
+ cli_set_message(cli->outbuf, 0, 0, True);
SCVAL(cli->outbuf,smb_com,SMBtcon);
cli_setup_packet(cli);
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index e0c40b52ed..77419b4a1a 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -58,6 +58,52 @@ static struct sockaddr_storage dest_ss;
static struct client_connection *connections;
+static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
+ struct cli_state *cli,
+ const char *sharename,
+ char **pp_newserver,
+ char **pp_newshare,
+ bool force_encrypt,
+ const char *username,
+ const char *password,
+ const char *domain);
+
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+NTSTATUS cli_cm_force_encryption(struct cli_state *c,
+ const char *username,
+ const char *password,
+ const char *domain,
+ const char *sharename)
+{
+ NTSTATUS status = cli_force_encryption(c,
+ username,
+ password,
+ domain);
+
+ if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNKNOWN_REVISION)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ } else if (NT_STATUS_EQUAL(status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", sharename);
+ } else if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(status));
+ }
+
+ return status;
+}
+
/********************************************************************
Return a connection to a server.
********************************************************************/
@@ -65,7 +111,8 @@ static struct client_connection *connections;
static struct cli_state *do_connect(TALLOC_CTX *ctx,
const char *server,
const char *share,
- bool show_sessetup)
+ bool show_sessetup,
+ bool force_encrypt)
{
struct cli_state *c = NULL;
struct nmb_name called, calling;
@@ -197,9 +244,14 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
if ((c->capabilities & CAP_DFS) &&
cli_check_msdfs_proxy(ctx, c, sharename,
- &newserver, &newshare)) {
+ &newserver, &newshare,
+ force_encrypt,
+ username,
+ password,
+ lp_workgroup())) {
cli_shutdown(c);
- return do_connect(ctx, newserver, newshare, false);
+ return do_connect(ctx, newserver,
+ newshare, false, force_encrypt);
}
/* must be a normal share */
@@ -211,6 +263,18 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
return NULL;
}
+ if (force_encrypt) {
+ status = cli_cm_force_encryption(c,
+ username,
+ password,
+ lp_workgroup(),
+ sharename);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_shutdown(c);
+ return NULL;
+ }
+ }
+
DEBUG(4,(" tconx ok\n"));
return c;
}
@@ -269,7 +333,8 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
struct cli_state *referring_cli,
const char *server,
const char *share,
- bool show_hdr)
+ bool show_hdr,
+ bool force_encrypt)
{
struct client_connection *node;
@@ -279,7 +344,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
return NULL;
}
- node->cli = do_connect(ctx, server, share, show_hdr);
+ node->cli = do_connect(ctx, server, share, show_hdr, force_encrypt);
if ( !node->cli ) {
TALLOC_FREE( node );
@@ -331,7 +396,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
struct cli_state *referring_cli,
const char *server,
const char *share,
- bool show_hdr)
+ bool show_hdr,
+ bool force_encrypt)
{
struct cli_state *c;
@@ -339,7 +405,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
c = cli_cm_find(server, share);
if (!c) {
- c = cli_cm_connect(ctx, referring_cli, server, share, show_hdr);
+ c = cli_cm_connect(ctx, referring_cli,
+ server, share, show_hdr, force_encrypt);
}
return c;
@@ -776,7 +843,9 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/* Check for the referral. */
if (!(cli_ipc = cli_cm_open(ctx, rootcli,
- rootcli->desthost, "IPC$", false))) {
+ rootcli->desthost,
+ "IPC$", false,
+ (rootcli->trans_enc_state != NULL)))) {
return false;
}
@@ -818,7 +887,10 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/* Open the connection to the target server & share */
if ((*targetcli = cli_cm_open(ctx, rootcli,
- server, share, false)) == NULL) {
+ server,
+ share,
+ false,
+ (rootcli->trans_enc_state != NULL))) == NULL) {
d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
server, share );
return false;
@@ -905,11 +977,15 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/********************************************************************
********************************************************************/
-bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
+static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli,
const char *sharename,
char **pp_newserver,
- char **pp_newshare )
+ char **pp_newshare,
+ bool force_encrypt,
+ const char *username,
+ const char *password,
+ const char *domain)
{
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs = 0;
@@ -944,6 +1020,17 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
return false;
}
+ if (force_encrypt) {
+ NTSTATUS status = cli_cm_force_encryption(cli,
+ username,
+ password,
+ lp_workgroup(),
+ "IPC$");
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ }
+
res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
if (!cli_tdis(cli)) {
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 76630bd504..66c6ee1022 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -81,7 +81,7 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx,
return False;
}
- set_message(ptr,17,strlen(mailslot) + 1 + len,True);
+ cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
SCVAL(ptr,smb_com,SMBtrans);
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 0544b3d879..ecef293d07 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -20,6 +20,21 @@
#include "includes.h"
+/*******************************************************************
+ Setup the word count and byte count for a client smb message.
+********************************************************************/
+
+int cli_set_message(char *buf,int num_words,int num_bytes,bool zero)
+{
+ if (zero && (num_words || num_bytes)) {
+ memset(buf + smb_size,'\0',num_words*2 + num_bytes);
+ }
+ SCVAL(buf,smb_wct,num_words);
+ SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+ return (smb_size + num_words*2 + num_bytes);
+}
+
/****************************************************************************
Change the timeout (in milliseconds).
****************************************************************************/
@@ -71,6 +86,17 @@ static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen)
break;
}
}
+
+ if (cli_encryption_on(cli)) {
+ NTSTATUS status = cli_decrypt_message(cli);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("SMB decryption failed on incoming packet! Error %s\n",
+ nt_errstr(status)));
+ cli->smb_rw_error = SMB_READ_BAD_DECRYPT;
+ return -1;
+ }
+ }
+
show_msg(cli->inbuf);
return len;
}
@@ -85,7 +111,7 @@ bool cli_receive_smb(struct cli_state *cli)
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
if (cli->fd == -1)
- return False;
+ return false;
again:
len = client_receive_smb(cli, 0);
@@ -100,7 +126,7 @@ bool cli_receive_smb(struct cli_state *cli)
int fnum = SVAL(cli->inbuf,smb_vwv2);
unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
if (!cli->oplock_handler(cli, fnum, level)) {
- return False;
+ return false;
}
}
/* try to prevent loops */
@@ -114,7 +140,7 @@ bool cli_receive_smb(struct cli_state *cli)
DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
}
if (!cli_check_sign_mac(cli)) {
@@ -135,16 +161,16 @@ bool cli_receive_smb(struct cli_state *cli)
* Set bad sig but don't close fd.
*/
cli->smb_rw_error = SMB_READ_BAD_SIG;
- return True;
+ return true;
}
DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
cli->smb_rw_error = SMB_READ_BAD_SIG;
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
};
- return True;
+ return true;
}
/****************************************************************************
@@ -164,6 +190,7 @@ ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
/****************************************************************************
Read a smb readX header.
+ We can only use this if encryption and signing are off.
****************************************************************************/
bool cli_receive_smb_readX_header(struct cli_state *cli)
@@ -171,7 +198,7 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
ssize_t len, offset;
if (cli->fd == -1)
- return False;
+ return false;
again:
@@ -199,7 +226,7 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
if (cli->oplock_handler) {
int fnum = SVAL(cli->inbuf,smb_vwv2);
unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
- if (!cli->oplock_handler(cli, fnum, level)) return False;
+ if (!cli->oplock_handler(cli, fnum, level)) return false;
}
/* try to prevent loops */
SCVAL(cli->inbuf,smb_com,0xFF);
@@ -238,14 +265,14 @@ bool cli_receive_smb_readX_header(struct cli_state *cli)
}
}
- return True;
+ return true;
read_err:
cli->smb_rw_error = SMB_READ_ERROR;
close(cli->fd);
cli->fd = -1;
- return False;
+ return false;
}
static ssize_t write_socket(int fd, const char *buf, size_t len)
@@ -272,32 +299,54 @@ bool cli_send_smb(struct cli_state *cli)
size_t len;
size_t nwritten=0;
ssize_t ret;
+ char *buf_out = cli->outbuf;
+ bool enc_on = cli_encryption_on(cli);
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
if (cli->fd == -1)
- return False;
+ return false;
cli_calculate_sign_mac(cli);
- len = smb_len(cli->outbuf) + 4;
+ if (enc_on) {
+ NTSTATUS status = cli_encrypt_message(cli, &buf_out);
+ if (!NT_STATUS_IS_OK(status)) {
+ close(cli->fd);
+ cli->fd = -1;
+ cli->smb_rw_error = SMB_WRITE_ERROR;
+ DEBUG(0,("Error in encrypting client message. Error %s\n",
+ nt_errstr(status) ));
+ return false;
+ }
+ }
+
+ len = smb_len(buf_out) + 4;
while (nwritten < len) {
- ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
+ ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten);
if (ret <= 0) {
+ if (enc_on) {
+ cli_free_enc_buffer(cli, buf_out);
+ }
close(cli->fd);
cli->fd = -1;
cli->smb_rw_error = SMB_WRITE_ERROR;
DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
(int)len,(int)ret, strerror(errno) ));
- return False;
+ return false;
}
nwritten += ret;
}
+
+ if (enc_on) {
+ cli_free_enc_buffer(cli, buf_out);
+ }
+
/* Increment the mid so we can tell between responses. */
cli->mid++;
if (!cli->mid)
cli->mid++;
- return True;
+ return true;
}
/****************************************************************************
@@ -347,7 +396,7 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli,
DEBUG(0,("Error writing %d extradata "
"bytes to client. %d (%s)\n",
(int)extradata,(int)ret, strerror(errno) ));
- return False;
+ return false;
}
nwritten += ret;
}
@@ -409,7 +458,7 @@ void cli_init_creds(struct cli_state *cli, const char *username, const char *dom
fstrcpy(cli->user_name, username);
pwd_set_cleartext(&cli->pwd, password);
if (!*username) {
- cli->pwd.null_pwd = True;
+ cli->pwd.null_pwd = true;
}
DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain));
@@ -424,16 +473,16 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state)
if (signing_state == Undefined)
return;
- if (signing_state == False) {
- cli->sign_info.allow_smb_signing = False;
- cli->sign_info.mandatory_signing = False;
+ if (signing_state == false) {
+ cli->sign_info.allow_smb_signing = false;
+ cli->sign_info.mandatory_signing = false;
return;
}
- cli->sign_info.allow_smb_signing = True;
+ cli->sign_info.allow_smb_signing = true;
if (signing_state == Required)
- cli->sign_info.mandatory_signing = True;
+ cli->sign_info.mandatory_signing = true;
}
/****************************************************************************
@@ -470,7 +519,7 @@ struct cli_state *cli_initialise(void)
cli->outbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
cli->oplock_handler = cli_oplock_ack;
- cli->case_sensitive = False;
+ cli->case_sensitive = false;
cli->smb_rw_error = SMB_READ_OK;
cli->use_spnego = lp_client_use_spnego();
@@ -481,13 +530,13 @@ struct cli_state *cli_initialise(void)
client routines using DOS errors instead of STATUS32
ones. This intended only as a temporary hack. */
if (getenv("CLI_FORCE_DOSERR"))
- cli->force_dos_errors = True;
+ cli->force_dos_errors = true;
if (lp_client_signing())
- cli->sign_info.allow_smb_signing = True;
+ cli->sign_info.allow_smb_signing = true;
if (lp_client_signing() == Required)
- cli->sign_info.mandatory_signing = True;
+ cli->sign_info.mandatory_signing = true;
if (!cli->outbuf || !cli->inbuf)
goto error;
@@ -522,7 +571,7 @@ struct cli_state *cli_initialise(void)
/****************************************************************************
External interface.
Close an open named pipe over SMB. Free any authentication data.
- Returns False if the cli_close call failed.
+ Returns false if the cli_close call failed.
****************************************************************************/
bool cli_rpc_pipe_close(struct rpc_pipe_client *cli)
@@ -530,7 +579,7 @@ bool cli_rpc_pipe_close(struct rpc_pipe_client *cli)
bool ret;
if (!cli) {
- return False;
+ return false;
}
ret = cli_close(cli->cli, cli->fnum);
@@ -650,15 +699,15 @@ bool cli_send_keepalive(struct cli_state *cli)
{
if (cli->fd == -1) {
DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
- return False;
+ return false;
}
if (!send_keepalive(cli->fd)) {
close(cli->fd);
cli->fd = -1;
DEBUG(0,("Error sending keepalive packet to client.\n"));
- return False;
+ return false;
}
- return True;
+ return true;
}
/****************************************************************************
@@ -674,7 +723,7 @@ bool cli_echo(struct cli_state *cli, uint16 num_echos,
SMB_ASSERT(length < 1024);
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,length,True);
+ cli_set_message(cli->outbuf,1,length,true);
SCVAL(cli->outbuf,smb_com,SMBecho);
SSVAL(cli->outbuf,smb_tid,65535);
SSVAL(cli->outbuf,smb_vwv0,num_echos);
@@ -689,13 +738,13 @@ bool cli_echo(struct cli_state *cli, uint16 num_echos,
for (i=0; i<num_echos; i++) {
if (!cli_receive_smb(cli)) {
- return False;
+ return false;
}
if (cli_is_error(cli)) {
- return False;
+ return false;
}
}
- return True;
+ return true;
}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 001a42d4b9..9b4c380d40 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -429,7 +429,7 @@ bool cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1, 0, true);
+ cli_set_message(cli->outbuf,1, 0, true);
SCVAL(cli->outbuf,smb_com,SMBmv);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -470,7 +470,7 @@ bool cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fnam
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 4, 0, true);
+ cli_set_message(cli->outbuf, 4, 0, true);
SCVAL(cli->outbuf,smb_com,SMBntrename);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -512,7 +512,7 @@ bool cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *f
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 4, 0, true);
+ cli_set_message(cli->outbuf, 4, 0, true);
SCVAL(cli->outbuf,smb_com,SMBntrename);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -554,7 +554,7 @@ bool cli_unlink_full(struct cli_state *cli, const char *fname, uint16 attrs)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1, 0, true);
+ cli_set_message(cli->outbuf,1, 0, true);
SCVAL(cli->outbuf,smb_com,SMBunlink);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -600,7 +600,7 @@ bool cli_mkdir(struct cli_state *cli, const char *dname)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0, 0, true);
+ cli_set_message(cli->outbuf,0, 0, true);
SCVAL(cli->outbuf,smb_com,SMBmkdir);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -636,7 +636,7 @@ bool cli_rmdir(struct cli_state *cli, const char *dname)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0, 0, true);
+ cli_set_message(cli->outbuf,0, 0, true);
SCVAL(cli->outbuf,smb_com,SMBrmdir);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -719,7 +719,7 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,24,0, true);
+ cli_set_message(cli->outbuf,24,0, true);
SCVAL(cli->outbuf,smb_com,SMBntcreateX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -815,7 +815,7 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,15,0, true);
+ cli_set_message(cli->outbuf,15,0, true);
SCVAL(cli->outbuf,smb_com,SMBopenX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -863,7 +863,7 @@ bool cli_close(struct cli_state *cli, int fnum)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -896,7 +896,7 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -948,7 +948,7 @@ bool cli_lock(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1001,7 +1001,7 @@ bool cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1053,7 +1053,7 @@ bool cli_lock64(struct cli_state *cli, int fnum,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0', smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1108,7 +1108,7 @@ bool cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBlockingX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1255,7 +1255,7 @@ bool cli_getattrE(struct cli_state *cli, int fd,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBgetattrE);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1307,7 +1307,7 @@ bool cli_getatr(struct cli_state *cli, const char *fname,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBgetatr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1359,7 +1359,7 @@ bool cli_setattrE(struct cli_state *cli, int fd,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,7,0,True);
+ cli_set_message(cli->outbuf,7,0,True);
SCVAL(cli->outbuf,smb_com,SMBsetattrE);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1398,7 +1398,7 @@ bool cli_setatr(struct cli_state *cli, const char *fname, uint16 attr, time_t t)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,8,0,True);
+ cli_set_message(cli->outbuf,8,0,True);
SCVAL(cli->outbuf,smb_com,SMBsetatr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1452,7 +1452,7 @@ bool cli_chkpath(struct cli_state *cli, const char *path)
}
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBcheckpath);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1483,7 +1483,7 @@ bool cli_chkpath(struct cli_state *cli, const char *path)
bool cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
{
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBdskattr);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -1512,7 +1512,7 @@ int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBctemp);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -1565,7 +1565,7 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf, 3, 0, True);
+ cli_set_message(cli->outbuf, 3, 0, True);
SCVAL(cli->outbuf,smb_com,SMBioctl);
cli_setup_packet(cli);
diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index 1a75d144b2..fb923378ab 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
FS info functions
Copyright (C) Stefan (metze) Metzmacher 2003
+ Copyright (C) Jeremy Allison 2007
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
@@ -301,3 +302,368 @@ cleanup:
return ret;
}
+
+/******************************************************************************
+ Send/receive the request encryption blob.
+******************************************************************************/
+
+static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
+{
+ uint16 setup;
+ char param[4];
+ char *rparam=NULL, *rdata=NULL;
+ unsigned int rparam_count=0, rdata_count=0;
+ NTSTATUS status = NT_STATUS_OK;
+
+ setup = TRANSACT2_SETFSINFO;
+
+ SSVAL(param,0,0);
+ SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL,
+ 0, 0,
+ &setup, 1, 0,
+ param, 4, 0,
+ (char *)in->data, in->length, CLI_BUFFER_SIZE)) {
+ status = cli_nt_error(cli);
+ goto out;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &rparam_count,
+ &rdata, &rdata_count)) {
+ status = cli_nt_error(cli);
+ goto out;
+ }
+
+ if (cli_is_error(cli)) {
+ status = cli_nt_error(cli);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ goto out;
+ }
+ }
+
+ *out = data_blob(rdata, rdata_count);
+ *param_out = data_blob(rparam, rparam_count);
+
+ out:
+
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+ return status;
+}
+
+/******************************************************************************
+ Make a client state struct.
+******************************************************************************/
+
+static struct smb_trans_enc_state *make_cli_enc_state(enum smb_trans_enc_type smb_enc_type)
+{
+ struct smb_trans_enc_state *es = NULL;
+ es = SMB_MALLOC_P(struct smb_trans_enc_state);
+ if (!es) {
+ return NULL;
+ }
+ ZERO_STRUCTP(es);
+ es->smb_enc_type = smb_enc_type;
+
+ if (smb_enc_type == SMB_TRANS_ENC_GSS) {
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
+ if (!es->s.gss_state) {
+ SAFE_FREE(es);
+ return NULL;
+ }
+ ZERO_STRUCTP(es->s.gss_state);
+#else
+ DEBUG(0,("make_cli_enc_state: no krb5 compiled.\n"));
+ SAFE_FREE(es);
+ return NULL;
+#endif
+ }
+ return es;
+}
+
+/******************************************************************************
+ Start a raw ntlmssp encryption.
+******************************************************************************/
+
+NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli,
+ const char *user,
+ const char *pass,
+ const char *domain)
+{
+ DATA_BLOB blob_in = data_blob_null;
+ DATA_BLOB blob_out = data_blob_null;
+ DATA_BLOB param_out = data_blob_null;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_NTLM);
+
+ if (!es) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = ntlmssp_client_start(&es->s.ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ ntlmssp_want_feature(es->s.ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
+ es->s.ntlmssp_state->neg_flags |= (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
+
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_username(es->s.ntlmssp_state, user))) {
+ goto fail;
+ }
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_domain(es->s.ntlmssp_state, domain))) {
+ goto fail;
+ }
+ if (!NT_STATUS_IS_OK(status = ntlmssp_set_password(es->s.ntlmssp_state, pass))) {
+ goto fail;
+ }
+
+ do {
+ status = ntlmssp_update(es->s.ntlmssp_state, blob_in, &blob_out);
+ data_blob_free(&blob_in);
+ data_blob_free(&param_out);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
+ NTSTATUS trans_status = enc_blob_send_receive(cli,
+ &blob_out,
+ &blob_in,
+ &param_out);
+ if (!NT_STATUS_EQUAL(trans_status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+ !NT_STATUS_IS_OK(trans_status)) {
+ status = trans_status;
+ } else {
+ if (param_out.length == 2) {
+ es->enc_ctx_num = SVAL(param_out.data, 0);
+ }
+ }
+ }
+ data_blob_free(&blob_out);
+ } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+
+ data_blob_free(&blob_in);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Replace the old state, if any. */
+ if (cli->trans_enc_state) {
+ common_free_encryption_state(&cli->trans_enc_state);
+ }
+ cli->trans_enc_state = es;
+ cli->trans_enc_state->enc_on = True;
+ es = NULL;
+ }
+
+ fail:
+
+ common_free_encryption_state(&es);
+ return status;
+}
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+
+#ifndef SMB_GSS_REQUIRED_FLAGS
+#define SMB_GSS_REQUIRED_FLAGS (GSS_C_CONF_FLAG|GSS_C_INTEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)
+#endif
+
+/******************************************************************************
+ Get client gss blob to send to a server.
+******************************************************************************/
+
+static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es,
+ const char *service,
+ const char *host,
+ NTSTATUS status_in,
+ DATA_BLOB spnego_blob_in,
+ DATA_BLOB *p_blob_out)
+{
+ const char *krb_mechs[] = {OID_KERBEROS5, NULL};
+ OM_uint32 ret;
+ OM_uint32 min;
+ gss_name_t srv_name;
+ gss_buffer_desc input_name;
+ gss_buffer_desc *p_tok_in;
+ gss_buffer_desc tok_out, tok_in;
+ DATA_BLOB blob_out = data_blob_null;
+ DATA_BLOB blob_in = data_blob_null;
+ char *host_princ_s = NULL;
+ OM_uint32 ret_flags = 0;
+ NTSTATUS status = NT_STATUS_OK;
+
+ gss_OID_desc nt_hostbased_service =
+ {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
+
+ memset(&tok_out, '\0', sizeof(tok_out));
+
+ /* Get a ticket for the service@host */
+ asprintf(&host_princ_s, "%s@%s", service, host);
+ if (host_princ_s == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ input_name.value = host_princ_s;
+ input_name.length = strlen(host_princ_s) + 1;
+
+ ret = gss_import_name(&min,
+ &input_name,
+ &nt_hostbased_service,
+ &srv_name);
+
+ if (ret != GSS_S_COMPLETE) {
+ SAFE_FREE(host_princ_s);
+ return map_nt_error_from_gss(ret, min);
+ }
+
+ if (spnego_blob_in.length == 0) {
+ p_tok_in = GSS_C_NO_BUFFER;
+ } else {
+ /* Remove the SPNEGO wrapper */
+ if (!spnego_parse_auth_response(spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto fail;
+ }
+ tok_in.value = blob_in.data;
+ tok_in.length = blob_in.length;
+ p_tok_in = &tok_in;
+ }
+
+ ret = gss_init_sec_context(&min,
+ GSS_C_NO_CREDENTIAL, /* Use our default cred. */
+ &es->s.gss_state->gss_ctx,
+ srv_name,
+ GSS_C_NO_OID, /* default OID. */
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
+ GSS_C_INDEFINITE, /* requested ticket lifetime. */
+ NULL, /* no channel bindings */
+ p_tok_in,
+ NULL, /* ignore mech type */
+ &tok_out,
+ &ret_flags,
+ NULL); /* ignore time_rec */
+
+ status = map_nt_error_from_gss(ret, min);
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
+ DEBUG(10,("make_cli_gss_blob: gss_init_sec_context failed with %s\n",
+ ads_errstr(adss)));
+ goto fail;
+ }
+
+ if ((ret_flags & SMB_GSS_REQUIRED_FLAGS) != SMB_GSS_REQUIRED_FLAGS) {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
+
+ blob_out = data_blob(tok_out.value, tok_out.length);
+
+ /* Wrap in an SPNEGO wrapper */
+ *p_blob_out = gen_negTokenTarg(krb_mechs, blob_out);
+
+ fail:
+
+ data_blob_free(&blob_out);
+ data_blob_free(&blob_in);
+ SAFE_FREE(host_princ_s);
+ gss_release_name(&min, &srv_name);
+ if (tok_out.value) {
+ gss_release_buffer(&min, &tok_out);
+ }
+ return status;
+}
+
+/******************************************************************************
+ Start a SPNEGO gssapi encryption context.
+******************************************************************************/
+
+NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
+{
+ DATA_BLOB blob_recv = data_blob_null;
+ DATA_BLOB blob_send = data_blob_null;
+ DATA_BLOB param_out = data_blob_null;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ fstring fqdn;
+ const char *servicename;
+ struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_GSS);
+
+ if (!es) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ name_to_fqdn(fqdn, cli->desthost);
+ strlower_m(fqdn);
+
+ servicename = "cifs";
+ status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ servicename = "host";
+ status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ goto fail;
+ }
+ }
+
+ do {
+ data_blob_free(&blob_recv);
+ status = enc_blob_send_receive(cli, &blob_send, &blob_recv, &param_out);
+ if (param_out.length == 2) {
+ es->enc_ctx_num = SVAL(param_out.data, 0);
+ }
+ data_blob_free(&blob_send);
+ status = make_cli_gss_blob(es, servicename, fqdn, status, blob_recv, &blob_send);
+ } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+ data_blob_free(&blob_recv);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Replace the old state, if any. */
+ if (cli->trans_enc_state) {
+ common_free_encryption_state(&cli->trans_enc_state);
+ }
+ cli->trans_enc_state = es;
+ cli->trans_enc_state->enc_on = True;
+ es = NULL;
+ }
+
+ fail:
+
+ common_free_encryption_state(&es);
+ return status;
+}
+#else
+NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+#endif
+
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+NTSTATUS cli_force_encryption(struct cli_state *c,
+ const char *username,
+ const char *password,
+ const char *domain)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+
+ if (!SERVER_HAS_UNIX_CIFS(c)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ return NT_STATUS_UNKNOWN_REVISION;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ return NT_STATUS_UNSUPPORTED_COMPRESSION;
+ }
+
+ if (c->use_kerberos) {
+ return cli_gss_smb_encryption_start(c);
+ }
+ return cli_raw_ntlm_smb_encryption_start(c,
+ username,
+ password,
+ domain);
+}
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 2e4c360507..d5c7db09e9 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -521,7 +521,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBsearch);
@@ -581,7 +581,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
+ cli_set_message(cli->outbuf,2,0,True);
SCVAL(cli->outbuf,smb_com,SMBfclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c
index 13ef1d43d4..00c25aa725 100644
--- a/source3/libsmb/climessage.c
+++ b/source3/libsmb/climessage.c
@@ -29,7 +29,7 @@ int cli_message_start_build(struct cli_state *cli, const char *host, const char
/* construct a SMBsendstrt command */
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,0,0,True);
+ cli_set_message(cli->outbuf,0,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendstrt);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -75,7 +75,7 @@ int cli_message_text_build(struct cli_state *cli, const char *msg, int len, int
char *p;
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendtxt);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
cli_setup_packet(cli);
@@ -132,7 +132,7 @@ int cli_message_end_build(struct cli_state *cli, int grp)
char *p;
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,1,0,True);
+ cli_set_message(cli->outbuf,1,0,True);
SCVAL(cli->outbuf,smb_com,SMBsendend);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c
index 2e54f5a781..ef8b396461 100644
--- a/source3/libsmb/clioplock.c
+++ b/source3/libsmb/clioplock.c
@@ -32,7 +32,7 @@ bool cli_oplock_ack(struct cli_state *cli, int fnum, unsigned char level)
cli->outbuf = buf;
memset(buf,'\0',smb_size);
- set_message(buf,8,0,True);
+ cli_set_message(buf,8,0,True);
SCVAL(buf,smb_com,SMBlockingX);
SSVAL(buf,smb_tid, cli->cnum);
diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c
index 7fbdb97c01..223ddb4186 100644
--- a/source3/libsmb/cliprint.c
+++ b/source3/libsmb/cliprint.c
@@ -195,7 +195,7 @@ int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,15,0,True);
+ cli_set_message(cli->outbuf,15,0,True);
SCVAL(cli->outbuf,smb_com,SMBsplopen);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -242,7 +242,7 @@ bool cli_spl_close(struct cli_state *cli, int fnum)
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,3,0,True);
+ cli_set_message(cli->outbuf,3,0,True);
SCVAL(cli->outbuf,smb_com,SMBsplclose);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/cliquota.c b/source3/libsmb/cliquota.c
index 206576f040..f369d28dff 100644
--- a/source3/libsmb/cliquota.c
+++ b/source3/libsmb/cliquota.c
@@ -150,7 +150,7 @@ bool cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUC
SIVAL(params, 8,0x00000000);
SIVAL(params,12,0x00000024);
- sid_len = sid_size(&pqt->sid);
+ sid_len = ndr_size_dom_sid(&pqt->sid, 0);
data_len = sid_len+8;
SIVAL(data, 0, 0x00000000);
SIVAL(data, 4, sid_len);
@@ -213,7 +213,7 @@ bool cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUC
SSVAL(params,0,quota_fnum);
- sid_len = sid_size(&pqt->sid);
+ sid_len = ndr_size_dom_sid(&pqt->sid, 0);
SIVAL(data,0,0);
SIVAL(data,4,sid_len);
SBIG_UINT(data, 8,(SMB_BIG_UINT)0);
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index d77875bae5..0b33e43563 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -34,7 +34,7 @@ static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
if ((SMB_BIG_UINT)offset >> 32)
bigoffset = True;
- set_message(cli->outbuf,bigoffset ? 12 : 10,0,True);
+ cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True);
SCVAL(cli->outbuf,smb_com,SMBreadX);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -65,8 +65,8 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
size_t size2;
size_t readsize;
ssize_t total = 0;
- /* We can only do direct reads if not signing. */
- bool direct_reads = !client_is_signing_on(cli);
+ /* We can only do direct reads if not signing or encrypting. */
+ bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli);
if (size == 0)
return 0;
@@ -76,7 +76,9 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
* rounded down to a multiple of 1024.
*/
- if (client_is_signing_on(cli) == False && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
+ if (client_is_signing_on(cli) == false &&
+ cli_encryption_on(cli) == false &&
+ (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
} else if (cli->capabilities & CAP_LARGE_READX) {
if (cli->is_samba) {
@@ -203,7 +205,7 @@ static bool cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,10,0,True);
+ cli_set_message(cli->outbuf,10,0,True);
SCVAL(cli->outbuf,smb_com,SMBreadbraw);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
@@ -295,8 +297,8 @@ static bool cli_issue_write(struct cli_state *cli,
{
char *p;
bool large_writex = false;
- /* We can only do direct writes if not signing. */
- bool direct_writes = !client_is_signing_on(cli);
+ /* We can only do direct writes if not signing and not encrypting. */
+ bool direct_writes = !client_is_signing_on(cli) && !cli_encryption_on(cli);
if (!direct_writes && size + 1 > cli->bufsize) {
cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024);
@@ -319,9 +321,9 @@ static bool cli_issue_write(struct cli_state *cli,
}
if (large_writex) {
- set_message(cli->outbuf,14,0,True);
+ cli_set_message(cli->outbuf,14,0,True);
} else {
- set_message(cli->outbuf,12,0,True);
+ cli_set_message(cli->outbuf,12,0,True);
}
SCVAL(cli->outbuf,smb_com,SMBwriteX);
@@ -404,16 +406,17 @@ ssize_t cli_write(struct cli_state *cli,
if (write_mode == 0 &&
!client_is_signing_on(cli) &&
+ !cli_encryption_on(cli) &&
(cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
(cli->capabilities & CAP_LARGE_FILES)) {
/* Only do massive writes if we can do them direct
- * with no signing - not on a pipe. */
+ * with no signing or encrypting - not on a pipe. */
writesize = CLI_SAMBA_MAX_POSIX_LARGE_WRITEX_SIZE;
- } else if (cli->capabilities & CAP_LARGE_READX) {
+ } else if (cli->capabilities & CAP_LARGE_WRITEX) {
if (cli->is_samba) {
- writesize = CLI_SAMBA_MAX_LARGE_READX_SIZE;
+ writesize = CLI_SAMBA_MAX_LARGE_WRITEX_SIZE;
} else {
- writesize = CLI_WINDOWS_MAX_LARGE_READX_SIZE;
+ writesize = CLI_WINDOWS_MAX_LARGE_WRITEX_SIZE;
}
} else {
writesize = (cli->max_xmit - (smb_size+32)) & ~1023;
@@ -471,7 +474,7 @@ ssize_t cli_smbwrite(struct cli_state *cli,
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
- set_message(cli->outbuf,5, 0,True);
+ cli_set_message(cli->outbuf,5, 0,True);
SCVAL(cli->outbuf,smb_com,SMBwrite);
SSVAL(cli->outbuf,smb_tid,cli->cnum);
diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c
index 46a6609415..adc6fba9af 100644
--- a/source3/libsmb/clisecdesc.c
+++ b/source3/libsmb/clisecdesc.c
@@ -28,9 +28,8 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
char param[8];
char *rparam=NULL, *rdata=NULL;
unsigned int rparam_count=0, rdata_count=0;
- prs_struct pd;
- bool pd_initialized = False;
SEC_DESC *psd = NULL;
+ NTSTATUS status;
SIVAL(param, 0, fnum);
SIVAL(param, 4, 0x7);
@@ -56,15 +55,12 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
if (cli_is_error(cli))
goto cleanup;
- if (!prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL)) {
- goto cleanup;
- }
- pd_initialized = True;
- prs_copy_data_in(&pd, rdata, rdata_count);
- prs_set_offset(&pd,0);
+ status = unmarshall_sec_desc(mem_ctx, (uint8 *)rdata, rdata_count,
+ &psd);
- if (!sec_io_desc("sd data", &psd, &pd, 1)) {
- DEBUG(1,("Failed to parse secdesc\n"));
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("unmarshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
goto cleanup;
}
@@ -73,8 +69,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
SAFE_FREE(rparam);
SAFE_FREE(rdata);
- if (pd_initialized)
- prs_mem_free(&pd);
return psd;
}
@@ -87,20 +81,16 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
char *rparam=NULL, *rdata=NULL;
unsigned int rparam_count=0, rdata_count=0;
uint32 sec_info = 0;
- TALLOC_CTX *mem_ctx;
- prs_struct pd;
+ TALLOC_CTX *frame = talloc_stackframe();
bool ret = False;
-
- if ((mem_ctx = talloc_init("cli_set_secdesc")) == NULL) {
- DEBUG(0,("talloc_init failed.\n"));
- goto cleanup;
- }
-
- prs_init(&pd, 0, mem_ctx, MARSHALL);
- prs_give_memory(&pd, NULL, 0, True);
-
- if (!sec_io_desc("sd data", &sd, &pd, 1)) {
- DEBUG(1,("Failed to marshall secdesc\n"));
+ uint8 *data;
+ size_t len;
+ NTSTATUS status;
+
+ status = marshall_sec_desc(talloc_tos(), sd, &data, &len);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("marshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
goto cleanup;
}
@@ -119,7 +109,7 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
0,
NULL, 0, 0,
param, 8, 0,
- prs_data_p(&pd), prs_offset(&pd), 0)) {
+ (char *)data, len, 0)) {
DEBUG(1,("Failed to send NT_TRANSACT_SET_SECURITY_DESC\n"));
goto cleanup;
}
@@ -139,8 +129,7 @@ bool cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
SAFE_FREE(rparam);
SAFE_FREE(rdata);
- talloc_destroy(mem_ctx);
+ TALLOC_FREE(frame);
- prs_mem_free(&pd);
return ret;
}
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index a6f7f7fec1..bfb31fdb74 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -43,7 +43,7 @@ bool cli_send_trans(struct cli_state *cli, int trans,
this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,14+lsetup,0,True);
+ cli_set_message(cli->outbuf,14+lsetup,0,True);
SCVAL(cli->outbuf,smb_com,trans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
@@ -107,7 +107,7 @@ bool cli_send_trans(struct cli_state *cli, int trans,
this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
- set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
+ cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
outparam = smb_buf(cli->outbuf);
@@ -368,7 +368,7 @@ bool cli_send_nt_trans(struct cli_state *cli,
this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,19+lsetup,0,True);
+ cli_set_message(cli->outbuf,19+lsetup,0,True);
SCVAL(cli->outbuf,smb_com,SMBnttrans);
SSVAL(cli->outbuf,smb_tid, cli->cnum);
cli_setup_packet(cli);
@@ -424,7 +424,7 @@ bool cli_send_nt_trans(struct cli_state *cli,
this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
- set_message(cli->outbuf,18,0,True);
+ cli_set_message(cli->outbuf,18,0,True);
SCVAL(cli->outbuf,smb_com,SMBnttranss);
/* XXX - these should probably be aligned */
diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c
index dd556bba5a..79445a2410 100644
--- a/source3/libsmb/doserr.c
+++ b/source3/libsmb/doserr.c
@@ -63,6 +63,7 @@ werror_code_struct dos_errs[] =
{ "WERR_JOB_NOT_FOUND", WERR_JOB_NOT_FOUND },
{ "WERR_DEST_NOT_FOUND", WERR_DEST_NOT_FOUND },
{ "WERR_NOT_LOCAL_DOMAIN", WERR_NOT_LOCAL_DOMAIN },
+ { "WERR_USER_EXISTS", WERR_USER_EXISTS },
{ "WERR_NO_LOGON_SERVERS", WERR_NO_LOGON_SERVERS },
{ "WERR_NO_SUCH_LOGON_SESSION", WERR_NO_SUCH_LOGON_SESSION },
{ "WERR_PRINTER_DRIVER_IN_USE", WERR_PRINTER_DRIVER_IN_USE },
@@ -77,6 +78,7 @@ werror_code_struct dos_errs[] =
{ "WERR_SETUP_NOT_JOINED", WERR_SETUP_NOT_JOINED },
{ "WERR_SETUP_ALREADY_JOINED", WERR_SETUP_ALREADY_JOINED },
{ "WERR_SETUP_DOMAIN_CONTROLLER", WERR_SETUP_DOMAIN_CONTROLLER },
+ { "WERR_DEFAULT_JOIN_REQUIRED", WERR_DEFAULT_JOIN_REQUIRED },
{ "WERR_DEVICE_NOT_AVAILABLE", WERR_DEVICE_NOT_AVAILABLE },
{ "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
{ "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
@@ -90,6 +92,7 @@ werror_code_struct dos_errs[] =
{ "WERR_REG_CORRUPT", WERR_REG_CORRUPT },
{ "WERR_REG_IO_FAILURE", WERR_REG_IO_FAILURE },
{ "WERR_REG_FILE_INVALID", WERR_REG_FILE_INVALID },
+ { "WERR_NO_SUCH_SERVICE", WERR_NO_SUCH_SERVICE },
{ "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED },
{ "WERR_CAN_NOT_COMPLETE", WERR_CAN_NOT_COMPLETE},
{ "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS},
@@ -110,6 +113,7 @@ werror_str_struct dos_err_strs[] = {
{ WERR_SETUP_ALREADY_JOINED, "Machine is already joined" },
{ WERR_SETUP_DOMAIN_CONTROLLER, "Machine is a Domain Controller" },
{ WERR_LOGON_FAILURE, "Invalid logon credentials" },
+ { WERR_USER_EXISTS, "User account already exists" },
};
/*****************************************************************************
diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c
index ce826ae999..4ec30f7e17 100644
--- a/source3/libsmb/errormap.c
+++ b/source3/libsmb/errormap.c
@@ -1502,3 +1502,108 @@ WERROR ntstatus_to_werror(NTSTATUS error)
/* a lame guess */
return W_ERROR(NT_STATUS_V(error) & 0xffff);
}
+
+#if defined(HAVE_GSSAPI)
+/*******************************************************************************
+ Map between gssapi errors and NT status. I made these up :-(. JRA.
+*******************************************************************************/
+
+static const struct {
+ unsigned long gss_err;
+ NTSTATUS ntstatus;
+} gss_to_ntstatus_errormap[] = {
+#if defined(GSS_S_CALL_INACCESSIBLE_READ)
+ {GSS_S_CALL_INACCESSIBLE_READ, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_CALL_INACCESSIBLE_WRITE)
+ {GSS_S_CALL_INACCESSIBLE_WRITE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_CALL_BAD_STRUCTURE)
+ {GSS_S_CALL_BAD_STRUCTURE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_MECH)
+ {GSS_S_BAD_MECH, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_NAME)
+ {GSS_S_BAD_NAME, NT_STATUS_INVALID_ACCOUNT_NAME},
+#endif
+#if defined(GSS_S_BAD_NAMETYPE)
+ {GSS_S_BAD_NAMETYPE, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_BINDINGS)
+ {GSS_S_BAD_BINDINGS, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_BAD_STATUS)
+ {GSS_S_BAD_STATUS, NT_STATUS_UNSUCCESSFUL},
+#endif
+#if defined(GSS_S_BAD_SIG)
+ {GSS_S_BAD_SIG, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_NO_CRED)
+ {GSS_S_NO_CRED, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_NO_CONTEXT)
+ {GSS_S_NO_CONTEXT, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_DEFECTIVE_TOKEN)
+ {GSS_S_DEFECTIVE_TOKEN, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_DEFECTIVE_CREDENTIAL)
+ {GSS_S_DEFECTIVE_CREDENTIAL, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_CREDENTIALS_EXPIRED)
+ {GSS_S_CREDENTIALS_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#endif
+#if defined(GSS_S_CONTEXT_EXPIRED)
+ {GSS_S_CONTEXT_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#endif
+#if defined(GSS_S_BAD_QOP)
+ {GSS_S_BAD_QOP, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_UNAUTHORIZED)
+ {GSS_S_UNAUTHORIZED, NT_STATUS_ACCESS_DENIED},
+#endif
+#if defined(GSS_S_UNAVAILABLE)
+ {GSS_S_UNAVAILABLE, NT_STATUS_UNSUCCESSFUL},
+#endif
+#if defined(GSS_S_DUPLICATE_ELEMENT)
+ {GSS_S_DUPLICATE_ELEMENT, NT_STATUS_INVALID_PARAMETER},
+#endif
+#if defined(GSS_S_NAME_NOT_MN)
+ {GSS_S_NAME_NOT_MN, NT_STATUS_INVALID_PARAMETER},
+#endif
+ { 0, NT_STATUS_OK }
+};
+
+/*********************************************************************
+ Map an NT error code from a gssapi error code.
+*********************************************************************/
+
+NTSTATUS map_nt_error_from_gss(uint32 gss_maj, uint32 minor)
+{
+ int i = 0;
+
+ if (gss_maj == GSS_S_COMPLETE) {
+ return NT_STATUS_OK;
+ }
+
+ if (gss_maj == GSS_S_CONTINUE_NEEDED) {
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
+
+ if (gss_maj == GSS_S_FAILURE) {
+ return map_nt_error_from_unix((int)minor);
+ }
+
+ /* Look through list */
+ while(gss_to_ntstatus_errormap[i].gss_err != 0) {
+ if (gss_to_ntstatus_errormap[i].gss_err == gss_maj) {
+ return gss_to_ntstatus_errormap[i].ntstatus;
+ }
+ i++;
+ }
+
+ /* Default return */
+ return NT_STATUS_ACCESS_DENIED;
+}
+#endif
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 2ff2830256..da8f1e332b 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -6,6 +6,7 @@
Copyright (C) John Terpstra 2000
Copyright (C) Tom Jansen (Ninja ISD) 2002
Copyright (C) Derrell Lipman 2003, 2004
+ Copyright (C) Jeremy Allison 2007, 2008
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
@@ -739,6 +740,12 @@ smbc_server(SMBCCTX *context,
password, strlen(password)+1);
}
+ /*
+ * We don't need to renegotiate encryption
+ * here as the encryption context is not per
+ * tid.
+ */
+
if (! cli_send_tconX(srv->cli, share, "?????",
password, strlen(password)+1)) {
@@ -903,6 +910,30 @@ smbc_server(SMBCCTX *context,
DEBUG(4,(" tconx ok\n"));
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(c,
+ username_used,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(c);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok\n"));
+ }
+
/*
* Ok, we have got a nice connection
* Let's allocate a server structure.
@@ -1019,6 +1050,30 @@ smbc_attr_server(SMBCCTX *context,
return NULL;
}
+ if (context->internal->_smb_encryption_level) {
+ /* Attempt UNIX smb encryption. */
+ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
+ username,
+ password,
+ workgroup))) {
+
+ /*
+ * context->internal->_smb_encryption_level == 1
+ * means don't fail if encryption can't be negotiated,
+ * == 2 means fail if encryption can't be negotiated.
+ */
+
+ DEBUG(4,(" SMB encrypt failed on IPC$\n"));
+
+ if (context->internal->_smb_encryption_level == 2) {
+ cli_shutdown(ipc_cli);
+ errno = EPERM;
+ return NULL;
+ }
+ }
+ DEBUG(4,(" SMB encrypt ok on IPC$\n"));
+ }
+
ipc_srv = SMB_MALLOC_P(SMBCSRV);
if (!ipc_srv) {
errno = ENOMEM;
@@ -6724,6 +6779,7 @@ smbc_option_set(SMBCCTX *context,
bool b;
smbc_get_auth_data_with_context_fn auth_fn;
void *v;
+ const char *s;
} option_value;
va_start(ap, option_name);
@@ -6772,6 +6828,19 @@ smbc_option_set(SMBCCTX *context,
*/
option_value.v = va_arg(ap, void *);
context->internal->_user_data = option_value.v;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Save an encoded value for encryption level.
+ * 0 = off, 1 = attempt, 2 = required.
+ */
+ option_value.s = va_arg(ap, const char *);
+ if (strcmp(option_value.s, "none") == 0) {
+ context->internal->_smb_encryption_level = 0;
+ } else if (strcmp(option_value.s, "request") == 0) {
+ context->internal->_smb_encryption_level = 1;
+ } else if (strcmp(option_value.s, "require") == 0) {
+ context->internal->_smb_encryption_level = 2;
+ }
}
va_end(ap);
@@ -6821,6 +6890,35 @@ smbc_option_get(SMBCCTX *context,
* with smbc_option_get()
*/
return context->internal->_user_data;
+ } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+ /*
+ * Return the current smb encrypt negotiate option as a string.
+ */
+ switch (context->internal->_smb_encryption_level) {
+ case 0:
+ return (void *) "none";
+ case 1:
+ return (void *) "request";
+ case 2:
+ return (void *) "require";
+ }
+ } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
+ /*
+ * Return the current smb encrypt status option as a bool.
+ * false = off, true = on. We don't know what server is
+ * being requested, so we only return true if all servers
+ * are using an encrypted connection.
+ */
+ SMBCSRV *s;
+ unsigned int num_servers = 0;
+
+ for (s = context->internal->_servers; s; s = s->next) {
+ num_servers++;
+ if (s->cli->trans_enc_state == NULL) {
+ return (void *)false;
+ }
+ }
+ return (void *) (bool) (num_servers > 0);
}
return NULL;
diff --git a/source3/libsmb/ntlm_check.c b/source3/libsmb/ntlm_check.c
index f8ed044f8a..ae10d7373d 100644
--- a/source3/libsmb/ntlm_check.c
+++ b/source3/libsmb/ntlm_check.c
@@ -182,7 +182,10 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
DATA_BLOB *user_sess_key,
DATA_BLOB *lm_sess_key)
{
- static const unsigned char zeros[8] = { 0, };
+ unsigned char zeros[8];
+
+ ZERO_STRUCT(zeros);
+
if (nt_pw == NULL) {
DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n",
username));
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index ed08e8102b..35c20ed647 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -823,7 +823,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
session_key.data);
DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
} else {
- static const uint8 zeros[24] = { 0, };
+ uint8 zeros[24];
+ ZERO_STRUCT(zeros);
session_key = data_blob_talloc(
ntlmssp_state->mem_ctx, NULL, 16);
if (session_key.data == NULL) {
@@ -1066,9 +1067,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
}
if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
- static const uchar zeros[16] = { 0, };
+ uchar zeros[16];
/* do nothing - blobs are zero length */
+ ZERO_STRUCT(zeros);
+
/* session key is all zeros */
session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
new file mode 100644
index 0000000000..b5befbf7cd
--- /dev/null
+++ b/source3/libsmb/smb_seal.c
@@ -0,0 +1,497 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB Transport encryption (sealing) code.
+ Copyright (C) Jeremy Allison 2007.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/******************************************************************************
+ Pull out the encryption context for this packet. 0 means global context.
+******************************************************************************/
+
+NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16 *p_enc_ctx_num)
+{
+ if (smb_len(buf) < 8) {
+ return NT_STATUS_INVALID_BUFFER_SIZE;
+ }
+
+ if (buf[4] == 0xFF) {
+ if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
+ /* Not an encrypted buffer. */
+ return NT_STATUS_NOT_FOUND;
+ }
+ if (buf[5] == 'E') {
+ *p_enc_ctx_num = SVAL(buf,6);
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ Is encryption turned on ?
+******************************************************************************/
+
+bool common_encryption_on(struct smb_trans_enc_state *es)
+{
+ return ((es != NULL) && es->enc_on);
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ NTLM decrypt an incoming buffer.
+ Abartlett tells me that SSPI puts the signature first before the encrypted
+ output, so cope with the same for compatibility.
+******************************************************************************/
+
+NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
+{
+ NTSTATUS status;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+ size_t data_len;
+ char *inbuf;
+ DATA_BLOB sig;
+
+ if (buf_len < 8 + NTLMSSP_SIG_SIZE) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ inbuf = (char *)smb_xmemdup(buf, buf_len);
+
+ /* Adjust for the signature. */
+ data_len = buf_len - 8 - NTLMSSP_SIG_SIZE;
+
+ /* Point at the signature. */
+ sig = data_blob_const(inbuf+8, NTLMSSP_SIG_SIZE);
+
+ status = ntlmssp_unseal_packet(ntlmssp_state,
+ (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'E' <enc> <ctx> */
+ data_len,
+ (unsigned char *)inbuf + 8 + NTLMSSP_SIG_SIZE,
+ data_len,
+ &sig);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ SAFE_FREE(inbuf);
+ return status;
+ }
+
+ memcpy(buf + 8, inbuf + 8 + NTLMSSP_SIG_SIZE, data_len);
+
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf,data_len + 4);
+
+ SAFE_FREE(inbuf);
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
+ Abartlett tells me that SSPI puts the signature first before the encrypted
+ output, so do the same for compatibility.
+******************************************************************************/
+
+NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
+{
+ NTSTATUS status;
+ char *buf_out;
+ size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
+ DATA_BLOB sig;
+
+ *ppbuf_out = NULL;
+
+ if (data_len == 0) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /*
+ * We know smb_len can't return a value > 128k, so no int overflow
+ * check needed.
+ */
+
+ buf_out = SMB_XMALLOC_ARRAY(char, 8 + NTLMSSP_SIG_SIZE + data_len);
+
+ /* Copy the data from the original buffer. */
+
+ memcpy(buf_out + 8 + NTLMSSP_SIG_SIZE, buf + 8, data_len);
+
+ smb_set_enclen(buf_out, smb_len(buf) + NTLMSSP_SIG_SIZE, enc_ctx_num);
+
+ sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
+
+ status = ntlmssp_seal_packet(ntlmssp_state,
+ (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
+ data_len,
+ (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
+ data_len,
+ &sig);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ data_blob_free(&sig);
+ SAFE_FREE(buf_out);
+ return status;
+ }
+
+ /* First 16 data bytes are signature for SSPI compatibility. */
+ memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
+ *ppbuf_out = buf_out;
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ gss-api decrypt an incoming buffer. We insist that the size of the
+ unwrapped buffer must be smaller or identical to the incoming buffer.
+******************************************************************************/
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
+{
+ gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
+ OM_uint32 ret = 0;
+ OM_uint32 minor = 0;
+ int flags_got = 0;
+ gss_buffer_desc in_buf, out_buf;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+
+ if (buf_len < 8) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ in_buf.value = buf + 8;
+ in_buf.length = buf_len - 8;
+
+ ret = gss_unwrap(&minor,
+ gss_ctx,
+ &in_buf,
+ &out_buf,
+ &flags_got, /* did we get sign+seal ? */
+ (gss_qop_t *) NULL);
+
+ if (ret != GSS_S_COMPLETE) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
+ DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. Error %s\n",
+ ads_errstr(adss) ));
+ return map_nt_error_from_gss(ret, minor);
+ }
+
+ if (out_buf.length > in_buf.length) {
+ DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
+ (unsigned int)out_buf.length,
+ (unsigned int)in_buf.length ));
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ memcpy(buf + 8, out_buf.value, out_buf.length);
+ /* Reset the length and overwrite the header. */
+ smb_setlen(buf, out_buf.length + 4);
+
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ gss-api encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
+******************************************************************************/
+
+static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
+ uint16 enc_ctx_num,
+ char *buf,
+ char **ppbuf_out)
+{
+ gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
+ OM_uint32 ret = 0;
+ OM_uint32 minor = 0;
+ int flags_got = 0;
+ gss_buffer_desc in_buf, out_buf;
+ size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
+
+ *ppbuf_out = NULL;
+
+ if (buf_len < 8) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ in_buf.value = buf + 8;
+ in_buf.length = buf_len - 8;
+
+ ret = gss_wrap(&minor,
+ gss_ctx,
+ true, /* we want sign+seal. */
+ GSS_C_QOP_DEFAULT,
+ &in_buf,
+ &flags_got, /* did we get sign+seal ? */
+ &out_buf);
+
+ if (ret != GSS_S_COMPLETE) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, minor);
+ DEBUG(0,("common_gss_encrypt_buffer: gss_wrap failed. Error %s\n",
+ ads_errstr(adss) ));
+ return map_nt_error_from_gss(ret, minor);
+ }
+
+ if (!flags_got) {
+ /* Sign+seal not supported. */
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ /* Ya see - this is why I *hate* gss-api. I don't
+ * want to have to malloc another buffer of the
+ * same size + 8 bytes just to get a continuous
+ * header + buffer, but gss won't let me pass in
+ * a pre-allocated buffer. Bastards (and you know
+ * who you are....). I might fix this by
+ * going to "encrypt_and_send" passing in a file
+ * descriptor and doing scatter-gather write with
+ * TCP cork on Linux. But I shouldn't have to
+ * bother :-*(. JRA.
+ */
+
+ *ppbuf_out = (char *)SMB_MALLOC(out_buf.length + 8); /* We know this can't wrap. */
+ if (!*ppbuf_out) {
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
+ smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
+
+ gss_release_buffer(&minor, &out_buf);
+ return NT_STATUS_OK;
+}
+#endif
+
+/******************************************************************************
+ Generic code for client and server.
+ Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
+{
+ if (!common_encryption_on(es)) {
+ /* Not encrypting. */
+ *buf_out = buffer;
+ return NT_STATUS_OK;
+ }
+
+ switch (es->smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ return common_ntlm_encrypt_buffer(es->s.ntlmssp_state, es->enc_ctx_num, buffer, buf_out);
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ return common_gss_encrypt_buffer(es->s.gss_state, es->enc_ctx_num, buffer, buf_out);
+#endif
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+}
+
+/******************************************************************************
+ Generic code for client and server.
+ Decrypt an incoming SMB buffer. Replaces the data within it.
+ New data must be less than or equal to the current length.
+******************************************************************************/
+
+NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
+{
+ if (!common_encryption_on(es)) {
+ /* Not decrypting. */
+ return NT_STATUS_OK;
+ }
+
+ switch (es->smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ return common_ntlm_decrypt_buffer(es->s.ntlmssp_state, buf);
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ return common_gss_decrypt_buffer(es->s.gss_state, buf);
+#endif
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+}
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+/******************************************************************************
+ Shutdown a gss encryption state.
+******************************************************************************/
+
+static void common_free_gss_state(struct smb_tran_enc_state_gss **pp_gss_state)
+{
+ OM_uint32 minor = 0;
+ struct smb_tran_enc_state_gss *gss_state = *pp_gss_state;
+
+ if (gss_state->creds != GSS_C_NO_CREDENTIAL) {
+ gss_release_cred(&minor, &gss_state->creds);
+ }
+ if (gss_state->gss_ctx != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(&minor, &gss_state->gss_ctx, NULL);
+ }
+ SAFE_FREE(*pp_gss_state);
+}
+#endif
+
+/******************************************************************************
+ Shutdown an encryption state.
+******************************************************************************/
+
+void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
+{
+ struct smb_trans_enc_state *es = *pp_es;
+
+ if (es == NULL) {
+ return;
+ }
+
+ if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ if (es->s.ntlmssp_state) {
+ ntlmssp_end(&es->s.ntlmssp_state);
+ }
+ }
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
+ /* Free the gss context handle. */
+ if (es->s.gss_state) {
+ common_free_gss_state(&es->s.gss_state);
+ }
+ }
+#endif
+ SAFE_FREE(es);
+ *pp_es = NULL;
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
+{
+ if (!common_encryption_on(es)) {
+ return;
+ }
+
+ if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ SAFE_FREE(buf);
+ return;
+ }
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (es->smb_enc_type == SMB_TRANS_ENC_GSS) {
+ OM_uint32 min;
+ gss_buffer_desc rel_buf;
+ rel_buf.value = buf;
+ rel_buf.length = smb_len(buf) + 4;
+ gss_release_buffer(&min, &rel_buf);
+ }
+#endif
+}
+
+/******************************************************************************
+ Client side encryption.
+******************************************************************************/
+
+/******************************************************************************
+ Is client encryption on ?
+******************************************************************************/
+
+bool cli_encryption_on(struct cli_state *cli)
+{
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ return common_encryption_on(cli->trans_enc_state);
+}
+
+/******************************************************************************
+ Shutdown a client encryption state.
+******************************************************************************/
+
+void cli_free_encryption_context(struct cli_state *cli)
+{
+ common_free_encryption_state(&cli->trans_enc_state);
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void cli_free_enc_buffer(struct cli_state *cli, char *buf)
+{
+ /* We know this is an smb buffer, and we
+ * didn't malloc, only copy, for a keepalive,
+ * so ignore non-session messages. */
+
+ if(CVAL(buf,0)) {
+ return;
+ }
+
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ common_free_enc_buffer(cli->trans_enc_state, buf);
+}
+
+/******************************************************************************
+ Decrypt an incoming buffer.
+******************************************************************************/
+
+NTSTATUS cli_decrypt_message(struct cli_state *cli)
+{
+ NTSTATUS status;
+ uint16 enc_ctx_num;
+
+ /* Ignore non-session messages. */
+ if(CVAL(cli->inbuf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ status = get_enc_ctx_num((const uint8_t *)cli->inbuf, &enc_ctx_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ return common_decrypt_buffer(cli->trans_enc_state, cli->inbuf);
+}
+
+/******************************************************************************
+ Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
+{
+ /* Ignore non-session messages. */
+ if(CVAL(cli->outbuf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ /* If we supported multiple encrytion contexts
+ * here we'd look up based on tid.
+ */
+ return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
+}
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index d5cbe3b125..f03c21bd0e 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -745,8 +745,8 @@ bool srv_oplock_set_signing(bool onoff)
bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
{
- /* Check if it's a session keepalive. */
- if(CVAL(inbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(inbuf,0)) {
return True;
}
@@ -759,8 +759,8 @@ bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
void srv_calculate_sign_mac(char *outbuf)
{
- /* Check if it's a session keepalive. */
- if(CVAL(outbuf,0) == SMBkeepalive) {
+ /* Check if it's a non-session message. */
+ if(CVAL(outbuf,0)) {
return;
}
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 9e37d1d6cf..d7f6f604f7 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -704,16 +704,22 @@ char *decrypt_trustdom_secret(const char *pass, DATA_BLOB *data_in)
void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
const char *pwd,
DATA_BLOB *session_key,
- struct wkssvc_PasswordBuffer *pwd_buf)
+ struct wkssvc_PasswordBuffer **pwd_buf)
{
uint8_t buffer[516];
struct MD5Context ctx;
-
- DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
-
+ struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
+ DATA_BLOB confounded_session_key;
int confounder_len = 8;
uint8_t confounder[8];
+ my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
+ if (!my_pwd_buf) {
+ return;
+ }
+
+ confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
+
encode_pw_buffer(buffer, pwd, STR_UNICODE);
generate_random_buffer((uint8_t *)confounder, confounder_len);
@@ -725,10 +731,12 @@ void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
SamOEMhashBlob(buffer, 516, &confounded_session_key);
- memcpy(&pwd_buf->data[0], confounder, confounder_len);
- memcpy(&pwd_buf->data[8], buffer, 516);
+ memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
+ memcpy(&my_pwd_buf->data[8], buffer, 516);
data_blob_free(&confounded_session_key);
+
+ *pwd_buf = my_pwd_buf;
}
WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index dab21e53b3..270c6d2261 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -608,7 +608,10 @@ static bool parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
for (i = 0; i < lck->num_share_modes; i++) {
struct share_mode_entry *entry_p = &lck->share_modes[i];
- char *str = share_mode_str(NULL, i, entry_p);
+ char *str = NULL;
+ if (DEBUGLEVEL >= 10) {
+ str = share_mode_str(NULL, i, entry_p);
+ }
DEBUG(10,("parse_share_modes: %s\n",
str ? str : ""));
if (!process_exists(entry_p->pid)) {
diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c
index 70bb6a02e8..6d2972d8ed 100644
--- a/source3/modules/nfs4_acls.c
+++ b/source3/modules/nfs4_acls.c
@@ -309,7 +309,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
}
DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n",
- sec_desc_size(*ppdesc)));
+ ndr_size_security_descriptor(*ppdesc, 0)));
return NT_STATUS_OK;
}
diff --git a/source3/modules/vfs_solarisacl.c b/source3/modules/vfs_solarisacl.c
index 673b6805af..cda243f8c1 100644
--- a/source3/modules/vfs_solarisacl.c
+++ b/source3/modules/vfs_solarisacl.c
@@ -264,8 +264,8 @@ int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
}
done:
- DEBUG(10, ("solarisacl_sys_acl_st_fd %s.\n",
- ((ret == 0) ? "succeded" : "failed" )));
+ DEBUG(10, ("solarisacl_sys_acl_set_fd %s.\n",
+ ((ret == 0) ? "succeeded" : "failed" )));
SAFE_FREE(solaris_acl);
SAFE_FREE(default_acl);
return ret;
diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c
index bafe87c044..b50d215b91 100644
--- a/source3/nmbd/nmbd_elections.c
+++ b/source3/nmbd/nmbd_elections.c
@@ -336,7 +336,9 @@ bool check_elections(void)
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
for (work = subrec->workgrouplist; work; work = work->next) {
- run_any_election |= work->RunningElection;
+ if (work->RunningElection) {
+ run_any_election = work->RunningElection;
+ }
/*
* Start an election if we have any chance of winning.
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index 349d36ce70..c1d373aa18 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -1613,6 +1613,8 @@ void retransmit_or_expire_response_records(time_t t)
for (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) {
struct response_record *rrec, *nextrrec;
+ restart:
+
for (rrec = subrec->responselist; rrec; rrec = nextrrec) {
nextrrec = rrec->next;
@@ -1651,6 +1653,9 @@ on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_
no timeout function. */
remove_response_record(subrec, rrec);
}
+ /* We have changed subrec->responselist,
+ * restart from the beginning of this list. */
+ goto restart;
} /* !rrec->in_expitation_processing */
} /* rrec->repeat_count > 0 */
} /* rrec->repeat_time <= t */
@@ -1924,7 +1929,7 @@ bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len,
return false;
}
- set_message(ptr,17,strlen(mailslot) + 1 + len,True);
+ cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
SCVAL(ptr,smb_com,SMBtrans);
diff --git a/source3/nmbd/nmbd_responserecordsdb.c b/source3/nmbd/nmbd_responserecordsdb.c
index 22a038ef2e..6498ce04cf 100644
--- a/source3/nmbd/nmbd_responserecordsdb.c
+++ b/source3/nmbd/nmbd_responserecordsdb.c
@@ -31,26 +31,12 @@ int num_response_packets = 0;
static void add_response_record(struct subnet_record *subrec,
struct response_record *rrec)
{
- struct response_record *rrec2;
-
num_response_packets++; /* count of total number of packets still around */
DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
rrec->response_id, subrec->subnet_name, num_response_packets));
- if (!subrec->responselist) {
- subrec->responselist = rrec;
- rrec->prev = NULL;
- rrec->next = NULL;
- return;
- }
-
- for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next)
- ;
-
- rrec2->next = rrec;
- rrec->next = NULL;
- rrec->prev = rrec2;
+ DLIST_ADD_END(subrec->responselist, rrec, struct response_record *);
}
/***************************************************************************
@@ -60,13 +46,7 @@ static void add_response_record(struct subnet_record *subrec,
void remove_response_record(struct subnet_record *subrec,
struct response_record *rrec)
{
- if (rrec->prev)
- rrec->prev->next = rrec->next;
- if (rrec->next)
- rrec->next->prev = rrec->prev;
-
- if (subrec->responselist == rrec)
- subrec->responselist = rrec->next;
+ DLIST_REMOVE(subrec->responselist, rrec);
if(rrec->userdata) {
if(rrec->userdata->free_fn) {
diff --git a/source3/nsswitch/libwbclient/wbc_pam.c b/source3/nsswitch/libwbclient/wbc_pam.c
index 1548c3344a..7f7c7b8140 100644
--- a/source3/nsswitch/libwbclient/wbc_pam.c
+++ b/source3/nsswitch/libwbclient/wbc_pam.c
@@ -31,7 +31,7 @@
* @return #wbcErr
**/
-wbcErr wbcAuthenticateUser(const char *username,
+wbcErr wbcAuthenticateUser(const char *username,
const char *password)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
@@ -61,5 +61,5 @@ wbcErr wbcAuthenticateUser(const char *username,
BAIL_ON_WBC_ERROR(wbc_status);
done:
- return wbc_status;
+ return wbc_status;
}
diff --git a/source3/nsswitch/libwbclient/wbc_pwd.c b/source3/nsswitch/libwbclient/wbc_pwd.c
index 4e3b0d3967..b24e198bc5 100644
--- a/source3/nsswitch/libwbclient/wbc_pwd.c
+++ b/source3/nsswitch/libwbclient/wbc_pwd.c
@@ -228,13 +228,14 @@ wbcErr wbcGetgrnam(const char *name, struct group **grp)
&response);
BAIL_ON_WBC_ERROR(wbc_status);
- *grp = copy_group_entry(&response.data.gr, response.extra_data.data);
+ *grp = copy_group_entry(&response.data.gr,
+ (char*)response.extra_data.data);
BAIL_ON_PTR_ERROR(*grp, wbc_status);
done:
if (response.extra_data.data)
free(response.extra_data.data);
-
+
return wbc_status;
}
@@ -270,7 +271,8 @@ wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
&response);
BAIL_ON_WBC_ERROR(wbc_status);
- *grp = copy_group_entry(&response.data.gr, response.extra_data.data);
+ *grp = copy_group_entry(&response.data.gr,
+ (char*)response.extra_data.data);
BAIL_ON_PTR_ERROR(*grp, wbc_status);
done:
diff --git a/source3/nsswitch/libwbclient/wbc_sid.c b/source3/nsswitch/libwbclient/wbc_sid.c
index c877e1d9d4..abe1457cc1 100644
--- a/source3/nsswitch/libwbclient/wbc_sid.c
+++ b/source3/nsswitch/libwbclient/wbc_sid.c
@@ -265,12 +265,12 @@ wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
/* Copy out result */
if (domain != NULL) {
- *domain = strdup(response.data.name.dom_name);
+ *domain = talloc_strdup(NULL, response.data.name.dom_name);
BAIL_ON_PTR_ERROR((*domain), wbc_status);
}
if (name != NULL) {
- *name = strdup(response.data.name.name);
+ *name = talloc_strdup(NULL, response.data.name.name);
BAIL_ON_PTR_ERROR((*name), wbc_status);
}
@@ -283,9 +283,9 @@ wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
done:
if (!WBC_ERROR_IS_OK(wbc_status)) {
if (*domain)
- free(*domain);
+ talloc_free(*domain);
if (*name)
- free(*name);
+ talloc_free(*name);
}
return wbc_status;
@@ -334,11 +334,9 @@ wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
ridbuf_size = (sizeof(char)*11) * num_rids + 1;
- ridlist = malloc(ridbuf_size);
+ ridlist = talloc_zero_array(NULL, char, ridbuf_size);
BAIL_ON_PTR_ERROR(ridlist, wbc_status);
- memset(ridlist, 0x0, ridbuf_size);
-
len = 0;
for (i=0; i<num_rids && (len-1)>0; i++) {
char ridstr[12];
@@ -356,15 +354,15 @@ wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS,
&request,
&response);
- free(ridlist);
+ talloc_free(ridlist);
- domain_name = strdup(response.data.domain_name);
+ domain_name = talloc_strdup(NULL, response.data.domain_name);
BAIL_ON_PTR_ERROR(domain_name, wbc_status);
- *names = (const char**)malloc(sizeof(char*) * num_rids);
+ *names = talloc_array(NULL, const char*, num_rids);
BAIL_ON_PTR_ERROR((*names), wbc_status);
- *types = (enum wbcSidType*)malloc(sizeof(enum wbcSidType) * num_rids);
+ *types = talloc_array(NULL, enum wbcSidType, num_rids);
BAIL_ON_PTR_ERROR((*types), wbc_status);
p = (char *)response.extra_data.data;
@@ -393,7 +391,8 @@ wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
*q = '\0';
- (*names)[i] = strdup(p);
+ (*names)[i] = talloc_strdup((*names), p);
+ BAIL_ON_PTR_ERROR(((*names)[i]), wbc_status);
p = q+1;
}
@@ -403,18 +402,20 @@ wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
BAIL_ON_WBC_ERROR(wbc_status);
}
- free(response.extra_data.data);
-
wbc_status = WBC_ERR_SUCCESS;
done:
+ if (response.extra_data.data) {
+ free(response.extra_data.data);
+ }
+
if (!WBC_ERROR_IS_OK(wbc_status)) {
if (domain_name)
- free(domain_name);
+ talloc_free(domain_name);
if (*names)
- free(*names);
+ talloc_free(*names);
if (*types)
- free(*types);
+ talloc_free(*types);
} else {
*pp_domain_name = domain_name;
}
diff --git a/source3/nsswitch/libwbclient/wbc_util.c b/source3/nsswitch/libwbclient/wbc_util.c
index c6acb27e55..ff3cec8689 100644
--- a/source3/nsswitch/libwbclient/wbc_util.c
+++ b/source3/nsswitch/libwbclient/wbc_util.c
@@ -51,10 +51,6 @@ wbcErr wbcPing(void)
*
* @return #wbcErr
*
- * The char* members of the struct wbcDomainInfo* are malloc()'d
- * and it the the responsibility of the caller to free the members
- * before discarding the struct.
- *
**/
@@ -64,7 +60,7 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
struct winbindd_response response;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct wbcDomainInfo *info = NULL;
-
+
if (!domain || !dinfo) {
wbc_status = WBC_ERR_INVALID_PARAM;
BAIL_ON_WBC_ERROR(wbc_status);
@@ -75,7 +71,7 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- strncpy(request.domain_name, domain,
+ strncpy(request.domain_name, domain,
sizeof(request.domain_name)-1);
wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO,
@@ -86,15 +82,15 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
info = talloc(NULL, struct wbcDomainInfo);
BAIL_ON_PTR_ERROR(info, wbc_status);
- info->short_name = talloc_strdup(info,
+ info->short_name = talloc_strdup(info,
response.data.domain_info.name);
BAIL_ON_PTR_ERROR(info->short_name, wbc_status);
- info->dns_name = talloc_strdup(info,
+ info->dns_name = talloc_strdup(info,
response.data.domain_info.alt_name);
BAIL_ON_PTR_ERROR(info->dns_name, wbc_status);
- wbc_status = wbcStringToSid(response.data.domain_info.sid,
+ wbc_status = wbcStringToSid(response.data.domain_info.sid,
&info->sid);
BAIL_ON_WBC_ERROR(wbc_status);
@@ -106,7 +102,7 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
info->flags |= WBC_DOMINFO_PRIMARY;
*dinfo = info;
-
+
wbc_status = WBC_ERR_SUCCESS;
done:
diff --git a/source3/nsswitch/libwbclient/wbclient.h b/source3/nsswitch/libwbclient/wbclient.h
index 2867aad69e..6b85d7e8b3 100644
--- a/source3/nsswitch/libwbclient/wbclient.h
+++ b/source3/nsswitch/libwbclient/wbclient.h
@@ -177,7 +177,7 @@ wbcErr wbcDomainSequenceNumbers(void);
* Athenticate functions
*/
-wbcErr wbcAuthenticateUser(const char *username,
+wbcErr wbcAuthenticateUser(const char *username,
const char *password);
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 5b009fc964..29166cf02e 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -472,6 +472,7 @@ typedef struct {
int iAioWriteSize;
int iMap_readonly;
int iDirectoryNameCacheSize;
+ int ismb_encrypt;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -617,6 +618,7 @@ static service sDefault = {
#else
100, /* iDirectoryNameCacheSize */
#endif
+ Auto, /* ismb_encrypt */
NULL, /* Parametric options */
"" /* dummy */
@@ -1027,6 +1029,7 @@ static struct parm_struct parm_table[] = {
{"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_ADVANCED},
{"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
{"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
+ {"smb encrypt", P_ENUM, P_LOCAL, &sDefault.ismb_encrypt, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
{"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED},
{"client ldap sasl wrapping", P_ENUM, P_GLOBAL, &Globals.client_ldap_sasl_wrapping, NULL, enum_ldap_sasl_wrapping, FLAG_ADVANCED},
{"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED},
@@ -2173,6 +2176,7 @@ FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
+FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
@@ -6218,7 +6222,9 @@ bool lp_use_sendfile(int snum)
if (Protocol < PROTOCOL_NT1) {
return False;
}
- return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && !srv_is_signing_active());
+ return (_lp_use_sendfile(snum) &&
+ (get_remote_arch() != RA_WIN95) &&
+ !srv_is_signing_active());
}
/*******************************************************************
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 198960550b..0ab45bafc3 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -25,10 +25,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
-/* Cache of latest SAM lookup query */
-
-static struct samu *csamuser = NULL;
-
static_decl_pdb;
static struct pdb_init_function_entry *backends = NULL;
@@ -208,55 +204,32 @@ static struct pdb_methods *pdb_get_methods(void)
return pdb_get_methods_reload(False);
}
-/******************************************************************
- Backward compatibility functions for the original passdb interface
-*******************************************************************/
-
-bool pdb_setsampwent(bool update, uint16 acb_mask)
-{
- struct pdb_methods *pdb = pdb_get_methods();
- return NT_STATUS_IS_OK(pdb->setsampwent(pdb, update, acb_mask));
-}
-
-void pdb_endsampwent(void)
-{
- struct pdb_methods *pdb = pdb_get_methods();
- pdb->endsampwent(pdb);
-}
-
-bool pdb_getsampwent(struct samu *user)
-{
- struct pdb_methods *pdb = pdb_get_methods();
-
- if ( !NT_STATUS_IS_OK(pdb->getsampwent(pdb, user) ) ) {
- return False;
- }
-
- return True;
-}
-
bool pdb_getsampwnam(struct samu *sam_acct, const char *username)
{
struct pdb_methods *pdb = pdb_get_methods();
+ struct samu *cache_copy;
+ const struct dom_sid *user_sid;
if (!NT_STATUS_IS_OK(pdb->getsampwnam(pdb, sam_acct, username))) {
return False;
}
- if ( csamuser ) {
- TALLOC_FREE(csamuser);
- }
-
- csamuser = samu_new( NULL );
- if (!csamuser) {
+ cache_copy = samu_new(NULL);
+ if (cache_copy == NULL) {
return False;
}
- if (!pdb_copy_sam_account(csamuser, sam_acct)) {
- TALLOC_FREE(csamuser);
+ if (!pdb_copy_sam_account(cache_copy, sam_acct)) {
+ TALLOC_FREE(cache_copy);
return False;
}
+ user_sid = pdb_get_user_sid(cache_copy);
+
+ memcache_add_talloc(NULL, PDB_GETPWSID_CACHE,
+ data_blob_const(user_sid, sizeof(*user_sid)),
+ cache_copy);
+
return True;
}
@@ -289,6 +262,7 @@ bool pdb_getsampwsid(struct samu *sam_acct, const DOM_SID *sid)
{
struct pdb_methods *pdb = pdb_get_methods();
uint32 rid;
+ void *cache_data;
/* hard code the Guest RID of 501 */
@@ -301,9 +275,16 @@ bool pdb_getsampwsid(struct samu *sam_acct, const DOM_SID *sid)
}
/* check the cache first */
-
- if ( csamuser && sid_equal(sid, pdb_get_user_sid(csamuser) ) )
- return pdb_copy_sam_account(sam_acct, csamuser);
+
+ cache_data = memcache_lookup_talloc(
+ NULL, PDB_GETPWSID_CACHE, data_blob_const(sid, sizeof(*sid)));
+
+ if (cache_data != NULL) {
+ struct samu *cache_copy = talloc_get_type_abort(
+ cache_data, struct samu);
+
+ return pdb_copy_sam_account(sam_acct, cache_copy);
+ }
return NT_STATUS_IS_OK(pdb->getsampwsid(pdb, sam_acct, sid));
}
@@ -498,10 +479,7 @@ NTSTATUS pdb_update_sam_account(struct samu *sam_acct)
{
struct pdb_methods *pdb = pdb_get_methods();
- if (csamuser != NULL) {
- TALLOC_FREE(csamuser);
- csamuser = NULL;
- }
+ memcache_flush(NULL, PDB_GETPWSID_CACHE);
return pdb->update_sam_account(pdb, sam_acct);
}
@@ -510,10 +488,7 @@ NTSTATUS pdb_delete_sam_account(struct samu *sam_acct)
{
struct pdb_methods *pdb = pdb_get_methods();
- if (csamuser != NULL) {
- TALLOC_FREE(csamuser);
- csamuser = NULL;
- }
+ memcache_flush(NULL, PDB_GETPWSID_CACHE);
return pdb->delete_sam_account(pdb, sam_acct);
}
@@ -524,10 +499,7 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
uid_t uid;
NTSTATUS status;
- if (csamuser != NULL) {
- TALLOC_FREE(csamuser);
- csamuser = NULL;
- }
+ memcache_flush(NULL, PDB_GETPWSID_CACHE);
/* sanity check to make sure we don't rename root */
@@ -1181,21 +1153,6 @@ static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods,
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, bool update, uint32 acb_mask)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, struct samu *user)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-static void pdb_default_endsampwent(struct pdb_methods *methods)
-{
- return; /* NT_STATUS_NOT_IMPLEMENTED; */
-}
-
static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
{
return account_policy_get(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
@@ -1738,7 +1695,7 @@ static NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
}
#endif
-static struct pdb_search *pdb_search_init(enum pdb_search_type type)
+struct pdb_search *pdb_search_init(enum pdb_search_type type)
{
TALLOC_CTX *mem_ctx;
struct pdb_search *result;
@@ -1795,81 +1752,6 @@ static void fill_displayentry(TALLOC_CTX *mem_ctx, uint32 rid,
entry->description = "";
}
-static bool user_search_in_progress = False;
-struct user_search {
- uint16 acct_flags;
-};
-
-static bool next_entry_users(struct pdb_search *s,
- struct samr_displayentry *entry)
-{
- struct user_search *state = (struct user_search *)s->private_data;
- struct samu *user = NULL;
-
- next:
- if ( !(user = samu_new( NULL )) ) {
- DEBUG(0, ("next_entry_users: samu_new() failed!\n"));
- return False;
- }
-
- if (!pdb_getsampwent(user)) {
- TALLOC_FREE(user);
- return False;
- }
-
- if ((state->acct_flags != 0) &&
- ((pdb_get_acct_ctrl(user) & state->acct_flags) == 0)) {
- TALLOC_FREE(user);
- goto next;
- }
-
- fill_displayentry(s->mem_ctx, pdb_get_user_rid(user),
- pdb_get_acct_ctrl(user), pdb_get_username(user),
- pdb_get_fullname(user), pdb_get_acct_desc(user),
- entry);
-
- TALLOC_FREE(user);
- return True;
-}
-
-static void search_end_users(struct pdb_search *search)
-{
- pdb_endsampwent();
- user_search_in_progress = False;
-}
-
-static bool pdb_default_search_users(struct pdb_methods *methods,
- struct pdb_search *search,
- uint32 acct_flags)
-{
- struct user_search *state;
-
- if (user_search_in_progress) {
- DEBUG(1, ("user search in progress\n"));
- return False;
- }
-
- if (!pdb_setsampwent(False, acct_flags)) {
- DEBUG(5, ("Could not start search\n"));
- return False;
- }
-
- user_search_in_progress = True;
-
- state = TALLOC_P(search->mem_ctx, struct user_search);
- if (state == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return False;
- }
-
- state->acct_flags = acct_flags;
-
- search->private_data = state;
- search->next_entry = next_entry_users;
- search->search_end = search_end_users;
- return True;
-}
-
struct group_search {
GROUP_MAP *groups;
size_t num_groups, current_group;
@@ -2136,9 +2018,6 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
return NT_STATUS_NO_MEMORY;
}
- (*methods)->setsampwent = pdb_default_setsampwent;
- (*methods)->endsampwent = pdb_default_endsampwent;
- (*methods)->getsampwent = pdb_default_getsampwent;
(*methods)->getsampwnam = pdb_default_getsampwnam;
(*methods)->getsampwsid = pdb_default_getsampwsid;
(*methods)->create_user = pdb_default_create_user;
@@ -2180,7 +2059,6 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
(*methods)->gid_to_sid = pdb_default_gid_to_sid;
(*methods)->sid_to_id = pdb_default_sid_to_id;
- (*methods)->search_users = pdb_default_search_users;
(*methods)->search_groups = pdb_default_search_groups;
(*methods)->search_aliases = pdb_default_search_aliases;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index bc912ada29..205b178a93 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -1454,79 +1454,6 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
}
/**********************************************************************
- Connect to LDAP server for password enumeration.
-*********************************************************************/
-
-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, bool update, uint32 acb_mask)
-{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
- int rc;
- char *filter = NULL;
- const char *suffix;
- const char **attr_list;
- bool machine_mask = False, user_mask = False;
- NTSTATUS status = NT_STATUS_OK;
- TALLOC_CTX *ctx = talloc_init("ldapsam_setsampwent");
-
- if (!ctx) {
- return NT_STATUS_NO_MEMORY;
- }
- filter = talloc_asprintf(ctx, "(&%s%s)", "(uid=%u)",
- get_objclass_filter(ldap_state->schema_ver));
- if (!filter) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
- filter = talloc_all_string_sub(ctx, filter, "%u", "*");
- if (!filter) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
- machine_mask = ((acb_mask != 0) && (acb_mask & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)));
- user_mask = ((acb_mask != 0) && (acb_mask & ACB_NORMAL));
-
- if (machine_mask) {
- suffix = lp_ldap_machine_suffix();
- } else if (user_mask) {
- suffix = lp_ldap_user_suffix();
- } else {
- suffix = lp_ldap_suffix();
- }
-
- DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n",
- acb_mask, suffix));
-
- attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
- rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter,
- attr_list, 0, &ldap_state->result);
- TALLOC_FREE( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
- DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", suffix, filter));
- ldap_msgfree(ldap_state->result);
- ldap_state->result = NULL;
- status = NT_STATUS_UNSUCCESSFUL;
- goto out;
- }
-
- DEBUG(2, ("ldapsam_setsampwent: %d entries in the base %s\n",
- ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
- ldap_state->result), suffix));
-
- ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->result);
- ldap_state->index = 0;
-
- out:
-
- TALLOC_FREE(ctx);
- return status;
-}
-
-/**********************************************************************
End enumeration of the LDAP password list.
*********************************************************************/
@@ -1539,32 +1466,6 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
}
}
-/**********************************************************************
-Get the next entry in the LDAP password database.
-*********************************************************************/
-
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
- struct samu *user)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state =
- (struct ldapsam_privates *)my_methods->private_data;
- bool bret = False;
-
- while (!bret) {
- if (!ldap_state->entry)
- return ret;
-
- ldap_state->index++;
- bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
-
- ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
- ldap_state->entry);
- }
-
- return NT_STATUS_OK;
-}
-
static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
const char *new_attr)
{
@@ -1867,6 +1768,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
SAFE_FREE(ld_error);
ber_bvfree(bv);
+#if defined(LDAP_CONSTRAINT_VIOLATION)
+ if (rc == LDAP_CONSTRAINT_VIOLATION)
+ return NT_STATUS_PASSWORD_RESTRICTION;
+#endif
return NT_STATUS_UNSUCCESSFUL;
} else {
DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
@@ -6172,9 +6077,6 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
(*pdb_method)->name = "ldapsam";
- (*pdb_method)->setsampwent = ldapsam_setsampwent;
- (*pdb_method)->endsampwent = ldapsam_endsampwent;
- (*pdb_method)->getsampwent = ldapsam_getsampwent;
(*pdb_method)->getsampwnam = ldapsam_getsampwnam;
(*pdb_method)->getsampwsid = ldapsam_getsampwsid;
(*pdb_method)->add_sam_account = ldapsam_add_sam_account;
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 6a3bdb80a2..6cf54fbdf6 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -1264,79 +1264,6 @@ static bool build_sam_account(struct smbpasswd_privates *smbpasswd_state,
Functions to be implemented by the new passdb API
****************************************************************/
-static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, bool update, uint32 acb_mask)
-{
- struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
-
- smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
- update ? PWF_UPDATE : PWF_READ,
- &(smbpasswd_state->pw_file_lock_depth));
-
- /* did we fail? Should we try to create it? */
- if (!smbpasswd_state->pw_file && update && errno == ENOENT) {
- FILE *fp;
- /* slprintf(msg_str,msg_str_len-1,
- "smbpasswd file did not exist - attempting to create it.\n"); */
- DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
- fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
- if (fp) {
- fprintf(fp, "# Samba SMB password file\n");
- fclose(fp);
- }
-
- smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
- update ? PWF_UPDATE : PWF_READ,
- &(smbpasswd_state->pw_file_lock_depth));
- }
-
- if (smbpasswd_state->pw_file != NULL)
- return NT_STATUS_OK;
- else
- return NT_STATUS_UNSUCCESSFUL;
-}
-
-static void smbpasswd_endsampwent (struct pdb_methods *my_methods)
-{
- struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
- endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));
-}
-
-/*****************************************************************
- ****************************************************************/
-
-static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, struct samu *user)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
- struct smb_passwd *pw_buf=NULL;
- bool done = False;
-
- DEBUG(5,("pdb_getsampwent\n"));
-
- if ( !user ) {
- DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
- return nt_status;
- }
-
- while (!done) {
- /* do we have an entry? */
- pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
- if (pw_buf == NULL)
- return nt_status;
-
- /* build the struct samu entry from the smb_passwd struct.
- We loop in case the user in the pdb does not exist in
- the local system password file */
- if (build_sam_account(smbpasswd_state, user, pw_buf))
- done = True;
- }
-
- DEBUG(5,("getsampwent (smbpasswd): done\n"));
-
- /* success */
- return NT_STATUS_OK;
-}
-
/****************************************************************
Search smbpasswd file by iterating over the entries. Do not
call getpwnam() for unix account information until we have found
@@ -1606,6 +1533,119 @@ static void free_private_data(void **vp)
/* No need to free any further, as it is talloc()ed */
}
+struct smbpasswd_search_state {
+ uint32_t acct_flags;
+
+ struct samr_displayentry *entries;
+ uint32_t num_entries;
+ ssize_t array_size;
+ uint32_t current;
+};
+
+static void smbpasswd_search_end(struct pdb_search *search)
+{
+ struct smbpasswd_search_state *state = talloc_get_type_abort(
+ search->private_data, struct smbpasswd_search_state);
+ TALLOC_FREE(state);
+}
+
+static bool smbpasswd_search_next_entry(struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct smbpasswd_search_state *state = talloc_get_type_abort(
+ search->private_data, struct smbpasswd_search_state);
+
+ if (state->current == state->num_entries) {
+ return false;
+ }
+
+ *entry = state->entries[state->current++];
+
+ return true;
+}
+
+static bool smbpasswd_search_users(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint32_t acct_flags)
+{
+ struct smbpasswd_privates *smbpasswd_state =
+ (struct smbpasswd_privates*)methods->private_data;
+
+ struct smbpasswd_search_state *search_state;
+ struct smb_passwd *pwd;
+ FILE *fp;
+
+ search_state = TALLOC_ZERO_P(search->mem_ctx,
+ struct smbpasswd_search_state);
+ if (search_state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return false;
+ }
+ search_state->acct_flags = acct_flags;
+
+ fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ,
+ &smbpasswd_state->pw_file_lock_depth);
+
+ if (fp == NULL) {
+ DEBUG(10, ("Unable to open smbpasswd file.\n"));
+ TALLOC_FREE(search_state);
+ return false;
+ }
+
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+ struct samr_displayentry entry;
+ struct samu *user;
+
+ if ((acct_flags != 0)
+ && ((acct_flags & pwd->acct_ctrl) == 0)) {
+ continue;
+ }
+
+ user = samu_new(talloc_tos());
+ if (user == NULL) {
+ DEBUG(0, ("samu_new failed\n"));
+ break;
+ }
+
+ if (!build_sam_account(smbpasswd_state, user, pwd)) {
+ /* Already got debug msgs... */
+ break;
+ }
+
+ ZERO_STRUCT(entry);
+
+ entry.acct_flags = pdb_get_acct_ctrl(user);
+ sid_peek_rid(pdb_get_user_sid(user), &entry.rid);
+ entry.account_name = talloc_strdup(
+ search_state, pdb_get_username(user));
+ entry.fullname = talloc_strdup(
+ search_state, pdb_get_fullname(user));
+ entry.description = talloc_strdup(
+ search_state, pdb_get_acct_desc(user));
+
+ TALLOC_FREE(user);
+
+ if ((entry.account_name == NULL) || (entry.fullname == NULL)
+ || (entry.description == NULL)) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ break;
+ }
+
+ ADD_TO_LARGE_ARRAY(search_state, struct samr_displayentry,
+ entry, &search_state->entries,
+ &search_state->num_entries,
+ &search_state->array_size);
+ }
+
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
+
+ search->private_data = search_state;
+ search->next_entry = smbpasswd_search_next_entry;
+ search->search_end = smbpasswd_search_end;
+
+ return true;
+}
+
static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char *location )
{
NTSTATUS nt_status;
@@ -1617,15 +1657,13 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char
(*pdb_method)->name = "smbpasswd";
- (*pdb_method)->setsampwent = smbpasswd_setsampwent;
- (*pdb_method)->endsampwent = smbpasswd_endsampwent;
- (*pdb_method)->getsampwent = smbpasswd_getsampwent;
(*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
(*pdb_method)->getsampwsid = smbpasswd_getsampwsid;
(*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
(*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
(*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
(*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
+ (*pdb_method)->search_users = smbpasswd_search_users;
(*pdb_method)->rid_algorithm = smbpasswd_rid_algorithm;
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index b4282b1278..5ee1cdc0c0 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -44,13 +44,6 @@ static int tdbsam_debug_level = DBGC_ALL;
#define RIDPREFIX "RID_"
#define PRIVPREFIX "PRIV_"
-struct pwent_list {
- struct pwent_list *prev, *next;
- TDB_DATA key;
-};
-static struct pwent_list *tdbsam_pwent_list;
-static bool pwent_initialized;
-
/* GLOBAL TDB SAM CONTEXT */
static TDB_CONTEXT *tdbsam;
@@ -891,134 +884,6 @@ void tdbsam_close( void )
return;
}
-/****************************************************************************
- creates a list of user keys
-****************************************************************************/
-
-static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
-{
- const char *prefix = USERPREFIX;
- int prefixlen = strlen (prefix);
- struct pwent_list *ptr;
-
- if ( strncmp((const char *)key.dptr, prefix, prefixlen) == 0 ) {
- if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
- DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
-
- /* just return 0 and let the traversal continue */
- return 0;
- }
- ZERO_STRUCTP(ptr);
-
- /* save a copy of the key */
-
- ptr->key.dptr = (uint8 *)memdup( key.dptr, key.dsize );
- if (!ptr->key.dptr) {
- DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
- /* just return 0 and let the traversal continue */
- SAFE_FREE(ptr);
- return 0;
- }
-
- ptr->key.dsize = key.dsize;
-
- DLIST_ADD( tdbsam_pwent_list, ptr );
-
- }
-
- return 0;
-}
-
-/***************************************************************
- Open the TDB passwd database for SAM account enumeration.
- Save a list of user keys for iteration.
-****************************************************************/
-
-static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, bool update, uint32 acb_mask)
-{
- if ( !tdbsam_open( tdbsam_filename ) ) {
- DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
- pwent_initialized = True;
-
- return NT_STATUS_OK;
-}
-
-
-/***************************************************************
- End enumeration of the TDB passwd list.
-****************************************************************/
-
-static void tdbsam_endsampwent(struct pdb_methods *my_methods)
-{
- struct pwent_list *ptr, *ptr_next;
-
- /* close the tdb only if we have a valid pwent state */
-
- if ( pwent_initialized ) {
- DEBUG(7, ("endtdbpwent: closed sam database.\n"));
- tdbsam_close();
- }
-
- /* clear out any remaining entries in the list */
-
- for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
- ptr_next = ptr->next;
- DLIST_REMOVE( tdbsam_pwent_list, ptr );
- SAFE_FREE( ptr->key.dptr);
- SAFE_FREE( ptr );
- }
-
- pwent_initialized = False;
-}
-
-/*****************************************************************
- Get one struct samu from the TDB (next in line)
-*****************************************************************/
-
-static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
-{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- TDB_DATA data;
- struct pwent_list *pkey;
-
- if ( !user ) {
- DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
- return nt_status;
- }
-
- if ( !tdbsam_pwent_list ) {
- DEBUG(4,("tdbsam_getsampwent: end of list\n"));
- return nt_status;
- }
-
- /* pull the next entry */
-
- pkey = tdbsam_pwent_list;
- DLIST_REMOVE( tdbsam_pwent_list, pkey );
-
- data = tdb_fetch(tdbsam, pkey->key);
-
- SAFE_FREE( pkey->key.dptr);
- SAFE_FREE( pkey);
-
- if ( !data.dptr ) {
- DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
- return nt_status;
- }
-
- if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
- DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
- }
-
- SAFE_FREE( data.dptr );
-
- return NT_STATUS_OK;
-}
-
/******************************************************************
Lookup a name in the SAM TDB
******************************************************************/
@@ -1306,10 +1171,6 @@ static bool tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd,
{
bool result = True;
- /* invalidate the existing TDB iterator if it is open */
-
- tdbsam_endsampwent( my_methods );
-
#if 0
if ( !pdb_get_group_rid(newpwd) ) {
DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
@@ -1396,10 +1257,6 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
return NT_STATUS_ACCESS_DENIED;
}
- /* invalidate the existing TDB iterator if it is open */
-
- tdbsam_endsampwent( my_methods );
-
if ( !(new_acct = samu_new( NULL )) ) {
return NT_STATUS_NO_MEMORY;
}
@@ -1592,6 +1449,139 @@ static bool tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
return ret;
}
+struct tdbsam_search_state {
+ struct pdb_methods *methods;
+ uint32_t acct_flags;
+
+ uint32_t *rids;
+ uint32_t num_rids;
+ ssize_t array_size;
+ uint32_t current;
+};
+
+static int tdbsam_collect_rids(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
+ void *private_data)
+{
+ struct tdbsam_search_state *state = talloc_get_type_abort(
+ private_data, struct tdbsam_search_state);
+ size_t prefixlen = strlen(RIDPREFIX);
+ uint32 rid;
+
+ if ((key.dsize < prefixlen)
+ || (strncmp((char *)key.dptr, RIDPREFIX, prefixlen))) {
+ return 0;
+ }
+
+ rid = strtoul((char *)key.dptr+prefixlen, NULL, 16);
+
+ ADD_TO_LARGE_ARRAY(state, uint32, rid, &state->rids, &state->num_rids,
+ &state->array_size);
+
+ return 0;
+}
+
+static void tdbsam_search_end(struct pdb_search *search)
+{
+ struct tdbsam_search_state *state = talloc_get_type_abort(
+ search->private_data, struct tdbsam_search_state);
+ TALLOC_FREE(state);
+}
+
+static bool tdbsam_search_next_entry(struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct tdbsam_search_state *state = talloc_get_type_abort(
+ search->private_data, struct tdbsam_search_state);
+ struct samu *user = NULL;
+ NTSTATUS status;
+ uint32_t rid;
+
+ again:
+ TALLOC_FREE(user);
+ user = samu_new(talloc_tos());
+ if (user == NULL) {
+ DEBUG(0, ("samu_new failed\n"));
+ return false;
+ }
+
+ if (state->current == state->num_rids) {
+ return false;
+ }
+
+ rid = state->rids[state->current++];
+
+ status = tdbsam_getsampwrid(state->methods, user, rid);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
+ /*
+ * Someone has deleted that user since we listed the RIDs
+ */
+ goto again;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("tdbsam_getsampwrid failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(user);
+ return false;
+ }
+
+ if ((state->acct_flags != 0) &&
+ ((state->acct_flags & pdb_get_acct_ctrl(user)) == 0)) {
+ goto again;
+ }
+
+ entry->acct_flags = pdb_get_acct_ctrl(user);
+ entry->rid = rid;
+ entry->account_name = talloc_strdup(
+ search->mem_ctx, pdb_get_username(user));
+ entry->fullname = talloc_strdup(
+ search->mem_ctx, pdb_get_fullname(user));
+ entry->description = talloc_strdup(
+ search->mem_ctx, pdb_get_acct_desc(user));
+
+ TALLOC_FREE(user);
+
+ if ((entry->account_name == NULL) || (entry->fullname == NULL)
+ || (entry->description == NULL)) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ return false;
+ }
+
+ return true;
+}
+
+static bool tdbsam_search_users(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint32 acct_flags)
+{
+ struct tdbsam_search_state *state;
+
+ if (!tdbsam_open(tdbsam_filename)) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n",
+ tdbsam_filename));
+ return false;
+ }
+
+ state = TALLOC_ZERO_P(search->mem_ctx, struct tdbsam_search_state);
+ if (state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return false;
+ }
+ state->acct_flags = acct_flags;
+ state->methods = methods;
+
+ tdb_traverse(tdbsam, tdbsam_collect_rids, state);
+
+ tdbsam_close();
+
+ search->private_data = state;
+ search->next_entry = tdbsam_search_next_entry;
+ search->search_end = tdbsam_search_end;
+
+ return true;
+}
+
/*********************************************************************
Initialize the tdb sam backend. Setup the dispath table of methods,
open the tdb, etc...
@@ -1609,15 +1599,13 @@ static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *loc
(*pdb_method)->name = "tdbsam";
- (*pdb_method)->setsampwent = tdbsam_setsampwent;
- (*pdb_method)->endsampwent = tdbsam_endsampwent;
- (*pdb_method)->getsampwent = tdbsam_getsampwent;
(*pdb_method)->getsampwnam = tdbsam_getsampwnam;
(*pdb_method)->getsampwsid = tdbsam_getsampwsid;
(*pdb_method)->add_sam_account = tdbsam_add_sam_account;
(*pdb_method)->update_sam_account = tdbsam_update_sam_account;
(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
(*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
+ (*pdb_method)->search_users = tdbsam_search_users;
(*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
(*pdb_method)->new_rid = tdbsam_new_rid;
@@ -1625,7 +1613,8 @@ static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *loc
/* save the path for later */
if (!location) {
- if (asprintf(&tdbfile, "%s/%s", get_dyn_STATEDIR(), PASSDB_FILE_NAME) < 0) {
+ if (asprintf(&tdbfile, "%s/%s", lp_private_dir(),
+ PASSDB_FILE_NAME) < 0) {
return NT_STATUS_NO_MEMORY;
}
pfile = tdbfile;
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index f83f898cc0..bae32e89f7 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -429,7 +429,8 @@ static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
/* store it back */
- sd_size = sec_desc_size(sd_store->sd) + sizeof(SEC_DESC_BUF);
+ sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
+ + sizeof(SEC_DESC_BUF);
prs_init(&ps, sd_size, ctx, MARSHALL);
if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
@@ -1866,7 +1867,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
goto err_exit;
}
- create_directory(conn, new_dir);
+ create_directory(conn, NULL, new_dir);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
@@ -5389,8 +5390,9 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
/* Store the security descriptor in a tdb */
- prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
- sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
+ prs_init(&ps,
+ (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
+ + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
&ps, 1)) {
@@ -5534,7 +5536,7 @@ bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **s
/* Save default security descriptor for later */
- prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
+ prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
sizeof(SEC_DESC_BUF), ctx, MARSHALL);
if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index fa6ed89edd..9f2c08629d 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -373,13 +373,17 @@ static struct printjob *print_job_find(const char *sharename, uint32 jobid)
/* Convert a unix jobid to a smb jobid */
-static uint32 sysjob_to_jobid_value;
+struct unixjob_traverse_state {
+ int sysjob;
+ uint32 sysjob_to_jobid_value;
+};
static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
- TDB_DATA data, void *state)
+ TDB_DATA data, void *private_data)
{
struct printjob *pjob;
- int *sysjob = (int *)state;
+ struct unixjob_traverse_state *state =
+ (struct unixjob_traverse_state *)private_data;
if (!data.dptr || data.dsize == 0)
return 0;
@@ -388,10 +392,10 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
if (key.dsize != sizeof(uint32))
return 0;
- if (*sysjob == pjob->sysjob) {
+ if (state->sysjob == pjob->sysjob) {
uint32 jobid = IVAL(key.dptr,0);
- sysjob_to_jobid_value = jobid;
+ state->sysjob_to_jobid_value = jobid;
return 1;
}
@@ -407,8 +411,10 @@ uint32 sysjob_to_jobid(int unix_jobid)
{
int services = lp_numservices();
int snum;
+ struct unixjob_traverse_state state;
- sysjob_to_jobid_value = (uint32)-1;
+ state.sysjob = unix_jobid;
+ state.sysjob_to_jobid_value = (uint32)-1;
for (snum = 0; snum < services; snum++) {
struct tdb_print_db *pdb;
@@ -418,10 +424,10 @@ uint32 sysjob_to_jobid(int unix_jobid)
if (!pdb) {
continue;
}
- tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
+ tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
release_print_db(pdb);
- if (sysjob_to_jobid_value != (uint32)-1)
- return sysjob_to_jobid_value;
+ if (state.sysjob_to_jobid_value != (uint32)-1)
+ return state.sysjob_to_jobid_value;
}
return (uint32)-1;
}
diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c
index b3d024d7b4..bb410e646b 100644
--- a/source3/registry/reg_api.c
+++ b/source3/registry/reg_api.c
@@ -378,7 +378,7 @@ WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
return err;
}
- *secdescsize = sec_desc_size(secdesc);
+ *secdescsize = ndr_size_security_descriptor(secdesc, 0);
TALLOC_FREE(mem_ctx);
*last_changed_time = 0;
@@ -729,7 +729,7 @@ WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
}
/* recurse through subkeys first */
- werr = reg_openkey(mem_ctx, parent, path, REG_KEY_WRITE, &key);
+ werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
diff --git a/source3/registry/reg_cachehook.c b/source3/registry/reg_cachehook.c
index 289d4e50ce..74670aac30 100644
--- a/source3/registry/reg_cachehook.c
+++ b/source3/registry/reg_cachehook.c
@@ -25,19 +25,21 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_REGISTRY
-static SORTED_TREE *cache_tree;
+static SORTED_TREE *cache_tree = NULL;
extern REGISTRY_OPS regdb_ops; /* these are the default */
static REGISTRY_HOOK default_hook = { KEY_TREE_ROOT, &regdb_ops };
/**********************************************************************
- Initialize the cache tree
+ Initialize the cache tree if it has not been initialized yet.
*********************************************************************/
bool reghook_cache_init( void )
{
- cache_tree = pathtree_init( &default_hook, NULL );
+ if (cache_tree == NULL) {
+ cache_tree = pathtree_init(&default_hook, NULL);
+ }
- return ( cache_tree == NULL );
+ return (cache_tree != NULL);
}
/**********************************************************************
diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c
index 25c6557c87..f50a41816c 100644
--- a/source3/registry/reg_db.c
+++ b/source3/registry/reg_db.c
@@ -259,7 +259,7 @@ bool regdb_init( void )
uint32 vers_id;
if ( tdb_reg )
- return True;
+ return true;
if ( !(tdb_reg = tdb_wrap_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600)) )
{
@@ -267,7 +267,7 @@ bool regdb_init( void )
if ( !tdb_reg ) {
DEBUG(0,("regdb_init: Failed to open registry %s (%s)\n",
state_path("registry.tdb"), strerror(errno) ));
- return False;
+ return false;
}
DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
@@ -286,11 +286,11 @@ bool regdb_init( void )
/* always setup the necessary keys and values */
if ( !init_registry_data() ) {
- DEBUG(0,("init_registry: Failed to initialize data in registry!\n"));
- return False;
+ DEBUG(0,("regdb_init: Failed to initialize data in registry!\n"));
+ return false;
}
- return True;
+ return true;
}
/***********************************************************************
@@ -329,6 +329,10 @@ WERROR regdb_open( void )
int regdb_close( void )
{
+ if (tdb_refcount == 0) {
+ return 0;
+ }
+
tdb_refcount--;
DEBUG(10,("regdb_close: decrementing refcount (%d)\n", tdb_refcount));
@@ -364,7 +368,7 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
uint8 *buffer = NULL;
int i = 0;
uint32 len, buflen;
- bool ret = True;
+ bool ret = true;
uint32 num_subkeys = regsubkey_ctr_numkeys(ctr);
char *keyname = NULL;
TALLOC_CTX *ctx = talloc_tos();
@@ -382,7 +386,7 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
/* allocate some initial memory */
if (!(buffer = (uint8 *)SMB_MALLOC(1024))) {
- return False;
+ return false;
}
buflen = 1024;
len = 0;
@@ -399,7 +403,7 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
/* allocate some extra space */
if ((buffer = (uint8 *)SMB_REALLOC( buffer, len*2 )) == NULL) {
DEBUG(0,("regdb_store_keys: Failed to realloc memory of size [%d]\n", len*2));
- ret = False;
+ ret = false;
goto done;
}
buflen = len*2;
@@ -413,7 +417,7 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
dbuf.dptr = buffer;
dbuf.dsize = len;
if ( tdb_store_bystring( tdb_reg->tdb, keyname, dbuf, TDB_REPLACE ) == -1) {
- ret = False;
+ ret = false;
goto done;
}
@@ -801,7 +805,7 @@ bool regdb_store_values( const char *key, REGVAL_CTR *values )
&& (memcmp(old_data.dptr, data.dptr, data.dsize) == 0)) {
SAFE_FREE(old_data.dptr);
SAFE_FREE(data.dptr);
- return True;
+ return true;
}
ret = tdb_trans_store_bystring(tdb_reg->tdb, keystr, data, TDB_REPLACE);
diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c
index 22700e6481..92077aa847 100644
--- a/source3/registry/regfio.c
+++ b/source3/registry/regfio.c
@@ -1554,7 +1554,7 @@ static uint32 sk_record_data_size( SEC_DESC * sd )
/* the record size is sizeof(hdr) + name + static members + data_size_field */
- size = sizeof(uint32)*5 + sec_desc_size( sd ) + sizeof(uint32);
+ size = sizeof(uint32)*5 + ndr_size_security_descriptor(sd, 0) + sizeof(uint32);
/* multiple of 8 */
size_mod8 = size & 0xfffffff8;
@@ -1784,7 +1784,8 @@ static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
nk->sec_desc->ref_count = 0;
/* size value must be self-inclusive */
- nk->sec_desc->size = sec_desc_size(sec_desc) + sizeof(uint32);
+ nk->sec_desc->size = ndr_size_security_descriptor(sec_desc, 0)
+ + sizeof(uint32);
DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, REGF_SK_REC *);
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index 26d2124da0..e192e4ca26 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -978,11 +978,12 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
int validation_level = 3;
const char *workstation_name_slash;
const char *server_name_slash;
- static uint8 zeros[16];
+ uint8 zeros[16];
DOM_CRED clnt_creds;
DOM_CRED ret_creds;
int i;
-
+
+ ZERO_STRUCT(zeros);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
ZERO_STRUCT(ret_creds);
@@ -1084,9 +1085,10 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
int validation_level = 3;
const char *workstation_name_slash;
const char *server_name_slash;
- static uint8 zeros[16];
+ uint8 zeros[16];
int i;
-
+
+ ZERO_STRUCT(zeros);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
diff --git a/source3/rpc_parse/parse_buffer.c b/source3/rpc_parse/parse_buffer.c
index c30ad487dd..e98822d46e 100644
--- a/source3/rpc_parse/parse_buffer.c
+++ b/source3/rpc_parse/parse_buffer.c
@@ -435,7 +435,7 @@ bool smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC
}
if (*secdesc != NULL) {
- buffer->string_at_end -= sec_desc_size(*secdesc);
+ buffer->string_at_end -= ndr_size_security_descriptor(*secdesc, 0);
if(!prs_set_offset(ps, buffer->string_at_end))
return False;
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 23dae9f3a1..638d71a73e 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -1544,9 +1544,11 @@ static void schannel_digest(struct schannel_auth_struct *a,
uchar digest_final[16])
{
uchar whole_packet_digest[16];
- static const uchar zeros[4] = { 0, };
+ uchar zeros[4];
struct MD5Context ctx3;
-
+
+ ZERO_STRUCT(zeros);
+
/* verfiy the signature on the packet by MD5 over various bits */
MD5Init(&ctx3);
/* use our sequence number, which ensures the packet is not
@@ -1573,11 +1575,13 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a,
RPC_AUTH_SCHANNEL_CHK *verf,
uchar sealing_key[16])
{
- static const uchar zeros[4] = { 0, };
+ uchar zeros[4];
uchar digest2[16];
uchar sess_kf0[16];
int i;
+ ZERO_STRUCT(zeros);
+
for (i = 0; i < sizeof(sess_kf0); i++) {
sess_kf0[i] = a->sess_key[i] ^ 0xf0;
}
@@ -1600,10 +1604,12 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a,
static void schannel_deal_with_seq_num(struct schannel_auth_struct *a,
RPC_AUTH_SCHANNEL_CHK *verf)
{
- static const uchar zeros[4] = { 0, };
+ uchar zeros[4];
uchar sequence_key[16];
uchar digest1[16];
+ ZERO_STRUCT(zeros);
+
hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1);
dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1));
diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c
index 6198a78de0..6ea128d3a4 100644
--- a/source3/rpc_parse/parse_sec.c
+++ b/source3/rpc_parse/parse_sec.c
@@ -291,14 +291,14 @@ bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
if (psd->owner_sid != NULL) {
off_owner_sid = offset;
- offset += sid_size(psd->owner_sid);
+ offset += ndr_size_dom_sid(psd->owner_sid, 0);
} else {
off_owner_sid = 0;
}
if (psd->group_sid != NULL) {
off_grp_sid = offset;
- offset += sid_size(psd->group_sid);
+ offset += ndr_size_dom_sid(psd->group_sid, 0);
} else {
off_grp_sid = 0;
}
@@ -426,7 +426,7 @@ bool sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int
if(!prs_uint32 ("ptr ", ps, depth, &ptr))
return False;
- len = sec_desc_size(psdb->sd);
+ len = ndr_size_security_descriptor(psdb->sd, 0);
if(!prs_uint32_pre("len ", ps, depth, &len, &off_len))
return False;
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index ea76c57045..3bf8ef27c1 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -3098,7 +3098,7 @@ uint32 spoolss_size_printer_info_2(PRINTER_INFO_2 *info)
size += 4;
- size += sec_desc_size( info->secdesc );
+ size += ndr_size_security_descriptor( info->secdesc, 0 );
size+=size_of_device_mode( info->devmode );
@@ -3185,7 +3185,7 @@ return the size required by a struct in the stream
uint32 spoolss_size_printer_info_3(PRINTER_INFO_3 *info)
{
/* The 8 is for the self relative pointer - 8 byte aligned.. */
- return 8 + (uint32)sec_desc_size( info->secdesc );
+ return 8 + (uint32)ndr_size_security_descriptor( info->secdesc, 0 );
}
/*******************************************************************
diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c
index 6337c53fc1..954aa80600 100644
--- a/source3/rpc_parse/parse_srv.c
+++ b/source3/rpc_parse/parse_srv.c
@@ -507,7 +507,8 @@ static bool srv_io_share_info502_str(const char *desc, SH_INFO_502_STR *sh502, p
if(UNMARSHALLING(ps)) {
- sh502->ptrs->sd_size = sh502->sd_size = sec_desc_size(sh502->sd);
+ sh502->ptrs->sd_size = sh502->sd_size =
+ ndr_size_security_descriptor(sh502->sd, 0);
prs_set_offset(ps, old_offset + sh502->reserved);
}
@@ -1460,7 +1461,7 @@ void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname,
{
switch(level) {
case 502: {
- size_t sd_size = sec_desc_size(sd);
+ size_t sd_size = ndr_size_security_descriptor(sd, 0);
q->ptr_srv_name = 1;
init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
q->info.switch_value = q->info_level = level;
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 3cc2472116..01e5cf2cda 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -870,13 +870,11 @@ static void init_srv_sess_info_0(pipes_struct *p, SRV_SESS_INFO_0 *ss0, uint32 *
/*******************************************************************
********************************************************************/
-/* global needed to make use of the share_mode_forall() callback */
-static struct sess_file_count s_file_cnt;
-
static void sess_file_fn( const struct share_mode_entry *e,
- const char *sharepath, const char *fname, void *state )
+ const char *sharepath, const char *fname,
+ void *data )
{
- struct sess_file_count *sess = &s_file_cnt;
+ struct sess_file_count *sess = (struct sess_file_count *)data;
if ( procid_equal(&e->pid, &sess->pid) && (sess->uid == e->uid) ) {
sess->count++;
@@ -890,11 +888,13 @@ static void sess_file_fn( const struct share_mode_entry *e,
static int net_count_files( uid_t uid, struct server_id pid )
{
+ struct sess_file_count s_file_cnt;
+
s_file_cnt.count = 0;
s_file_cnt.uid = uid;
s_file_cnt.pid = pid;
- share_mode_forall( sess_file_fn, NULL );
+ share_mode_forall( sess_file_fn, &s_file_cnt );
return s_file_cnt.count;
}
@@ -2159,7 +2159,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
goto error_exit;
}
- sd_size = sec_desc_size(psd);
+ sd_size = ndr_size_security_descriptor(psd, 0);
r_u->ptr_response = 1;
r_u->size_response = sd_size;
diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c
index 3f5cf03abb..ac45d8bf75 100644
--- a/source3/rpc_server/srv_svcctl_nt.c
+++ b/source3/rpc_server/srv_svcctl_nt.c
@@ -813,7 +813,7 @@ WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q
if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
return WERR_NOMEM;
- r_u->needed = sec_desc_size( sec_desc );
+ r_u->needed = ndr_size_security_descriptor( sec_desc, 0 );
if ( r_u->needed > q_u->buffer_size ) {
ZERO_STRUCTP( &r_u->buffer );
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index 6f6e1e6474..dd8b911bb8 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -850,6 +850,18 @@ out_free:
goto done;
}
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(cli,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ "IPC$");
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ result = 1;
+ goto done;
+ }
+ }
+
#if 0 /* COMMENT OUT FOR TESTING */
memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
#endif
diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh
index d4264bab8c..86abb15ed1 100755
--- a/source3/script/tests/selftest.sh
+++ b/source3/script/tests/selftest.sh
@@ -62,7 +62,6 @@ export PATH SOCKET_WRAPPER_DIR DOMAIN
export PRIVATEDIR LIBDIR PIDDIR LOCKDIR LOGDIR SERVERCONFFILE
export SRCDIR SCRIPTDIR BINDIR
export USERNAME PASSWORD
-export SMBTORTURE4
export WORKGROUP SERVER SERVER_IP
export NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP
export WINBINDD_SOCKET_DIR WINBINDD_PRIV_PIPE_DIR
@@ -70,10 +69,20 @@ export WINBINDD_SOCKET_DIR WINBINDD_PRIV_PIPE_DIR
PATH=bin:$PATH
export PATH
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH":"$BINDIR"
+if test x"$LD_LIBRARY_PATH" != x""; then
+ LD_LIBRARY_PATH="$BINDIR:$LD_LIBRARY_PATH"
+else
+ LD_LIBRARY_PATH="$BINDIR"
+fi
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
+SAMBA4BINDIR=`dirname $SMBTORTURE4`
+SAMBA4SHAREDDIR="$SAMBA4BINDIR/shared"
+
+export SAMBA4SHAREDDIR
+export SMBTORTURE4
+
##
## verify that we were built with --enable-socket-wrapper
##
diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
index 3a8f3bd5b6..c10aed0ee6 100755
--- a/source3/script/tests/test_smbclient_s3.sh
+++ b/source3/script/tests/test_smbclient_s3.sh
@@ -2,7 +2,7 @@
# this runs the file serving tests that are expected to pass with samba3
-if [ $# != 2 ]; then
+if [ $# -lt 2 ]; then
cat <<EOF
Usage: test_smbclient_s3.sh SERVER SERVER_IP
EOF
@@ -12,6 +12,8 @@ fi
SERVER="$1"
SERVER_IP="$2"
SMBCLIENT="$VALGRIND ${SMBCLIENT:-$BINDIR/smbclient} $CONFIGURATION"
+shift 2
+ADDARGS="$*"
incdir=`dirname $0`
. $incdir/test_functions.sh
@@ -24,7 +26,7 @@ test_noninteractive_no_prompt()
prompt="smb"
echo du | \
- $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp 2>&1 | \
+ $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I SERVER_IP $ADDARGS 2>&1 | \
grep $prompt
if [ $? = 0 ] ; then
@@ -48,8 +50,8 @@ quit
EOF
CLI_FORCE_INTERACTIVE=yes \
- $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp \
- < $tmpfile 2>/dev/null | \
+ $SMBCLIENT $CONFIGURATION "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP \
+ $ADDARGS < $tmpfile 2>/dev/null | \
grep $prompt
if [ $? = 0 ] ; then
@@ -64,7 +66,7 @@ EOF
}
testit "smbclient -L $SERVER_IP" $SMBCLIENT $CONFIGURATION -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
-testit "smbclient -L $SERVER" $SMBCLIENT $CONFIGURATION -L $SERVER -N -p 139 || failed=`expr $failed + 1`
+testit "smbclient -L $SERVER -I $SERVER_IP" $SMBCLIENT $CONFIGURATION -L $SERVER -I $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
testit "noninteractive smbclient does not prompt" \
test_noninteractive_no_prompt || \
diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh
index f662eacd3e..acb641b9fb 100755
--- a/source3/script/tests/test_smbtorture_s3.sh
+++ b/source3/script/tests/test_smbtorture_s3.sh
@@ -42,7 +42,7 @@ for t in $tests; do
fi
start=""
name="$t"
- testit "$name" $VALGRIND $BINDIR/smbtorture $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
+ testit "$name" $VALGRIND $BINDIR/smbtorture $unc -U"$username"%"$password" $ADDARGS $t || failed=`expr $failed + 1`
done
testok $0 $failed
diff --git a/source3/script/tests/tests_all.sh b/source3/script/tests/tests_all.sh
index 12789aa926..2edc025017 100755
--- a/source3/script/tests/tests_all.sh
+++ b/source3/script/tests/tests_all.sh
@@ -1,9 +1,16 @@
$SCRIPTDIR/test_local_s3.sh || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" || failed=`expr $failed + $?`
+echo "Testing encrypted"
+$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" "-e" || failed=`expr $failed + $?`
$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP || failed=`expr $failed + $?`
+echo "Testing encrypted"
+$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP "-e" || failed=`expr $failed + $?`
$SCRIPTDIR/test_wbinfo_s3.sh $WORKGROUP $SERVER $USERNAME $PASSWORD || failed=`expr $failed + $?`
+LD_LIBRARY_PATH="$SAMBA4SHAREDDIR:$LD_LIBRARY_PATH"
+echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH
SMBTORTURE4VERSION=`$SMBTORTURE4 --version`
if [ -n "$SMBTORTURE4" -a -n "$SMBTORTURE4VERSION" ];then
echo "Running Tests with Samba4's smbtorture"
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 994b10d6a8..bc1761b0fd 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn,
}
construct_reply_common((char *)req->inbuf, aio_ex->outbuf);
- set_message(aio_ex->outbuf, 12, 0, True);
+ srv_set_message(aio_ex->outbuf, 12, 0, True);
SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
a = &aio_ex->acb;
@@ -356,8 +356,9 @@ bool schedule_aio_write_and_X(connection_struct *conn,
SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
show_msg(aio_ex->outbuf);
- if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) {
- exit_server_cleanly("handle_aio_write: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("handle_aio_write: srv_send_smb "
"failed.");
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
@@ -407,10 +408,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
"Error = %s\n",
aio_ex->fsp->fsp_name, strerror(errno) ));
- outsize = (UNIXERROR(ERRDOS,ERRnoaccess));
ret = errno;
+ ERROR_NT(map_nt_error_from_unix(ret));
+ outsize = srv_set_message(outbuf,0,0,true);
} else {
- outsize = set_message(outbuf,12,nread,False);
+ outsize = srv_set_message(outbuf,12,nread,False);
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
@@ -425,8 +427,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
}
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("handle_aio_read_complete: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),outbuf,
+ IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) {
+ exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
"failed.");
}
@@ -448,6 +451,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
int ret = 0;
files_struct *fsp = aio_ex->fsp;
char *outbuf = aio_ex->outbuf;
+ const char *inbuf = aio_ex->inbuf;
ssize_t numtowrite = aio_ex->acb.aio_nbytes;
ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
@@ -492,8 +496,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
return 0;
}
- UNIXERROR(ERRHRD,ERRdiskfull);
ret = errno;
+ ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull);
+ srv_set_message(outbuf,0,0,true);
} else {
bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0);
NTSTATUS status;
@@ -509,16 +514,18 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
fsp->fnum, (int)numtowrite, (int)nwritten));
status = sync_file(fsp->conn,fsp, write_through);
if (!NT_STATUS_IS_OK(status)) {
- UNIXERROR(ERRHRD,ERRdiskfull);
ret = errno;
+ ERROR_BOTH(map_nt_error_from_unix(ret),
+ ERRHRD, ERRdiskfull);
+ srv_set_message(outbuf,0,0,true);
DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
fsp->fsp_name, nt_errstr(status) ));
}
}
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("handle_aio_write: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
}
DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 0078bb7d13..4e0d5289f8 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -41,6 +41,7 @@ typedef struct _blocking_lock_record {
enum brl_type lock_type;
char *inbuf;
int length;
+ bool encrypted;
} blocking_lock_record;
/* dlink list we store pending lock records on. */
@@ -149,7 +150,7 @@ static bool recalc_brl_timeout(void)
****************************************************************************/
bool push_blocking_lock_request( struct byte_range_lock *br_lck,
- const char *inbuf, int length,
+ const struct smb_request *req,
files_struct *fsp,
int lock_timeout,
int lock_num,
@@ -161,6 +162,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
uint32 blocking_pid)
{
static bool set_lock_msg;
+ size_t length = smb_len(req->inbuf)+4;
blocking_lock_record *blr;
NTSTATUS status;
@@ -188,7 +190,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
return False;
}
- blr->com_type = CVAL(inbuf,smb_com);
+ blr->com_type = CVAL(req->inbuf,smb_com);
blr->fsp = fsp;
if (lock_timeout == -1) {
blr->expire_time.tv_sec = 0;
@@ -204,8 +206,9 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
blr->lock_type = lock_type;
blr->offset = offset;
blr->count = count;
- memcpy(blr->inbuf, inbuf, length);
+ memcpy(blr->inbuf, req->inbuf, length);
blr->length = length;
+ blr->encrypted = req->encrypted;
/* Add a pending lock record for this. */
status = brl_lock(smbd_messaging_context(), br_lck,
@@ -235,14 +238,14 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
set_lock_msg = True;
}
- DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with "
+ DEBUG(3,("push_blocking_lock_request: lock request length=%u blocked with "
"expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
- length, (unsigned int)blr->expire_time.tv_sec,
+ (unsigned int)length, (unsigned int)blr->expire_time.tv_sec,
(unsigned int)blr->expire_time.tv_usec, lock_timeout,
blr->fsp->fnum, blr->fsp->fsp_name ));
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
return True;
}
@@ -259,7 +262,7 @@ static void reply_lockingX_success(blocking_lock_record *blr)
smb_panic("Could not allocate smb_request");
}
- init_smb_request(req, (uint8 *)blr->inbuf, 0);
+ init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
reply_outbuf(req, 2, 0);
/*
@@ -272,8 +275,10 @@ static void reply_lockingX_success(blocking_lock_record *blr)
chain_reply(req);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
- exit_server_cleanly("send_blocking_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+ exit_server_cleanly("send_blocking_reply: srv_send_smb failed.");
}
}
@@ -298,19 +303,21 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat
/* Store the last lock error. */
files_struct *fsp = blr->fsp;
- fsp->last_lock_failure.context.smbpid = blr->lock_pid;
- fsp->last_lock_failure.context.tid = fsp->conn->cnum;
- fsp->last_lock_failure.context.pid = procid_self();
- fsp->last_lock_failure.start = blr->offset;
- fsp->last_lock_failure.size = blr->count;
- fsp->last_lock_failure.fnum = fsp->fnum;
- fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
- fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ if (fsp) {
+ fsp->last_lock_failure.context.smbpid = blr->lock_pid;
+ fsp->last_lock_failure.context.tid = fsp->conn->cnum;
+ fsp->last_lock_failure.context.pid = procid_self();
+ fsp->last_lock_failure.start = blr->offset;
+ fsp->last_lock_failure.size = blr->count;
+ fsp->last_lock_failure.fnum = fsp->fnum;
+ fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
+ fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ }
}
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("generic_blocking_lock_error: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),outbuf, blr->encrypted)) {
+ exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
}
}
@@ -388,8 +395,10 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status
*/
SCVAL(outbuf,smb_com,SMBtrans2);
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server_cleanly("blocking_lock_reply_error: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ outbuf,
+ IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+ exit_server_cleanly("blocking_lock_reply_error: srv_send_smb failed.");
}
break;
}
@@ -531,12 +540,12 @@ static bool process_trans2(blocking_lock_record *blr)
return True;
}
- init_smb_request(req, (uint8 *)blr->inbuf, 0);
+ init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted);
SCVAL(req->inbuf, smb_com, SMBtrans2);
SSVAL(params,0,0);
/* Fake up max_data_bytes here - we know it fits. */
- send_trans2_replies(req, params, 2, NULL, 0, 0xffff);
+ send_trans2_replies(blr->fsp->conn, req, params, 2, NULL, 0, 0xffff);
return True;
}
@@ -597,6 +606,9 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
locktype,
NT_STATUS_RANGE_NOT_LOCKED);
}
+ /* We're closing the file fsp here, so ensure
+ * we don't have a dangling pointer. */
+ blr->fsp = NULL;
}
}
}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 8e3c9b4c91..a96f80ee0e 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -438,12 +438,19 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
dosmode &= SAMBA_ATTRIBUTES_MASK;
DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
- if (!st || (st && !VALID_STAT(*st))) {
+
+ if (st == NULL) {
+ SET_STAT_INVALID(st1);
st = &st1;
+ }
+
+ if (!VALID_STAT(*st)) {
if (SMB_VFS_STAT(conn,fname,st))
return(-1);
}
+ unixmode = st->st_mode;
+
get_acl_group_bits(conn, fname, &st->st_mode);
if (S_ISDIR(st->st_mode))
@@ -451,8 +458,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
else
dosmode &= ~aDIR;
- if (dos_mode(conn,fname,st) == dosmode)
+ if (dos_mode(conn,fname,st) == dosmode) {
+ st->st_mode = unixmode;
return(0);
+ }
/* Store the DOS attributes in an EA by preference. */
if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
@@ -460,6 +469,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
+ st->st_mode = unixmode;
return 0;
}
@@ -500,6 +510,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
+ st->st_mode = unixmode;
return 0;
}
@@ -534,6 +545,9 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
+ if (ret == 0) {
+ st->st_mode = unixmode;
+ }
}
return( ret );
diff --git a/source3/smbd/error.c b/source3/smbd/error.c
index 12eff42023..de2de088ec 100644
--- a/source3/smbd/error.c
+++ b/source3/smbd/error.c
@@ -24,34 +24,6 @@ extern struct unix_error_map unix_dos_nt_errmap[];
extern uint32 global_client_caps;
-/****************************************************************************
- Create an error packet from errno.
-****************************************************************************/
-
-int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file)
-{
- int eclass=def_class;
- int ecode=def_code;
- NTSTATUS ntstatus = def_status;
- int i=0;
-
- if (errno != 0) {
- DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno)));
-
- while (unix_dos_nt_errmap[i].dos_class != 0) {
- if (unix_dos_nt_errmap[i].unix_error == errno) {
- eclass = unix_dos_nt_errmap[i].dos_class;
- ecode = unix_dos_nt_errmap[i].dos_code;
- ntstatus = unix_dos_nt_errmap[i].nt_error;
- break;
- }
- i++;
- }
- }
-
- return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
-}
-
bool use_nt_status(void)
{
return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
@@ -111,7 +83,7 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu
int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = srv_set_message(outbuf,0,0,True);
error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
return outsize;
}
@@ -150,8 +122,24 @@ void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode,
line, file);
}
+void reply_openerror(struct smb_request *req, NTSTATUS status)
+{
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ /*
+ * We hit an existing file, and if we're returning DOS
+ * error codes OBJECT_NAME_COLLISION would map to
+ * ERRDOS/183, we need to return ERRDOS/80, see bug
+ * 4852.
+ */
+ reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
+ ERRDOS, ERRfilexists);
+ } else {
+ reply_nterror(req, status);
+ }
+}
+
void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode,
- NTSTATUS defstatus, int line, const char *file)
+ NTSTATUS defstatus, int line, const char *file)
{
int eclass=defclass;
int ecode=defcode;
@@ -163,7 +151,7 @@ void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode,
if (errno != 0) {
DEBUG(3,("unix_error_packet: error string = %s\n",
- strerror(errno)));
+ strerror(errno)));
while (unix_dos_nt_errmap[i].dos_class != 0) {
if (unix_dos_nt_errmap[i].unix_error == errno) {
@@ -177,22 +165,5 @@ void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode,
}
error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus,
- line, file);
+ line, file);
}
-
-void reply_openerror(struct smb_request *req, NTSTATUS status)
-{
- if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
- /*
- * We hit an existing file, and if we're returning DOS
- * error codes OBJECT_NAME_COLLISION would map to
- * ERRDOS/183, we need to return ERRDOS/80, see bug
- * 4852.
- */
- reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
- ERRDOS, ERRfilexists);
- } else {
- reply_nterror(req, status);
- }
-}
-
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index f28016ccb3..68a13d692f 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -30,7 +30,7 @@ extern int max_send;
#define NERR_notsupported 50
-static void api_no_reply(struct smb_request *req);
+static void api_no_reply(connection_struct *conn, struct smb_request *req);
/*******************************************************************
copies parameters and data, as needed, into the smb buffer
@@ -81,7 +81,8 @@ static void copy_trans_params_and_data(char *outbuf, int align,
Send a trans reply.
****************************************************************************/
-void send_trans_reply(struct smb_request *req,
+void send_trans_reply(connection_struct *conn,
+ struct smb_request *req,
char *rparam, int rparam_len,
char *rdata, int rdata_len,
bool buffer_too_large)
@@ -129,8 +130,10 @@ void send_trans_reply(struct smb_request *req,
}
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("send_trans_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
TALLOC_FREE(req->outbuf);
@@ -175,8 +178,10 @@ void send_trans_reply(struct smb_request *req,
}
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(), (char *)req->outbuf))
- exit_server_cleanly("send_trans_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
tot_data_sent += this_ldata;
tot_param_sent += this_lparam;
@@ -188,7 +193,7 @@ void send_trans_reply(struct smb_request *req,
Start the first part of an RPC reply which began with an SMBtrans request.
****************************************************************************/
-static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
+static void api_rpc_trans_reply(connection_struct *conn, struct smb_request *req, smb_np_struct *p)
{
bool is_data_outstanding;
char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
@@ -203,11 +208,11 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
&is_data_outstanding)) < 0) {
SAFE_FREE(rdata);
- api_no_reply(req);
+ api_no_reply(conn,req);
return;
}
- send_trans_reply(req, NULL, 0, rdata, data_len, is_data_outstanding);
+ send_trans_reply(conn, req, NULL, 0, rdata, data_len, is_data_outstanding);
SAFE_FREE(rdata);
return;
}
@@ -216,7 +221,7 @@ static void api_rpc_trans_reply(struct smb_request *req, smb_np_struct *p)
WaitNamedPipeHandleState
****************************************************************************/
-static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_WNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
char *param, int param_len)
{
uint16 priority;
@@ -231,10 +236,10 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
if (wait_rpc_pipe_hnd_state(p, priority)) {
/* now send the reply */
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
- api_no_reply(req);
+ api_no_reply(conn,req);
}
@@ -242,7 +247,7 @@ static void api_WNPHS(struct smb_request *req, smb_np_struct *p,
SetNamedPipeHandleState
****************************************************************************/
-static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
+static void api_SNPHS(connection_struct *conn, struct smb_request *req, smb_np_struct *p,
char *param, int param_len)
{
uint16 id;
@@ -257,10 +262,10 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
if (set_rpc_pipe_hnd_state(p, id)) {
/* now send the reply */
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
- api_no_reply(req);
+ api_no_reply(conn,req);
}
@@ -268,7 +273,7 @@ static void api_SNPHS(struct smb_request *req, smb_np_struct *p,
When no reply is generated, indicate unsupported.
****************************************************************************/
-static void api_no_reply(struct smb_request *req)
+static void api_no_reply(connection_struct *conn, struct smb_request *req)
{
char rparam[4];
@@ -279,7 +284,7 @@ static void api_no_reply(struct smb_request *req)
DEBUG(3,("Unsupported API fd command\n"));
/* now send the reply */
- send_trans_reply(req, rparam, 4, NULL, 0, False);
+ send_trans_reply(conn, req, rparam, 4, NULL, 0, False);
return;
}
@@ -321,7 +326,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
/* Win9x does this call with a unicode pipe name, not a pnum. */
/* Just return success for now... */
DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
- send_trans_reply(req, NULL, 0, NULL, 0, False);
+ send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
return;
}
@@ -349,18 +354,18 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
/* dce/rpc command */
reply = write_to_pipe(p, data, tdscnt);
if (!reply) {
- api_no_reply(req);
+ api_no_reply(conn, req);
return;
}
- api_rpc_trans_reply(req, p);
+ api_rpc_trans_reply(conn, req, p);
break;
case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
/* Wait Named Pipe Handle state */
- api_WNPHS(req, p, params, tpscnt);
+ api_WNPHS(conn, req, p, params, tpscnt);
break;
case TRANSACT_SETNAMEDPIPEHANDLESTATE:
/* Set Named Pipe Handle state */
- api_SNPHS(req, p, params, tpscnt);
+ api_SNPHS(conn, req, p, params, tpscnt);
break;
default:
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -472,8 +477,10 @@ static void handle_trans(connection_struct *conn, struct smb_request *req,
state->max_data_return,
state->max_param_return);
- if (state->close_on_completion)
+ if (state->close_on_completion) {
close_cnum(conn,state->vuid);
+ req->conn = NULL;
+ }
return;
}
@@ -482,8 +489,9 @@ static void handle_trans(connection_struct *conn, struct smb_request *req,
Reply to a SMBtrans.
****************************************************************************/
-void reply_trans(connection_struct *conn, struct smb_request *req)
+void reply_trans(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int dsoff;
unsigned int dscnt;
unsigned int psoff;
@@ -662,8 +670,9 @@ void reply_trans(connection_struct *conn, struct smb_request *req)
Reply to a secondary SMBtrans.
****************************************************************************/
-void reply_transs(connection_struct *conn, struct smb_request *req)
+void reply_transs(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
int size;
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 3ab216c062..5a6df1f139 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -4605,7 +4605,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
/* If api_Unsupported returns false we can't return anything. */
if (reply) {
- send_trans_reply(req, rparam, rparam_len,
+ send_trans_reply(conn, req, rparam, rparam_len,
rdata, rdata_len, False);
}
diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c
index c369f6eda4..1dc9c67dcc 100644
--- a/source3/smbd/mangle_hash.c
+++ b/source3/smbd/mangle_hash.c
@@ -57,8 +57,7 @@ static char magic_char = '~';
static const char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
#define MANGLE_BASE (sizeof(basechars)/sizeof(char)-1)
-static unsigned char chartest[256] = { 0 };
-static bool ct_initialized = False;
+static unsigned char *chartest;
#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
#define BASECHAR_MASK 0xf0
@@ -334,13 +333,13 @@ static void init_chartest( void )
{
const unsigned char *s;
- memset( (char *)chartest, '\0', 256 );
+ chartest = SMB_MALLOC_ARRAY(unsigned char, 256);
+
+ SMB_ASSERT(chartest != NULL);
for( s = (const unsigned char *)basechars; *s; s++ ) {
chartest[*s] |= BASECHAR_MASK;
}
-
- ct_initialized = True;
}
/* ************************************************************************** **
@@ -367,8 +366,9 @@ static bool is_mangled(const char *s, const struct share_params *p)
magic_char = lp_magicchar(p);
- if( !ct_initialized )
+ if (chartest == NULL) {
init_chartest();
+ }
magic = strchr_m( s, magic_char );
while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */
diff --git a/source3/smbd/message.c b/source3/smbd/message.c
index d0b524da0e..a870f03df9 100644
--- a/source3/smbd/message.c
+++ b/source3/smbd/message.c
@@ -137,7 +137,7 @@ static void msg_deliver(struct msg_state *state)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sends(connection_struct *conn, struct smb_request *req)
+void reply_sends(struct smb_request *req)
{
struct msg_state *state;
int len;
@@ -190,7 +190,7 @@ void reply_sends(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendstrt(connection_struct *conn, struct smb_request *req)
+void reply_sendstrt(struct smb_request *req)
{
char *p;
@@ -234,7 +234,7 @@ void reply_sendstrt(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendtxt(connection_struct *conn, struct smb_request *req)
+void reply_sendtxt(struct smb_request *req)
{
int len;
char *msg;
@@ -287,7 +287,7 @@ void reply_sendtxt(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_sendend(connection_struct *conn, struct smb_request *req)
+void reply_sendend(struct smb_request *req)
{
START_PROFILE(SMBsendend);
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 02f752fd67..9f56949eeb 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -505,7 +505,7 @@ static const struct {
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_negprot(connection_struct *conn, struct smb_request *req)
+void reply_negprot(struct smb_request *req)
{
size_t size = smb_len(req->inbuf) + 4;
int choice= -1;
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 0dd7fbb20e..7287210802 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -128,7 +128,8 @@ static bool notify_marshall_changes(int num_changes,
Setup the common parts of the return packet and send it.
*****************************************************************************/
-static void change_notify_reply_packet(const uint8 *request_buf,
+static void change_notify_reply_packet(connection_struct *conn,
+ const uint8 *request_buf,
NTSTATUS error_code)
{
char outbuf[smb_size+38];
@@ -142,15 +143,18 @@ static void change_notify_reply_packet(const uint8 *request_buf,
* Seems NT needs a transact command with an error code
* in it. This is a longer packet than a simple error.
*/
- set_message(outbuf,18,0,False);
+ srv_set_message(outbuf,18,0,False);
show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server_cleanly("change_notify_reply_packet: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),
+ outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
"failed.");
}
-void change_notify_reply(const uint8 *request_buf, uint32 max_param,
+void change_notify_reply(connection_struct *conn,
+ const uint8 *request_buf, uint32 max_param,
struct notify_change_buf *notify_buf)
{
prs_struct ps;
@@ -158,7 +162,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
uint8 tmp_request[smb_size];
if (notify_buf->num_changes == -1) {
- change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
notify_buf->num_changes = 0;
return;
}
@@ -171,12 +175,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
* We exceed what the client is willing to accept. Send
* nothing.
*/
- change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_OK);
goto done;
}
if (!(req = talloc(talloc_tos(), struct smb_request))) {
- change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
+ change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY);
goto done;
}
@@ -189,9 +193,9 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param,
smb_setlen((char *)tmp_request, smb_size);
SCVAL(tmp_request, smb_wct, 0);
- init_smb_request(req, tmp_request,0);
+ init_smb_request(req, tmp_request,0, conn->encrypted_tid);
- send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps),
+ send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
prs_offset(&ps), NULL, 0);
done:
@@ -242,9 +246,10 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
return status;
}
-NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
- uint32 filter, bool recursive,
- struct files_struct *fsp)
+NTSTATUS change_notify_add_request(const struct smb_request *req,
+ uint32 max_param,
+ uint32 filter, bool recursive,
+ struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
@@ -258,7 +263,7 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
request->mid_map = map;
map->req = request;
- memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
+ memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf));
request->max_param = max_param;
request->filter = filter;
request->fsp = fsp;
@@ -267,11 +272,11 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param,
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
- map->mid = SVAL(inbuf, smb_mid);
+ map->mid = SVAL(req->inbuf, smb_mid);
DLIST_ADD(notify_changes_by_mid, map);
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(req->inbuf,smb_mid));
return NT_STATUS_OK;
}
@@ -324,7 +329,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid)
return;
}
- change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED);
+ change_notify_reply_packet(map->req->fsp->conn,
+ map->req->request_buf, NT_STATUS_CANCELLED);
change_notify_remove_request(map->req);
}
@@ -340,7 +346,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
}
while (fsp->notify->requests != NULL) {
- change_notify_reply_packet(
+ change_notify_reply_packet(fsp->conn,
fsp->notify->requests->request_buf, status);
change_notify_remove_request(fsp->notify->requests);
}
@@ -434,7 +440,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
* TODO: do we have to walk the lists of requests pending?
*/
- change_notify_reply(fsp->notify->requests->request_buf,
+ change_notify_reply(fsp->conn,
+ fsp->notify->requests->request_buf,
fsp->notify->requests->max_param,
fsp->notify);
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index cb98a8139c..a51f3afd82 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -66,7 +66,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-void send_nt_replies(struct smb_request *req, NTSTATUS nt_error,
+void send_nt_replies(connection_struct *conn,
+ struct smb_request *req, NTSTATUS nt_error,
char *params, int paramsize,
char *pdata, int datasize)
{
@@ -242,8 +243,10 @@ void send_nt_replies(struct smb_request *req, NTSTATUS nt_error,
/* Send the packet */
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf)) {
- exit_server_cleanly("send_nt_replies: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn))) {
+ exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
}
TALLOC_FREE(req->outbuf);
@@ -410,8 +413,9 @@ static void do_ntcreate_pipe_open(connection_struct *conn,
Reply to an NT create and X call.
****************************************************************************/
-void reply_ntcreate_and_X(connection_struct *conn, struct smb_request *req)
+void reply_ntcreate_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 flags;
uint32 access_mask;
@@ -726,7 +730,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn,
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
return;
}
@@ -1080,7 +1084,7 @@ static void call_nt_transact_create(connection_struct *conn,
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(req, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
return;
}
@@ -1090,7 +1094,7 @@ static void call_nt_transact_create(connection_struct *conn,
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ntcancel(connection_struct *conn, struct smb_request *req)
+void reply_ntcancel(struct smb_request *req)
{
/*
* Go through and cancel any pending change notifies.
@@ -1252,8 +1256,9 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
Reply to a NT rename request.
****************************************************************************/
-void reply_ntrename(connection_struct *conn, struct smb_request *req)
+void reply_ntrename(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *oldname = NULL;
char *newname = NULL;
char *p;
@@ -1474,7 +1479,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
* here.
*/
- change_notify_reply(req->inbuf, max_param_count, fsp->notify);
+ change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify);
/*
* change_notify_reply() above has independently sent its
@@ -1487,7 +1492,9 @@ static void call_nt_transact_notify_change(connection_struct *conn,
* No changes pending, queue the request
*/
- status = change_notify_add_request(req->inbuf, max_param_count, filter,
+ status = change_notify_add_request(req,
+ max_param_count,
+ filter,
recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -1554,7 +1561,7 @@ static void call_nt_transact_rename(connection_struct *conn,
/*
* Rename was successful.
*/
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
fsp->fsp_name, new_name));
@@ -1650,14 +1657,14 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
return;
}
- sd_size = sec_desc_size(psd);
+ sd_size = ndr_size_security_descriptor(psd, 0);
DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
SIVAL(params,0,(uint32)sd_size);
if (max_data_count < sd_size) {
- send_nt_replies(req, NT_STATUS_BUFFER_TOO_SMALL,
+ send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
params, 4, *ppdata, 0);
TALLOC_FREE(frame);
return;
@@ -1686,7 +1693,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
SMB_ASSERT(sd_size == blob.length);
memcpy(data, blob.data, sd_size);
- send_nt_replies(req, NT_STATUS_OK, params, 4, data, (int)sd_size);
+ send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
TALLOC_FREE(frame);
return;
@@ -1744,7 +1751,7 @@ static void call_nt_transact_set_security_desc(connection_struct *conn,
}
done:
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
}
@@ -1793,7 +1800,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
so we can know if we need to pre-allocate or not */
DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
case FSCTL_CREATE_OR_GET_OBJECT_ID:
@@ -1819,7 +1826,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
push_file_id_16(pdata, &fsp->file_id);
memcpy(pdata+16,create_volume_objectid(conn,objid),16);
push_file_id_16(pdata+32, &fsp->file_id);
- send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
pdata, data_count);
return;
}
@@ -1964,7 +1971,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
talloc_destroy(shadow_data->mem_ctx);
- send_nt_replies(req, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0,
pdata, data_count);
return;
@@ -2020,7 +2027,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
*/
/* this works for now... */
- send_nt_replies(req, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
}
default:
@@ -2174,7 +2181,8 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)<max_data_count));
tmp_list=tmp_list->next,entry+=entry_len,qt_len+=entry_len) {
- sid_len = sid_size(&tmp_list->quotas->sid);
+ sid_len = ndr_size_dom_sid(
+ &tmp_list->quotas->sid, 0);
entry_len = 40 + sid_len;
/* nextoffset entry 4 bytes */
@@ -2305,7 +2313,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
break;
}
- send_nt_replies(req, nt_status, params, param_len,
+ send_nt_replies(conn, req, nt_status, params, param_len,
pdata, data_len);
}
@@ -2435,7 +2443,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
return;
}
- send_nt_replies(req, NT_STATUS_OK, params, param_len,
+ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
pdata, data_len);
}
#endif /* HAVE_SYS_QUOTAS */
@@ -2572,8 +2580,9 @@ static void handle_nttrans(connection_struct *conn,
Reply to a SMBNTtrans.
****************************************************************************/
-void reply_nttrans(connection_struct *conn, struct smb_request *req)
+void reply_nttrans(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint32 pscnt;
uint32 psoff;
uint32 dscnt;
@@ -2763,8 +2772,9 @@ void reply_nttrans(connection_struct *conn, struct smb_request *req)
Reply to a SMBnttranss
****************************************************************************/
-void reply_nttranss(connection_struct *conn, struct smb_request *req)
+void reply_nttranss(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 9428b47b6a..f178102fdd 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1405,7 +1405,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
#endif /* O_SYNC */
- if (posix_open & (access_mask & FILE_APPEND_DATA)) {
+ if (posix_open && (access_mask & FILE_APPEND_DATA)) {
flags2 |= O_APPEND;
}
@@ -1864,10 +1864,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
- file_set_dosmode(conn, fname,
- new_dos_attributes | aARCH, NULL,
- parent_dir,
- true);
+ SMB_STRUCT_STAT tmp_sbuf;
+ SET_STAT_INVALID(tmp_sbuf);
+ if (file_set_dosmode(
+ conn, fname,
+ new_dos_attributes | aARCH,
+ &tmp_sbuf, parent_dir,
+ true) == 0) {
+ unx_mode = tmp_sbuf.st_mode;
+ }
}
}
}
@@ -2262,7 +2267,7 @@ NTSTATUS open_directory(connection_struct *conn,
return NT_STATUS_OK;
}
-NTSTATUS create_directory(connection_struct *conn, const char *directory)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
{
NTSTATUS status;
SMB_STRUCT_STAT sbuf;
@@ -2270,7 +2275,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory)
SET_STAT_INVALID(sbuf);
- status = open_directory(conn, NULL, directory, &sbuf,
+ status = open_directory(conn, req, directory, &sbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */
FILE_SHARE_NONE, /* Ignored for stat opens */
FILE_CREATE,
@@ -2601,16 +2606,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
uint32_t sec_info_sent = ALL_SECURITY_INFORMATION;
uint32_t saved_access_mask = fsp->access_mask;
- if (sd->owner_sid==0) {
+ if (sd->owner_sid == NULL) {
sec_info_sent &= ~OWNER_SECURITY_INFORMATION;
}
- if (sd->group_sid==0) {
+ if (sd->group_sid == NULL) {
sec_info_sent &= ~GROUP_SECURITY_INFORMATION;
}
- if (sd->sacl==0) {
+ if (sd->sacl == NULL) {
sec_info_sent &= ~SACL_SECURITY_INFORMATION;
}
- if (sd->dacl==0) {
+ if (sd->dacl == NULL) {
sec_info_sent &= ~DACL_SECURITY_INFORMATION;
}
@@ -2667,7 +2672,12 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
*pinfo = info;
}
if (psbuf != NULL) {
- *psbuf = sbuf;
+ if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) {
+ *psbuf = sbuf;
+ }
+ else {
+ SMB_VFS_FSTAT(fsp, fsp->fh->fd, psbuf);
+ }
}
return NT_STATUS_OK;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 961abd277b..277e07c178 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -252,7 +252,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
}
memset(result,'\0',smb_size);
- set_message(result,8,0,True);
+ srv_set_message(result,8,0,true);
SCVAL(result,smb_com,SMBlockingX);
SSVAL(result,smb_tid,fsp->conn->cnum);
SSVAL(result,smb_pid,0xFFFF);
@@ -449,8 +449,10 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
@@ -554,8 +556,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
@@ -631,8 +635,10 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
sign_state = srv_oplock_set_signing(False);
show_msg(break_msg);
- if (!send_smb(smbd_server_fd(), break_msg)) {
- exit_server_cleanly("oplock_break: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ break_msg,
+ IS_CONN_ENCRYPTED(fsp->conn))) {
+ exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
/* Restore the sign state to what it was. */
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 0ddc00c767..6b4b83d97d 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -291,7 +291,7 @@ void reply_pipe_read_and_X(struct smb_request *req)
return;
}
- set_message((char *)req->outbuf, 12, nread, False);
+ srv_set_message((char *)req->outbuf, 12, nread, False);
SSVAL(req->outbuf,smb_vwv5,nread);
SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index ee76f90bf5..fe32d57ff7 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -50,6 +50,73 @@ enum smb_read_errors *get_srv_read_error(void)
return &smb_read_error;
}
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
+{
+ size_t len;
+ size_t nwritten=0;
+ ssize_t ret;
+ char *buf_out = buffer;
+
+ /* Sign the outgoing packet if required. */
+ srv_calculate_sign_mac(buf_out);
+
+ if (do_encrypt) {
+ NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("send_smb: SMB encryption failed "
+ "on outgoing packet! Error %s\n",
+ nt_errstr(status) ));
+ return false;
+ }
+ }
+
+ len = smb_len(buf_out) + 4;
+
+ while (nwritten < len) {
+ ret = write_data(fd,buf_out+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ srv_free_enc_buffer(buf_out);
+ return false;
+ }
+ nwritten += ret;
+ }
+
+ srv_free_enc_buffer(buf_out);
+ return true;
+}
+
+/*******************************************************************
+ Setup the word count and byte count for a smb message.
+********************************************************************/
+
+int srv_set_message(char *buf,
+ int num_words,
+ int num_bytes,
+ bool zero)
+{
+ if (zero && (num_words || num_bytes)) {
+ memset(buf + smb_size,'\0',num_words*2 + num_bytes);
+ }
+ SCVAL(buf,smb_wct,num_words);
+ SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
+ return (smb_size + num_words*2 + num_bytes);
+}
+
+static bool valid_smb_header(const uint8_t *inbuf)
+{
+ if (is_encrypted_packet(inbuf)) {
+ return true;
+ }
+ return (strncmp(smb_base(inbuf),"\377SMB",4) == 0);
+}
+
/* Socket functions for smbd packet processing. */
static bool valid_packet_size(size_t len)
@@ -125,7 +192,7 @@ static ssize_t read_packet_remainder(int fd,
(2*14) + /* word count (including bcc) */ \
1 /* pad byte */)
-ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
+static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
const char lenbuf[4],
int fd,
char **buffer,
@@ -165,7 +232,7 @@ ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
* valid writeX call.
*/
- if (is_valid_writeX_buffer(writeX_header)) {
+ if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
/*
* If the data offset is beyond what
* we've read, drain the extra bytes.
@@ -273,7 +340,7 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
return -1;
}
- if (CVAL(lenbuf,0) != SMBkeepalive &&
+ if (CVAL(lenbuf,0) == 0 &&
min_recv_size &&
smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */
!srv_is_signing_active()) {
@@ -313,17 +380,36 @@ static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
return len + 4;
}
-ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
- unsigned int timeout, size_t *p_unread)
+static ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx,
+ int fd,
+ char **buffer,
+ unsigned int timeout,
+ size_t *p_unread,
+ bool *p_encrypted)
{
ssize_t len;
+ *p_encrypted = false;
+
len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout, p_unread);
if (len < 0) {
return -1;
}
+ if (is_encrypted_packet((uint8_t *)*buffer)) {
+ NTSTATUS status = srv_decrypt_buffer(*buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
+ "incoming packet! Error %s\n",
+ nt_errstr(status) ));
+ cond_set_smb_read_error(get_srv_read_error(),
+ SMB_READ_BAD_DECRYPT);
+ return -1;
+ }
+ *p_encrypted = true;
+ }
+
/* Check the incoming SMB signature. */
if (!srv_check_sign_mac(*buffer, true)) {
DEBUG(0, ("receive_smb: SMB Signature verification failed on "
@@ -341,7 +427,8 @@ ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
void init_smb_request(struct smb_request *req,
const uint8 *inbuf,
- size_t unread_bytes)
+ size_t unread_bytes,
+ bool encrypted)
{
size_t req_size = smb_len(inbuf) + 4;
/* Ensure we have at least smb_size bytes. */
@@ -357,6 +444,8 @@ void init_smb_request(struct smb_request *req,
req->tid = SVAL(inbuf, smb_tid);
req->wct = CVAL(inbuf, smb_wct);
req->unread_bytes = unread_bytes;
+ req->encrypted = encrypted;
+ req->conn = conn_find(req->tid);
/* Ensure we have at least wct words and 2 bytes of bcc. */
if (smb_size + req->wct*2 > req_size) {
@@ -414,6 +503,7 @@ static bool push_queued_message(struct smb_request *req,
msg->request_time = request_time;
msg->end_time = end_time;
+ msg->encrypted = req->encrypted;
if (private_data) {
msg->private_data = data_blob_talloc(msg, private_data,
@@ -689,7 +779,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
char **buffer,
size_t *buffer_len,
int timeout,
- size_t *p_unread)
+ size_t *p_unread,
+ bool *p_encrypted)
{
fd_set r_fds, w_fds;
int selrtn;
@@ -756,6 +847,7 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
return False;
}
*buffer_len = msg->buf.length;
+ *p_encrypted = msg->encrypted;
/* We leave this message on the queue so the open code can
know this is a retry. */
@@ -872,7 +964,8 @@ static bool receive_message_or_smb(TALLOC_CTX *mem_ctx,
goto again;
}
- len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0, p_unread);
+ len = receive_smb_talloc(mem_ctx, smbd_server_fd(),
+ buffer, 0, p_unread, p_encrypted);
if (len == -1) {
return False;
@@ -952,7 +1045,7 @@ force write permissions on print services.
*/
static const struct smb_message_struct {
const char *name;
- void (*fn_new)(connection_struct *conn, struct smb_request *req);
+ void (*fn_new)(struct smb_request *req);
int flags;
} smb_messages[256] = {
@@ -1239,7 +1332,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
}
construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
- set_message((char *)req->outbuf, num_words, num_bytes, False);
+ srv_set_message((char *)req->outbuf, num_words, num_bytes, false);
/*
* Zero out the word area, the caller has to take care of the bcc area
* himself
@@ -1297,11 +1390,11 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len)
find.
****************************************************************************/
-static void switch_message(uint8 type, struct smb_request *req, int size)
+static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
{
int flags;
uint16 session_tag;
- connection_struct *conn;
+ connection_struct *conn = NULL;
static uint16 last_session_tag = UID_FIELD_INVALID;
@@ -1309,7 +1402,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
/* Make sure this is an SMB packet. smb_size contains NetBIOS header
* so subtract 4 from it. */
- if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0)
+ if (!valid_smb_header(req->inbuf)
|| (size < (smb_size - 4))) {
DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
smb_len(req->inbuf)));
@@ -1320,7 +1413,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
DEBUG(0,("Unknown message type %d!\n",type));
smb_dump("Unknown", 1, (char *)req->inbuf, size);
reply_unknown_new(req, type);
- return;
+ return NULL;
}
flags = smb_messages[type].flags;
@@ -1328,7 +1421,7 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
/* In share mode security we must ignore the vuid. */
session_tag = (lp_security() == SEC_SHARE)
? UID_FIELD_INVALID : req->vuid;
- conn = conn_find(req->tid);
+ conn = req->conn;
DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
(int)sys_getpid(), (unsigned long)conn));
@@ -1373,12 +1466,12 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
} else {
reply_doserror(req, ERRSRV, ERRinvnid);
}
- return;
+ return NULL;
}
if (!change_to_user(conn,session_tag)) {
reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
- return;
+ return conn;
}
/* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
@@ -1386,13 +1479,13 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
/* Does it need write permission? */
if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
- return;
+ return conn;
}
/* IPC services are limited */
if (IS_IPC(conn) && !(flags & CAN_IPC)) {
reply_doserror(req, ERRSRV,ERRaccess);
- return;
+ return conn;
}
} else {
/* This call needs to be run as root */
@@ -1401,11 +1494,24 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
/* load service specific parameters */
if (conn) {
+ if (req->encrypted) {
+ conn->encrypted_tid = true;
+ /* encrypted required from now on. */
+ conn->encrypt_level = Required;
+ } else if (ENCRYPTION_REQUIRED(conn)) {
+ uint8 com = CVAL(req->inbuf,smb_com);
+ if (com != SMBtrans2 && com != SMBtranss2) {
+ exit_server_cleanly("encryption required "
+ "on connection");
+ return conn;
+ }
+ }
+
if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
(flags & (AS_USER|DO_CHDIR)
?True:False))) {
reply_doserror(req, ERRSRV, ERRaccess);
- return;
+ return conn;
}
conn->num_smb_operations++;
}
@@ -1416,19 +1522,21 @@ static void switch_message(uint8 type, struct smb_request *req, int size)
!check_access(smbd_server_fd(), lp_hostsallow(-1),
lp_hostsdeny(-1)))) {
reply_doserror(req, ERRSRV, ERRaccess);
- return;
+ return conn;
}
- smb_messages[type].fn_new(conn, req);
+ smb_messages[type].fn_new(req);
+ return req->conn;
}
/****************************************************************************
Construct a reply to the incoming packet.
****************************************************************************/
-static void construct_reply(char *inbuf, int size, size_t unread_bytes)
+static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
{
uint8 type = CVAL(inbuf,smb_com);
+ connection_struct *conn;
struct smb_request *req;
chain_size = 0;
@@ -1438,9 +1546,9 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
if (!(req = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req, (uint8 *)inbuf, unread_bytes);
+ init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
- switch_message(type, req, size);
+ conn = switch_message(type, req, size);
if (req->unread_bytes) {
/* writeX failed. drain socket. */
@@ -1459,8 +1567,10 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
show_msg((char *)req->outbuf);
}
- if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) {
- exit_server_cleanly("construct_reply: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
+ exit_server_cleanly("construct_reply: srv_send_smb failed.");
}
TALLOC_FREE(req);
@@ -1472,7 +1582,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes)
Process an smb from the client
****************************************************************************/
-static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
+static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted)
{
static int trans_num;
int msg_type = CVAL(inbuf,0);
@@ -1493,7 +1603,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ( "Connection denied from %s\n",
client_addr(get_client_fd(),addr,sizeof(addr)) ) );
- (void)send_smb(smbd_server_fd(),(char *)buf);
+ (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
exit_server_cleanly("connection denied");
}
}
@@ -1514,7 +1624,7 @@ static void process_smb(char *inbuf, size_t nread, size_t unread_bytes)
show_msg(inbuf);
- construct_reply(inbuf,nread,unread_bytes);
+ construct_reply(inbuf,nread,unread_bytes,encrypted);
trans_num++;
}
@@ -1551,7 +1661,7 @@ void remove_from_common_flags2(uint32 v)
void construct_reply_common(const char *inbuf, char *outbuf)
{
- set_message(outbuf,0,0,False);
+ srv_set_message(outbuf,0,0,false);
SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
SIVAL(outbuf,smb_rcls,0);
@@ -1674,7 +1784,7 @@ void chain_reply(struct smb_request *req)
if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
smb_panic("could not allocate smb_request");
}
- init_smb_request(req2, (uint8 *)inbuf2,0);
+ init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted);
/* process the request */
switch_message(smb_com2, req2, new_size);
@@ -1960,6 +2070,7 @@ void smbd_process(void)
int num_echos;
char *inbuf;
size_t inbuf_len;
+ bool encrypted = false;
TALLOC_CTX *frame = talloc_stackframe();
errno = 0;
@@ -1975,7 +2086,9 @@ void smbd_process(void)
run_events(smbd_event_context(), 0, NULL, NULL);
while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
- select_timeout, &unread_bytes)) {
+ select_timeout,
+ &unread_bytes,
+ &encrypted)) {
if(!timeout_processing(&select_timeout,
&last_timeout_processing_time))
return;
@@ -1994,7 +2107,7 @@ void smbd_process(void)
*/
num_echos = smb_echo_count;
- process_smb(inbuf, inbuf_len, unread_bytes);
+ process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
TALLOC_FREE(inbuf);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 575ca13ff6..d5e683ca3c 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -391,7 +391,7 @@ void reply_special(char *inbuf)
/*
* We only really use 4 bytes of the outbuf, but for the smb_setlen
- * calculation & friends (send_smb uses that) we need the full smb
+ * calculation & friends (srv_send_smb uses that) we need the full smb
* header.
*/
char outbuf[smb_size];
@@ -470,7 +470,7 @@ void reply_special(char *inbuf)
DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
msg_type, msg_flags));
- send_smb(smbd_server_fd(), outbuf);
+ srv_send_smb(smbd_server_fd(), outbuf, false);
return;
}
@@ -479,8 +479,9 @@ void reply_special(char *inbuf)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tcon(connection_struct *conn, struct smb_request *req)
+void reply_tcon(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
const char *service;
char *service_buf = NULL;
char *password = NULL;
@@ -523,6 +524,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)
password_blob = data_blob(password, pwlen+1);
conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
+ req->conn = conn;
data_blob_clear_free(&password_blob);
@@ -549,8 +551,9 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
+void reply_tcon_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *service = NULL;
DATA_BLOB password;
TALLOC_CTX *ctx = talloc_tos();
@@ -578,6 +581,8 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
/* we might have to close an old one */
if ((tcon_flags & 0x1) && conn) {
close_cnum(conn,req->vuid);
+ req->conn = NULL;
+ conn = NULL;
}
if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
@@ -646,6 +651,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
conn = make_connection(service, password, client_devicetype,
req->vuid, &nt_status);
+ req->conn =conn;
data_blob_clear_free(&password);
@@ -731,17 +737,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
Reply to an unknown type.
****************************************************************************/
-int reply_unknown(char *inbuf,char *outbuf)
-{
- int type;
- type = CVAL(inbuf,smb_com);
-
- DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
- smb_fn_name(type), type, type));
-
- return(ERROR_DOS(ERRSRV,ERRunknownsmb));
-}
-
void reply_unknown_new(struct smb_request *req, uint8 type)
{
DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
@@ -755,8 +750,9 @@ void reply_unknown_new(struct smb_request *req, uint8 type)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ioctl(connection_struct *conn, struct smb_request *req)
+void reply_ioctl(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint16 device;
uint16 function;
uint32 ioctl_code;
@@ -844,8 +840,9 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
Reply to a checkpath.
****************************************************************************/
-void reply_checkpath(connection_struct *conn, struct smb_request *req)
+void reply_checkpath(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
@@ -938,8 +935,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
Reply to a getatr.
****************************************************************************/
-void reply_getatr(connection_struct *conn, struct smb_request *req)
+void reply_getatr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
SMB_STRUCT_STAT sbuf;
int mode=0;
@@ -1039,8 +1037,9 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
Reply to a setatr.
****************************************************************************/
-void reply_setatr(connection_struct *conn, struct smb_request *req)
+void reply_setatr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
int mode;
time_t mtime;
@@ -1139,8 +1138,9 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
Reply to a dskattr.
****************************************************************************/
-void reply_dskattr(connection_struct *conn, struct smb_request *req)
+void reply_dskattr(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT dfree,dsize,bsize;
START_PROFILE(SMBdskattr);
@@ -1191,8 +1191,9 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
Can be called from SMBsearch, SMBffirst or SMBfunique.
****************************************************************************/
-void reply_search(connection_struct *conn, struct smb_request *req)
+void reply_search(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *mask = NULL;
char *directory = NULL;
char *fname = NULL;
@@ -1493,7 +1494,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
Reply to a fclose (stop directory search).
****************************************************************************/
-void reply_fclose(connection_struct *conn, struct smb_request *req)
+void reply_fclose(struct smb_request *req)
{
int status_len;
char status[21];
@@ -1557,8 +1558,9 @@ void reply_fclose(connection_struct *conn, struct smb_request *req)
Reply to an open.
****************************************************************************/
-void reply_open(connection_struct *conn, struct smb_request *req)
+void reply_open(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 fattr=0;
SMB_OFF_T size = 0;
@@ -1597,51 +1599,30 @@ void reply_open(connection_struct *conn, struct smb_request *req)
return;
}
- status = resolve_dfspath(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- &fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- END_PROFILE(SMBopen);
- return;
- }
- reply_nterror(req, status);
- END_PROFILE(SMBopen);
- return;
- }
-
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBopen);
- return;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBopen);
- return;
- }
-
- if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
- &access_mask, &share_mode, &create_disposition, &create_options)) {
+ if (!map_open_params_to_ntcreate(
+ fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
+ &share_mode, &create_disposition, &create_options)) {
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
END_PROFILE(SMBopen);
return;
}
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- access_mask,
- share_mode,
- create_disposition,
- create_options,
- dos_attr,
- oplock_request,
- &info, &fsp);
+ status = create_file(conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ dos_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
@@ -1694,8 +1675,9 @@ void reply_open(connection_struct *conn, struct smb_request *req)
Reply to an open and X.
****************************************************************************/
-void reply_open_and_X(connection_struct *conn, struct smb_request *req)
+void reply_open_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint16 open_flags;
int deny_mode;
@@ -1762,53 +1744,30 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
return;
}
- status = resolve_dfspath(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- &fname);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBopenX);
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- return;
- }
- reply_nterror(req, status);
- return;
- }
-
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBopenX);
- return;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBopenX);
- return;
- }
-
- if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
- &access_mask,
- &share_mode,
- &create_disposition,
- &create_options)) {
+ if (!map_open_params_to_ntcreate(
+ fname, deny_mode, smb_ofun, &access_mask,
+ &share_mode, &create_disposition, &create_options)) {
reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
END_PROFILE(SMBopenX);
return;
}
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- access_mask,
- share_mode,
- create_disposition,
- create_options,
- smb_attr,
- oplock_request,
- &smb_action, &fsp);
+ status = create_file(conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ smb_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
@@ -1905,10 +1864,9 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
/****************************************************************************
Reply to a SMBulogoffX.
- conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
+void reply_ulogoffX(struct smb_request *req)
{
user_struct *vuser;
@@ -1941,8 +1899,9 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
Reply to a mknew or a create.
****************************************************************************/
-void reply_mknew(connection_struct *conn, struct smb_request *req)
+void reply_mknew(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
int com;
uint32 fattr = 0;
@@ -1982,35 +1941,6 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
return;
}
- status = resolve_dfspath(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- &fname);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBcreate);
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- return;
- }
- reply_nterror(req, status);
- return;
- }
-
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBcreate);
- return;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- END_PROFILE(SMBcreate);
- return;
- }
-
if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - "
"please report this\n", fname));
@@ -2024,15 +1954,22 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
create_disposition = FILE_OVERWRITE_IF;
}
- /* Open file using ntcreate. */
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- access_mask,
- share_mode,
- create_disposition,
- create_options,
- fattr,
- oplock_request,
- NULL, &fsp);
+ status = create_file(conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ fattr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
@@ -2072,8 +2009,9 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
Reply to a create temporary file.
****************************************************************************/
-void reply_ctemp(connection_struct *conn, struct smb_request *req)
+void reply_ctemp(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *fname = NULL;
uint32 fattr;
files_struct *fsp;
@@ -2538,8 +2476,9 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
Reply to a unlink
****************************************************************************/
-void reply_unlink(connection_struct *conn, struct smb_request *req)
+void reply_unlink(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
uint32 dirtype;
NTSTATUS status;
@@ -2780,8 +2719,9 @@ normal_readbraw:
Reply to a readbraw (core+ protocol).
****************************************************************************/
-void reply_readbraw(connection_struct *conn, struct smb_request *req)
+void reply_readbraw(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t maxcount,mincount;
size_t nread = 0;
SMB_OFF_T startpos;
@@ -2791,8 +2731,8 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
START_PROFILE(SMBreadbraw);
- if (srv_is_signing_active()) {
- exit_server_cleanly("reply_readbraw: SMB signing is active - "
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+ exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
"raw reads/writes are disallowed.");
}
@@ -2930,8 +2870,9 @@ void reply_readbraw(connection_struct *conn, struct smb_request *req)
Reply to a lockread (core+ protocol).
****************************************************************************/
-void reply_lockread(connection_struct *conn, struct smb_request *req)
+void reply_lockread(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t nread = -1;
char *data;
SMB_OFF_T startpos;
@@ -3017,7 +2958,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
return;
}
- set_message((char *)req->outbuf, 5, nread+3, False);
+ srv_set_message((char *)req->outbuf, 5, nread+3, False);
SSVAL(req->outbuf,smb_vwv0,nread);
SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3039,8 +2980,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
Reply to a read.
****************************************************************************/
-void reply_read(connection_struct *conn, struct smb_request *req)
+void reply_read(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtoread;
ssize_t nread = 0;
char *data;
@@ -3104,7 +3046,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
return;
}
- set_message((char *)req->outbuf, 5, nread+3, False);
+ srv_set_message((char *)req->outbuf, 5, nread+3, False);
SSVAL(req->outbuf,smb_vwv0,nread);
SSVAL(req->outbuf,smb_vwv5,nread+3);
@@ -3127,7 +3069,7 @@ static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
int outsize;
char *data;
- outsize = set_message(outbuf,12,smb_maxcnt,False);
+ outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
data = smb_buf(outbuf);
memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
@@ -3177,6 +3119,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
*/
if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
+ !is_encrypted_packet(req->inbuf) &&
lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
@@ -3283,8 +3226,9 @@ normal_read:
Reply to a read and X.
****************************************************************************/
-void reply_read_and_X(connection_struct *conn, struct smb_request *req)
+void reply_read_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
SMB_OFF_T startpos;
size_t smb_maxcnt;
@@ -3332,8 +3276,8 @@ void reply_read_and_X(connection_struct *conn, struct smb_request *req)
END_PROFILE(SMBreadX);
return;
}
- /* We currently don't do this on signed data. */
- if (srv_is_signing_active()) {
+ /* We currently don't do this on signed or sealed data. */
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
@@ -3412,8 +3356,9 @@ void error_to_writebrawerr(struct smb_request *req)
Reply to a writebraw (core+ or LANMAN1.0 protocol).
****************************************************************************/
-void reply_writebraw(connection_struct *conn, struct smb_request *req)
+void reply_writebraw(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int outsize = 0;
char *buf = NULL;
ssize_t nwritten=0;
@@ -3524,13 +3469,15 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
* it to send more bytes */
memcpy(buf, req->inbuf, smb_size);
- outsize = set_message(buf,
+ outsize = srv_set_message(buf,
Protocol>PROTOCOL_COREPLUS?1:0,0,True);
SCVAL(buf,smb_com,SMBwritebraw);
SSVALS(buf,smb_vwv0,0xFFFF);
show_msg(buf);
- if (!send_smb(smbd_server_fd(),buf)) {
- exit_server_cleanly("reply_writebraw: send_smb "
+ if (!srv_send_smb(smbd_server_fd(),
+ buf,
+ IS_CONN_ENCRYPTED(conn))) {
+ exit_server_cleanly("reply_writebraw: srv_send_smb "
"failed.");
}
@@ -3639,8 +3586,9 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
Reply to a writeunlock (core+).
****************************************************************************/
-void reply_writeunlock(connection_struct *conn, struct smb_request *req)
+void reply_writeunlock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
ssize_t nwritten = -1;
size_t numtowrite;
SMB_OFF_T startpos;
@@ -3738,8 +3686,9 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req)
Reply to a write.
****************************************************************************/
-void reply_write(connection_struct *conn, struct smb_request *req)
+void reply_write(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtowrite;
ssize_t nwritten = -1;
SMB_OFF_T startpos;
@@ -3849,13 +3798,19 @@ void reply_write(connection_struct *conn, struct smb_request *req)
(2*14) + /* word count (including bcc) */ \
1 /* pad byte */)
-bool is_valid_writeX_buffer(const char *inbuf)
+bool is_valid_writeX_buffer(const uint8_t *inbuf)
{
size_t numtowrite;
connection_struct *conn = NULL;
unsigned int doff = 0;
size_t len = smb_len_large(inbuf);
+ if (is_encrypted_packet(inbuf)) {
+ /* Can't do this on encrypted
+ * connections. */
+ return false;
+ }
+
if (CVAL(inbuf,smb_com) != SMBwriteX) {
return false;
}
@@ -3920,8 +3875,9 @@ bool is_valid_writeX_buffer(const char *inbuf)
Reply to a write and X.
****************************************************************************/
-void reply_write_and_X(connection_struct *conn, struct smb_request *req)
+void reply_write_and_X(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
SMB_OFF_T startpos;
size_t numtowrite;
@@ -4088,8 +4044,9 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
Reply to a lseek.
****************************************************************************/
-void reply_lseek(connection_struct *conn, struct smb_request *req)
+void reply_lseek(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_OFF_T startpos;
SMB_OFF_T res= -1;
int mode,umode;
@@ -4175,8 +4132,9 @@ void reply_lseek(connection_struct *conn, struct smb_request *req)
Reply to a flush.
****************************************************************************/
-void reply_flush(connection_struct *conn, struct smb_request *req)
+void reply_flush(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
uint16 fnum;
files_struct *fsp;
@@ -4219,7 +4177,7 @@ void reply_flush(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_exit(connection_struct *conn, struct smb_request *req)
+void reply_exit(struct smb_request *req)
{
START_PROFILE(SMBexit);
@@ -4237,8 +4195,9 @@ void reply_exit(connection_struct *conn, struct smb_request *req)
Reply to a close - has to deal with closing a directory opened by NT SMB's.
****************************************************************************/
-void reply_close(connection_struct *conn, struct smb_request *req)
+void reply_close(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
@@ -4315,8 +4274,9 @@ void reply_close(connection_struct *conn, struct smb_request *req)
Reply to a writeclose (Core+ protocol).
****************************************************************************/
-void reply_writeclose(connection_struct *conn, struct smb_request *req)
+void reply_writeclose(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
size_t numtowrite;
ssize_t nwritten = -1;
NTSTATUS close_status = NT_STATUS_OK;
@@ -4404,8 +4364,9 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req)
Reply to a lock.
****************************************************************************/
-void reply_lock(connection_struct *conn, struct smb_request *req)
+void reply_lock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp;
@@ -4463,8 +4424,9 @@ void reply_lock(connection_struct *conn, struct smb_request *req)
Reply to a unlock.
****************************************************************************/
-void reply_unlock(connection_struct *conn, struct smb_request *req)
+void reply_unlock(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp;
@@ -4517,8 +4479,9 @@ void reply_unlock(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_tdis(connection_struct *conn, struct smb_request *req)
+void reply_tdis(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
START_PROFILE(SMBtdis);
if (!conn) {
@@ -4531,6 +4494,7 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
conn->used = False;
close_cnum(conn,req->vuid);
+ req->conn = NULL;
reply_outbuf(req, 0, 0);
END_PROFILE(SMBtdis);
@@ -4542,8 +4506,9 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-void reply_echo(connection_struct *conn, struct smb_request *req)
+void reply_echo(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int smb_reverb;
int seq_num;
unsigned int data_len = smb_buflen(req->inbuf);
@@ -4581,8 +4546,10 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
SSVAL(req->outbuf,smb_vwv0,seq_num);
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("reply_echo: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)||req->encrypted))
+ exit_server_cleanly("reply_echo: srv_send_smb failed.");
}
DEBUG(3,("echo %d times\n", smb_reverb));
@@ -4599,8 +4566,9 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
Reply to a printopen.
****************************************************************************/
-void reply_printopen(connection_struct *conn, struct smb_request *req)
+void reply_printopen(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
NTSTATUS status;
@@ -4641,8 +4609,9 @@ void reply_printopen(connection_struct *conn, struct smb_request *req)
Reply to a printclose.
****************************************************************************/
-void reply_printclose(connection_struct *conn, struct smb_request *req)
+void reply_printclose(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
NTSTATUS status;
@@ -4686,8 +4655,9 @@ void reply_printclose(connection_struct *conn, struct smb_request *req)
Reply to a printqueue.
****************************************************************************/
-void reply_printqueue(connection_struct *conn, struct smb_request *req)
+void reply_printqueue(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int max_count;
int start_index;
@@ -4778,8 +4748,9 @@ void reply_printqueue(connection_struct *conn, struct smb_request *req)
Reply to a printwrite.
****************************************************************************/
-void reply_printwrite(connection_struct *conn, struct smb_request *req)
+void reply_printwrite(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
int numtowrite;
char *data;
files_struct *fsp;
@@ -4837,8 +4808,9 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
Reply to a mkdir.
****************************************************************************/
-void reply_mkdir(connection_struct *conn, struct smb_request *req)
+void reply_mkdir(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *directory = NULL;
NTSTATUS status;
SMB_STRUCT_STAT sbuf;
@@ -4885,7 +4857,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
return;
}
- status = create_directory(conn, directory);
+ status = create_directory(conn, req, directory);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -5105,8 +5077,9 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
Reply to a rmdir.
****************************************************************************/
-void reply_rmdir(connection_struct *conn, struct smb_request *req)
+void reply_rmdir(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *directory = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
@@ -5889,8 +5862,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
Reply to a mv.
****************************************************************************/
-void reply_mv(connection_struct *conn, struct smb_request *req)
+void reply_mv(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
char *newname = NULL;
char *p;
@@ -6120,8 +6094,9 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
Reply to a file copy.
****************************************************************************/
-void reply_copy(connection_struct *conn, struct smb_request *req)
+void reply_copy(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
char *name = NULL;
char *newname = NULL;
char *directory = NULL;
@@ -6583,8 +6558,9 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_forma
Reply to a lockingX request.
****************************************************************************/
-void reply_lockingX(connection_struct *conn, struct smb_request *req)
+void reply_lockingX(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
files_struct *fsp;
unsigned char locktype;
unsigned char oplocklevel;
@@ -6858,8 +6834,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
* onto the blocking lock queue.
*/
if(push_blocking_lock_request(br_lck,
- (char *)req->inbuf,
- smb_len(req->inbuf)+4,
+ req,
fsp,
lock_timeout,
i,
@@ -6942,7 +6917,7 @@ void reply_lockingX(connection_struct *conn, struct smb_request *req)
please contact vl@samba.org
****************************************************************************/
-void reply_readbmpx(connection_struct *conn, struct smb_request *req)
+void reply_readbmpx(struct smb_request *req)
{
START_PROFILE(SMBreadBmpx);
reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -6956,7 +6931,7 @@ void reply_readbmpx(connection_struct *conn, struct smb_request *req)
please contact vl@samba.org
****************************************************************************/
-void reply_readbs(connection_struct *conn, struct smb_request *req)
+void reply_readbs(struct smb_request *req)
{
START_PROFILE(SMBreadBs);
reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -6968,8 +6943,9 @@ void reply_readbs(connection_struct *conn, struct smb_request *req)
Reply to a SMBsetattrE.
****************************************************************************/
-void reply_setattrE(connection_struct *conn, struct smb_request *req)
+void reply_setattrE(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
struct timespec ts[2];
files_struct *fsp;
@@ -7046,7 +7022,7 @@ void reply_setattrE(connection_struct *conn, struct smb_request *req)
please contact vl@samba.org
****************************************************************************/
-void reply_writebmpx(connection_struct *conn, struct smb_request *req)
+void reply_writebmpx(struct smb_request *req)
{
START_PROFILE(SMBwriteBmpx);
reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -7060,7 +7036,7 @@ void reply_writebmpx(connection_struct *conn, struct smb_request *req)
please contact vl@samba.org
****************************************************************************/
-void reply_writebs(connection_struct *conn, struct smb_request *req)
+void reply_writebs(struct smb_request *req)
{
START_PROFILE(SMBwriteBs);
reply_doserror(req, ERRSRV, ERRuseSTD);
@@ -7072,8 +7048,9 @@ void reply_writebs(connection_struct *conn, struct smb_request *req)
Reply to a SMBgetattrE.
****************************************************************************/
-void reply_getattrE(connection_struct *conn, struct smb_request *req)
+void reply_getattrE(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
new file mode 100644
index 0000000000..21fca73fea
--- /dev/null
+++ b/source3/smbd/seal.c
@@ -0,0 +1,726 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB Transport encryption (sealing) code - server code.
+ Copyright (C) Jeremy Allison 2007.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/******************************************************************************
+ Server side encryption.
+******************************************************************************/
+
+/******************************************************************************
+ Global server state.
+******************************************************************************/
+
+struct smb_srv_trans_enc_ctx {
+ struct smb_trans_enc_state *es;
+ AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */
+};
+
+static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx;
+static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx;
+
+/******************************************************************************
+ Return global enc context - this must change if we ever do multiple contexts.
+******************************************************************************/
+
+uint16_t srv_enc_ctx(void)
+{
+ return srv_trans_enc_ctx->es->enc_ctx_num;
+}
+
+/******************************************************************************
+ Is this an incoming encrypted packet ?
+******************************************************************************/
+
+bool is_encrypted_packet(const uint8_t *inbuf)
+{
+ NTSTATUS status;
+ uint16_t enc_num;
+
+ /* Ignore non-session messages. */
+ if(CVAL(inbuf,0)) {
+ return false;
+ }
+
+ status = get_enc_ctx_num(inbuf, &enc_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
+ if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) {
+ return true;
+ }
+ return false;
+}
+
+/******************************************************************************
+ Create an auth_ntlmssp_state and ensure pointer copy is correct.
+******************************************************************************/
+
+static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
+{
+ NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return nt_status_squash(status);
+ }
+
+ /*
+ * We must remember to update the pointer copy for the common
+ * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
+ */
+ ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state;
+ return status;
+}
+
+/******************************************************************************
+ Destroy an auth_ntlmssp_state and ensure pointer copy is correct.
+******************************************************************************/
+
+static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
+{
+ /*
+ * We must remember to update the pointer copy for the common
+ * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
+ */
+
+ if (ec->auth_ntlmssp_state) {
+ auth_ntlmssp_end(&ec->auth_ntlmssp_state);
+ /* The auth_ntlmssp_end killed this already. */
+ ec->es->s.ntlmssp_state = NULL;
+ }
+}
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+
+/******************************************************************************
+ Import a name.
+******************************************************************************/
+
+static NTSTATUS get_srv_gss_creds(const char *service,
+ const char *name,
+ gss_cred_usage_t cred_type,
+ gss_cred_id_t *p_srv_cred)
+{
+ OM_uint32 ret;
+ OM_uint32 min;
+ gss_name_t srv_name;
+ gss_buffer_desc input_name;
+ char *host_princ_s = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ gss_OID_desc nt_hostbased_service =
+ {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
+
+ asprintf(&host_princ_s, "%s@%s", service, name);
+ if (host_princ_s == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ input_name.value = host_princ_s;
+ input_name.length = strlen(host_princ_s) + 1;
+
+ ret = gss_import_name(&min,
+ &input_name,
+ &nt_hostbased_service,
+ &srv_name);
+
+ DEBUG(10,("get_srv_gss_creds: imported name %s\n",
+ host_princ_s ));
+
+ if (ret != GSS_S_COMPLETE) {
+ SAFE_FREE(host_princ_s);
+ return map_nt_error_from_gss(ret, min);
+ }
+
+ /*
+ * We're accessing the krb5.keytab file here.
+ * ensure we have permissions to do so.
+ */
+ become_root();
+
+ ret = gss_acquire_cred(&min,
+ srv_name,
+ GSS_C_INDEFINITE,
+ GSS_C_NULL_OID_SET,
+ cred_type,
+ p_srv_cred,
+ NULL,
+ NULL);
+ unbecome_root();
+
+ if (ret != GSS_S_COMPLETE) {
+ ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
+ DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n",
+ ads_errstr(adss)));
+ status = map_nt_error_from_gss(ret, min);
+ }
+
+ SAFE_FREE(host_princ_s);
+ gss_release_name(&min, &srv_name);
+ return status;
+}
+
+/******************************************************************************
+ Create a gss state.
+ Try and get the cifs/server@realm principal first, then fall back to
+ host/server@realm.
+******************************************************************************/
+
+static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec)
+{
+ NTSTATUS status;
+ gss_cred_id_t srv_cred;
+ fstring fqdn;
+
+ name_to_fqdn(fqdn, global_myname());
+ strlower_m(fqdn);
+
+ status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred);
+ if (!NT_STATUS_IS_OK(status)) {
+ status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred);
+ if (!NT_STATUS_IS_OK(status)) {
+ return nt_status_squash(status);
+ }
+ }
+
+ ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
+ if (!ec->es->s.gss_state) {
+ OM_uint32 min;
+ gss_release_cred(&min, &srv_cred);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCTP(ec->es->s.gss_state);
+ ec->es->s.gss_state->creds = srv_cred;
+
+ /* No context yet. */
+ ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT;
+
+ return NT_STATUS_OK;
+}
+#endif
+
+/******************************************************************************
+ Shutdown a server encryption context.
+******************************************************************************/
+
+static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
+{
+ struct smb_srv_trans_enc_ctx *ec = *pp_ec;
+
+ if (!ec) {
+ return;
+ }
+
+ if (ec->es) {
+ switch (ec->es->smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ destroy_auth_ntlmssp(ec);
+ break;
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ break;
+#endif
+ }
+ common_free_encryption_state(&ec->es);
+ }
+
+ SAFE_FREE(ec);
+ *pp_ec = NULL;
+}
+
+/******************************************************************************
+ Create a server encryption context.
+******************************************************************************/
+
+static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec)
+{
+ struct smb_srv_trans_enc_ctx *ec;
+
+ *pp_ec = NULL;
+
+ ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx);
+ if (!ec) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCTP(partial_srv_trans_enc_ctx);
+ ec->es = SMB_MALLOC_P(struct smb_trans_enc_state);
+ if (!ec->es) {
+ SAFE_FREE(ec);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCTP(ec->es);
+ ec->es->smb_enc_type = smb_enc_type;
+ switch (smb_enc_type) {
+ case SMB_TRANS_ENC_NTLM:
+ {
+ NTSTATUS status = make_auth_ntlmssp(ec);
+ if (!NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&ec);
+ return status;
+ }
+ }
+ break;
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ case SMB_TRANS_ENC_GSS:
+ /* Acquire our credentials by calling gss_acquire_cred here. */
+ {
+ NTSTATUS status = make_auth_gss(ec);
+ if (!NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&ec);
+ return status;
+ }
+ }
+ break;
+#endif
+ default:
+ srv_free_encryption_context(&ec);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ *pp_ec = ec;
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Free an encryption-allocated buffer.
+******************************************************************************/
+
+void srv_free_enc_buffer(char *buf)
+{
+ /* We know this is an smb buffer, and we
+ * didn't malloc, only copy, for a keepalive,
+ * so ignore non-session messages. */
+
+ if(CVAL(buf,0)) {
+ return;
+ }
+
+ if (srv_trans_enc_ctx) {
+ common_free_enc_buffer(srv_trans_enc_ctx->es, buf);
+ }
+}
+
+/******************************************************************************
+ Decrypt an incoming buffer.
+******************************************************************************/
+
+NTSTATUS srv_decrypt_buffer(char *buf)
+{
+ /* Ignore non-session messages. */
+ if(CVAL(buf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ if (srv_trans_enc_ctx) {
+ return common_decrypt_buffer(srv_trans_enc_ctx->es, buf);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
+******************************************************************************/
+
+NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out)
+{
+ *buf_out = buf;
+
+ /* Ignore non-session messages. */
+ if(CVAL(buf,0)) {
+ return NT_STATUS_OK;
+ }
+
+ if (srv_trans_enc_ctx) {
+ return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out);
+ }
+ /* Not encrypting. */
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Do the gss encryption negotiation. Parameters are in/out.
+ Until success we do everything on the partial enc ctx.
+******************************************************************************/
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob)
+{
+ OM_uint32 ret;
+ OM_uint32 min;
+ OM_uint32 flags = 0;
+ gss_buffer_desc in_buf, out_buf;
+ struct smb_tran_enc_state_gss *gss_state;
+ DATA_BLOB auth_reply = data_blob_null;
+ DATA_BLOB response = data_blob_null;
+ NTSTATUS status;
+
+ if (!partial_srv_trans_enc_ctx) {
+ status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ gss_state = partial_srv_trans_enc_ctx->es->s.gss_state;
+
+ in_buf.value = secblob.data;
+ in_buf.length = secblob.length;
+
+ out_buf.value = NULL;
+ out_buf.length = 0;
+
+ become_root();
+
+ ret = gss_accept_sec_context(&min,
+ &gss_state->gss_ctx,
+ gss_state->creds,
+ &in_buf,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ NULL,
+ NULL, /* Ignore oids. */
+ &out_buf, /* To return. */
+ &flags,
+ NULL, /* Ingore time. */
+ NULL); /* Ignore delegated creds. */
+ unbecome_root();
+
+ status = gss_err_to_ntstatus(ret, min);
+ if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
+ return status;
+ }
+
+ /* Ensure we've got sign+seal available. */
+ if (ret == GSS_S_COMPLETE) {
+ if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) !=
+ (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) {
+ DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough "
+ "for SMB sealing.\n"));
+ gss_release_buffer(&min, &out_buf);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ auth_reply = data_blob(out_buf.value, out_buf.length);
+ gss_release_buffer(&min, &out_buf);
+
+ /* Wrap in SPNEGO. */
+ response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5);
+ data_blob_free(&auth_reply);
+
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+
+ return status;
+}
+#endif
+
+/******************************************************************************
+ Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out.
+ Until success we do everything on the partial enc ctx.
+******************************************************************************/
+
+static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, bool spnego_wrap)
+{
+ NTSTATUS status;
+ DATA_BLOB chal = data_blob_null;
+ DATA_BLOB response = data_blob_null;
+
+ status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal);
+
+ /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
+ * for success ... */
+
+ if (spnego_wrap) {
+ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ data_blob_free(&chal);
+ } else {
+ /* Return the raw blob. */
+ response = chal;
+ }
+
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
+}
+
+/******************************************************************************
+ Do the SPNEGO encryption negotiation. Parameters are in/out.
+ Based off code in smbd/sesssionsetup.c
+ Until success we do everything on the partial enc ctx.
+******************************************************************************/
+
+static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
+ unsigned char **ppdata,
+ size_t *p_data_size,
+ unsigned char **pparam,
+ size_t *p_param_size)
+{
+ NTSTATUS status;
+ DATA_BLOB blob = data_blob_null;
+ DATA_BLOB secblob = data_blob_null;
+ bool got_kerberos_mechanism = false;
+
+ blob = data_blob_const(*ppdata, *p_data_size);
+
+ status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism);
+ if (!NT_STATUS_IS_OK(status)) {
+ return nt_status_squash(status);
+ }
+
+ /* We should have no partial context at this point. */
+
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+
+#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) {
+ status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
+ } else
+#endif
+ {
+ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true);
+ }
+
+ data_blob_free(&secblob);
+
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return nt_status_squash(status);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Return the context we're using for this encryption state. */
+ if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num);
+ *p_param_size = 2;
+ }
+
+ return status;
+}
+
+/******************************************************************************
+ Complete a SPNEGO encryption negotiation. Parameters are in/out.
+ We only get this for a NTLM auth second stage.
+******************************************************************************/
+
+static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
+ unsigned char **ppdata,
+ size_t *p_data_size,
+ unsigned char **pparam,
+ size_t *p_param_size)
+{
+ NTSTATUS status;
+ DATA_BLOB blob = data_blob_null;
+ DATA_BLOB auth = data_blob_null;
+ DATA_BLOB auth_reply = data_blob_null;
+ DATA_BLOB response = data_blob_null;
+ struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx;
+
+ /* We must have a partial context here. */
+
+ if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ blob = data_blob_const(*ppdata, *p_data_size);
+ if (!spnego_parse_auth(blob, &auth)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply);
+ data_blob_free(&auth);
+
+ response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP);
+ data_blob_free(&auth_reply);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Return the context we're using for this encryption state. */
+ if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SSVAL(*pparam,0,ec->es->enc_ctx_num);
+ *p_param_size = 2;
+ }
+
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
+}
+
+/******************************************************************************
+ Raw NTLM encryption negotiation. Parameters are in/out.
+ This function does both steps.
+******************************************************************************/
+
+static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn,
+ unsigned char **ppdata,
+ size_t *p_data_size,
+ unsigned char **pparam,
+ size_t *p_param_size)
+{
+ NTSTATUS status;
+ DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size);
+ DATA_BLOB response = data_blob_null;
+ struct smb_srv_trans_enc_ctx *ec;
+
+ if (!partial_srv_trans_enc_ctx) {
+ /* This is the initial step. */
+ status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, false);
+ if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return nt_status_squash(status);
+ }
+ return status;
+ }
+
+ ec = partial_srv_trans_enc_ctx;
+ if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Second step. */
+ status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Return the context we're using for this encryption state. */
+ if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SSVAL(*pparam,0,ec->es->enc_ctx_num);
+ *p_param_size = 2;
+ }
+
+ /* Return the raw blob. */
+ SAFE_FREE(*ppdata);
+ *ppdata = response.data;
+ *p_data_size = response.length;
+ return status;
+}
+
+/******************************************************************************
+ Do the SPNEGO encryption negotiation. Parameters are in/out.
+******************************************************************************/
+
+NTSTATUS srv_request_encryption_setup(connection_struct *conn,
+ unsigned char **ppdata,
+ size_t *p_data_size,
+ unsigned char **pparam,
+ size_t *p_param_size)
+{
+ unsigned char *pdata = *ppdata;
+
+ SAFE_FREE(*pparam);
+ *p_param_size = 0;
+
+ if (*p_data_size < 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (pdata[0] == ASN1_APPLICATION(0)) {
+ /* its a negTokenTarg packet */
+ return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size);
+ }
+
+ if (pdata[0] == ASN1_CONTEXT(1)) {
+ /* It's an auth packet */
+ return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
+ }
+
+ /* Maybe it's a raw unwrapped auth ? */
+ if (*p_data_size < 7) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) {
+ return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
+ }
+
+ DEBUG(1,("srv_request_encryption_setup: Unknown packet\n"));
+
+ return NT_STATUS_LOGON_FAILURE;
+}
+
+/******************************************************************************
+ Negotiation was successful - turn on server-side encryption.
+******************************************************************************/
+
+static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec)
+{
+ if (!ec || !ec->es) {
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
+ if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) !=
+ (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ /* Todo - check gssapi case. */
+
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Negotiation was successful - turn on server-side encryption.
+******************************************************************************/
+
+NTSTATUS srv_encryption_start(connection_struct *conn)
+{
+ NTSTATUS status;
+
+ /* Check that we are really doing sign+seal. */
+ status = check_enc_good(partial_srv_trans_enc_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ /* Throw away the context we're using currently (if any). */
+ srv_free_encryption_context(&srv_trans_enc_ctx);
+
+ /* Steal the partial pointer. Deliberate shallow copy. */
+ srv_trans_enc_ctx = partial_srv_trans_enc_ctx;
+ srv_trans_enc_ctx->es->enc_on = true;
+
+ partial_srv_trans_enc_ctx = NULL;
+
+ return NT_STATUS_OK;
+}
+
+/******************************************************************************
+ Shutdown all server contexts.
+******************************************************************************/
+
+void server_encryption_shutdown(void)
+{
+ srv_free_encryption_context(&partial_srv_trans_enc_ctx);
+ srv_free_encryption_context(&srv_trans_enc_ctx);
+}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 8e69a3b381..65fc818144 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -795,6 +795,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->case_preserve = lp_preservecase(snum);
conn->short_case_preserve = lp_shortpreservecase(snum);
+ conn->encrypt_level = lp_smb_encrypt(snum);
+
conn->veto_list = NULL;
conn->hide_list = NULL;
conn->veto_oplock_list = NULL;
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 8ca012ff24..bc1d26faca 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -118,8 +118,7 @@ static void sessionsetup_start_signing_engine(
Send a security blob via a session setup reply.
****************************************************************************/
-static void reply_sesssetup_blob(connection_struct *conn,
- struct smb_request *req,
+static void reply_sesssetup_blob(struct smb_request *req,
DATA_BLOB blob,
NTSTATUS nt_status)
{
@@ -139,7 +138,7 @@ static void reply_sesssetup_blob(connection_struct *conn,
}
show_msg((char *)req->outbuf);
- send_smb(smbd_server_fd(),(char *)req->outbuf);
+ srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
TALLOC_FREE(req->outbuf);
}
@@ -247,8 +246,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
Reply to a session setup spnego negotiate packet for kerberos.
****************************************************************************/
-static void reply_spnego_kerberos(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_kerberos(struct smb_request *req,
DATA_BLOB *secblob,
uint16 vuid,
bool *p_invalidate_vuid)
@@ -539,7 +537,9 @@ static void reply_spnego_kerberos(connection_struct *conn,
}
}
- server_info->was_mapped |= username_was_mapped;
+ if (username_was_mapped) {
+ server_info->was_mapped = username_was_mapped;
+ }
/* we need to build the token for the user. make_server_info_guest()
already does this */
@@ -605,7 +605,7 @@ static void reply_spnego_kerberos(connection_struct *conn,
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, req, response, ret);
+ reply_sesssetup_blob(req, response, ret);
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
@@ -623,8 +623,7 @@ static void reply_spnego_kerberos(connection_struct *conn,
leg of the NTLM auth steps.
***************************************************************************/
-static void reply_spnego_ntlmssp(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_ntlmssp(struct smb_request *req,
uint16 vuid,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
@@ -693,7 +692,7 @@ static void reply_spnego_ntlmssp(connection_struct *conn,
response = *ntlmssp_blob;
}
- reply_sesssetup_blob(conn, req, response, nt_status);
+ reply_sesssetup_blob(req, response, nt_status);
if (wrap) {
data_blob_free(&response);
}
@@ -756,8 +755,7 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
Reply to a session setup spnego negotiate packet.
****************************************************************************/
-static void reply_spnego_negotiate(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_negotiate(struct smb_request *req,
uint16 vuid,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
@@ -783,7 +781,7 @@ static void reply_spnego_negotiate(connection_struct *conn,
if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
lp_use_kerberos_keytab()) ) {
bool destroy_vuid = True;
- reply_spnego_kerberos(conn, req, &secblob, vuid,
+ reply_spnego_kerberos(req, &secblob, vuid,
&destroy_vuid);
data_blob_free(&secblob);
if (destroy_vuid) {
@@ -811,7 +809,7 @@ static void reply_spnego_negotiate(connection_struct *conn,
data_blob_free(&secblob);
- reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state,
+ reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
&chal, status, True);
data_blob_free(&chal);
@@ -824,8 +822,7 @@ static void reply_spnego_negotiate(connection_struct *conn,
Reply to a session setup spnego auth packet.
****************************************************************************/
-static void reply_spnego_auth(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_auth(struct smb_request *req,
uint16 vuid,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
@@ -860,7 +857,7 @@ static void reply_spnego_auth(connection_struct *conn,
if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
lp_use_kerberos_keytab()) ) {
bool destroy_vuid = True;
- reply_spnego_kerberos(conn, req, &secblob,
+ reply_spnego_kerberos(req, &secblob,
vuid, &destroy_vuid);
data_blob_free(&secblob);
data_blob_free(&auth);
@@ -892,7 +889,7 @@ static void reply_spnego_auth(connection_struct *conn,
data_blob_free(&auth);
- reply_spnego_ntlmssp(conn, req, vuid,
+ reply_spnego_ntlmssp(req, vuid,
auth_ntlmssp_state,
&auth_reply, status, True);
@@ -1104,8 +1101,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-static void reply_sesssetup_and_X_spnego(connection_struct *conn,
- struct smb_request *req)
+static void reply_sesssetup_and_X_spnego(struct smb_request *req)
{
uint8 *p;
DATA_BLOB blob1;
@@ -1225,7 +1221,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn,
/* its a negTokenTarg packet */
- reply_spnego_negotiate(conn, req, vuid, blob1,
+ reply_spnego_negotiate(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
@@ -1235,7 +1231,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn,
/* its a auth packet */
- reply_spnego_auth(conn, req, vuid, blob1,
+ reply_spnego_auth(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
@@ -1260,7 +1256,7 @@ static void reply_sesssetup_and_X_spnego(connection_struct *conn,
data_blob_free(&blob1);
- reply_spnego_ntlmssp(conn, req, vuid,
+ reply_spnego_ntlmssp(req, vuid,
&vuser->auth_ntlmssp_state,
&chal, status, False);
data_blob_free(&chal);
@@ -1326,7 +1322,7 @@ static void setup_new_vc_session(void)
Reply to a session setup command.
****************************************************************************/
-void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
+void reply_sesssetup_and_X(struct smb_request *req)
{
int sess_vuid;
int smb_bufsize;
@@ -1377,7 +1373,7 @@ void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
setup_new_vc_session();
}
- reply_sesssetup_and_X_spnego(conn, req);
+ reply_sesssetup_and_X_spnego(req);
END_PROFILE(SMBsesssetupX);
return;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index e37f6ffbfd..c3b5f9fa2f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -575,7 +575,8 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-void send_trans2_replies(struct smb_request *req,
+void send_trans2_replies(connection_struct *conn,
+ struct smb_request *req,
const char *params,
int paramsize,
const char *pdata,
@@ -737,8 +738,10 @@ void send_trans2_replies(struct smb_request *req,
/* Send the packet */
show_msg((char *)req->outbuf);
- if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
- exit_server_cleanly("send_trans2_replies: send_smb failed.");
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ IS_CONN_ENCRYPTED(conn)))
+ exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
TALLOC_FREE(req->outbuf);
@@ -841,20 +844,6 @@ static void call_trans2open(connection_struct *conn,
fname, (unsigned int)deny_mode, (unsigned int)open_attr,
(unsigned int)open_ofun, open_size));
- /* XXXX we need to handle passed times, sattr and flags */
-
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
if (open_ofun == 0) {
reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
return;
@@ -899,14 +888,22 @@ static void call_trans2open(connection_struct *conn,
return;
}
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- access_mask,
- share_mode,
- create_disposition,
- create_options,
- open_attr,
- oplock_request,
- &smb_action, &fsp);
+ status = create_file(conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ open_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ open_size, /* allocation_size */
+ NULL, /* sd */
+ ea_list, /* ea_list */
+ &fsp, /* result */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
@@ -927,41 +924,6 @@ static void call_trans2open(connection_struct *conn,
return;
}
- /* Save the requested allocation size. */
- /* Allocate space for the file if a size hint is supplied */
- if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
- SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
- if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
- fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
- if (fsp->is_directory) {
- close_file(fsp,ERROR_CLOSE);
- /* Can't set allocation size on a directory. */
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
- if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,ERROR_CLOSE);
- reply_nterror(req, NT_STATUS_DISK_FULL);
- return;
- }
-
- /* Adjust size here to return the right size in the reply.
- Windows does it this way. */
- size = fsp->initial_allocation_size;
- } else {
- fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
- }
- }
-
- if (ea_list && smb_action == FILE_WAS_CREATED) {
- status = set_ea(conn, fsp, fname, ea_list);
- if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp,ERROR_CLOSE);
- reply_nterror(req, status);
- return;
- }
- }
-
/* Realloc the size of parameters and data we will return */
*pparams = (char *)SMB_REALLOC(*pparams, 30);
if(*pparams == NULL ) {
@@ -997,7 +959,7 @@ static void call_trans2open(connection_struct *conn,
}
/* Send the required number of replies */
- send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
}
/*********************************************************
@@ -2067,7 +2029,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,6,0); /* Never an EA error */
SSVAL(params,8,last_entry_off);
- send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
+ send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
if ((! *directory) && dptr_path(dptr_num)) {
@@ -2391,7 +2353,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,4,0); /* Never an EA error */
SSVAL(params,6,last_entry_off);
- send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
+ send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
return;
@@ -2430,6 +2392,27 @@ static void call_trans2qfsinfo(connection_struct *conn,
info_level = SVAL(params,0);
+ if (IS_IPC(conn)) {
+ if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+ DEBUG(0,("call_trans2qfsinfo: not an allowed "
+ "info level (0x%x) on IPC$.\n",
+ (unsigned int)info_level));
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+ }
+
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+ if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+ DEBUG(0,("call_trans2qfsinfo: encryption required "
+ "and info level 0x%x sent.\n",
+ (unsigned int)info_level));
+ exit_server_cleanly("encryption required "
+ "on connection");
+ return;
+ }
+ }
+
DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
if(SMB_VFS_STAT(conn,".",&st)!=0) {
@@ -2729,22 +2712,45 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
{
bool large_write = lp_min_receive_file_size() &&
!srv_is_signing_active();
+ bool large_read = !srv_is_signing_active();
+ int encrypt_caps = 0;
if (!lp_unix_extensions()) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
+
+ switch (conn->encrypt_level) {
+ case 0:
+ encrypt_caps = 0;
+ break;
+ case 1:
+ case Auto:
+ encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
+ break;
+ case Required:
+ encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
+ CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
+ large_write = false;
+ large_read = false;
+ break;
+ }
+
data_len = 12;
SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
- /* We have POSIX ACLs, pathname and locking capability. */
+
+ /* We have POSIX ACLs, pathname, encryption,
+ * large read/write, and locking capability. */
+
SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
CIFS_UNIX_POSIX_ACLS_CAP|
CIFS_UNIX_POSIX_PATHNAMES_CAP|
CIFS_UNIX_FCNTL_LOCKS_CAP|
CIFS_UNIX_EXTATTR_CAP|
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
- CIFS_UNIX_LARGE_READ_CAP|
+ encrypt_caps|
+ (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
(large_write ?
CIFS_UNIX_LARGE_WRITE_CAP : 0))));
break;
@@ -2864,8 +2870,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
*/
for (i = 0, sid_bytes = 0;
i < current_user.nt_user_token->num_sids; ++i) {
- sid_bytes +=
- sid_size(&current_user.nt_user_token->user_sids[i]);
+ sid_bytes += ndr_size_dom_sid(
+ &current_user.nt_user_token->user_sids[i], 0);
}
/* SID list byte count */
@@ -2885,8 +2891,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
/* SID list */
for (i = 0;
i < current_user.nt_user_token->num_sids; ++i) {
- int sid_len =
- sid_size(&current_user.nt_user_token->user_sids[i]);
+ int sid_len = ndr_size_dom_sid(
+ &current_user.nt_user_token->user_sids[i], 0);
sid_linearize(pdata + data_len, sid_len,
&current_user.nt_user_token->user_sids[i]);
@@ -2913,7 +2919,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
- send_trans2_replies(req, params, 0, pdata, data_len,
+ send_trans2_replies(conn, req, params, 0, pdata, data_len,
max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n",
@@ -2948,6 +2954,28 @@ static void call_trans2setfsinfo(connection_struct *conn,
info_level = SVAL(params,2);
+ if (IS_IPC(conn)) {
+ if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
+ info_level != SMB_SET_CIFS_UNIX_INFO) {
+ DEBUG(0,("call_trans2setfsinfo: not an allowed "
+ "info level (0x%x) on IPC$.\n",
+ (unsigned int)info_level));
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+ }
+
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+ if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
+ DEBUG(0,("call_trans2setfsinfo: encryption required "
+ "and info level 0x%x sent.\n",
+ (unsigned int)info_level));
+ exit_server_cleanly("encryption required "
+ "on connection");
+ return;
+ }
+ }
+
switch(info_level) {
case SMB_SET_CIFS_UNIX_INFO:
{
@@ -2998,6 +3026,62 @@ cap_low = 0x%x, cap_high = 0x%x\n",
}
break;
}
+
+ case SMB_REQUEST_TRANSPORT_ENCRYPTION:
+ {
+ NTSTATUS status;
+ size_t param_len = 0;
+ size_t data_len = total_data;
+
+ if (!lp_unix_extensions()) {
+ reply_nterror(
+ req,
+ NT_STATUS_INVALID_LEVEL);
+ return;
+ }
+
+ if (lp_smb_encrypt(SNUM(conn)) == false) {
+ reply_nterror(
+ req,
+ NT_STATUS_NOT_SUPPORTED);
+ return;
+ }
+
+ DEBUG( 4,("call_trans2setfsinfo: "
+ "request transport encrption.\n"));
+
+ status = srv_request_encryption_setup(conn,
+ (unsigned char **)ppdata,
+ &data_len,
+ (unsigned char **)pparams,
+ &param_len);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+ !NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ send_trans2_replies(conn, req,
+ *pparams,
+ param_len,
+ *ppdata,
+ data_len,
+ max_data_bytes);
+
+ if (NT_STATUS_IS_OK(status)) {
+ /* Server-side transport
+ * encryption is now *on*. */
+ status = srv_encryption_start(conn);
+ if (!NT_STATUS_IS_OK(status)) {
+ exit_server_cleanly(
+ "Failure in setting "
+ "up encrypted transport");
+ }
+ }
+ return;
+ }
+
case SMB_FS_QUOTA_INFORMATION:
{
files_struct *fsp = NULL;
@@ -3454,7 +3538,7 @@ static void call_trans2qpipeinfo(connection_struct *conn,
return;
}
- send_trans2_replies(req, params, param_size, *ppdata, data_size,
+ send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
max_data_bytes);
return;
@@ -4386,7 +4470,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
return;
}
- send_trans2_replies(req, params, param_size, *ppdata, data_size,
+ send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
max_data_bytes);
return;
@@ -5090,8 +5174,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_posix_lock(connection_struct *conn,
- const uint8 *inbuf,
- int length,
+ const struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp)
@@ -5101,6 +5184,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
uint32 lock_pid;
bool blocking_lock = False;
enum brl_type lock_type;
+
NTSTATUS status = NT_STATUS_OK;
if (fsp == NULL || fsp->fh->fd == -1) {
@@ -5188,7 +5272,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
* onto the blocking lock queue.
*/
if(push_blocking_lock_request(br_lck,
- (char *)inbuf, length,
+ req,
fsp,
-1, /* infinite timeout. */
0,
@@ -6246,7 +6330,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2,
+ send_trans2_replies(conn, req, params, 2,
*ppdata, 0,
max_data_bytes);
return;
@@ -6536,8 +6620,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
}
- status = smb_set_posix_lock(conn, req->inbuf,
- smb_len(req->inbuf) + 4,
+ status = smb_set_posix_lock(conn, req,
pdata, total_data, fsp);
break;
}
@@ -6605,7 +6688,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
}
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2, *ppdata, data_return_size,
+ send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
max_data_bytes);
return;
@@ -6697,7 +6780,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
return;
}
- status = create_directory(conn, directory);
+ status = create_directory(conn, req, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -6723,7 +6806,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
SSVAL(params,0,0);
- send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
return;
}
@@ -6777,7 +6860,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
if(fnf_handle == 0)
fnf_handle = 257;
- send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
return;
}
@@ -6808,7 +6891,7 @@ static void call_trans2findnotifynext(connection_struct *conn,
SSVAL(params,0,0); /* No changes */
SSVAL(params,2,0); /* No EA errors */
- send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
return;
}
@@ -6858,7 +6941,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
SSVAL(req->inbuf, smb_flg2,
SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
- send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
+ send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
return;
}
@@ -6905,7 +6988,7 @@ static void call_trans2ioctl(connection_struct *conn,
srvstr_push(pdata, req->flags2, pdata+18,
lp_servicename(SNUM(conn)), 13,
STR_ASCII|STR_TERMINATE); /* Service name */
- send_trans2_replies(req, *pparams, 0, *ppdata, 32,
+ send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
max_data_bytes);
return;
}
@@ -6918,7 +7001,7 @@ static void call_trans2ioctl(connection_struct *conn,
Reply to a SMBfindclose (stop trans2 directory search).
****************************************************************************/
-void reply_findclose(connection_struct *conn, struct smb_request *req)
+void reply_findclose(struct smb_request *req)
{
int dptr_num;
@@ -6948,7 +7031,7 @@ void reply_findclose(connection_struct *conn, struct smb_request *req)
Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
****************************************************************************/
-void reply_findnclose(connection_struct *conn, struct smb_request *req)
+void reply_findnclose(struct smb_request *req)
{
int dptr_num;
@@ -6984,6 +7067,17 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
SSVAL(req->inbuf,smb_flg2,req->flags2);
}
+ if (conn->encrypt_level == Required && !req->encrypted) {
+ if (state->call != TRANSACT2_QFSINFO &&
+ state->call != TRANSACT2_SETFSINFO) {
+ DEBUG(0,("handle_trans2: encryption required "
+ "with call 0x%x\n",
+ (unsigned int)state->call));
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+ }
+
/* Now we must call the relevant TRANS2 function */
switch(state->call) {
case TRANSACT2_OPEN:
@@ -7131,8 +7225,9 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
Reply to a SMBtrans2.
****************************************************************************/
-void reply_trans2(connection_struct *conn, struct smb_request *req)
+void reply_trans2(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int dsoff;
unsigned int dscnt;
unsigned int psoff;
@@ -7166,12 +7261,20 @@ void reply_trans2(connection_struct *conn, struct smb_request *req)
return;
}
- if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
- && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
- && (tran_call != TRANSACT2_QFILEINFO)) {
- reply_doserror(req, ERRSRV, ERRaccess);
- END_PROFILE(SMBtrans2);
- return;
+ if (IS_IPC(conn)) {
+ switch (tran_call) {
+ /* List the allowed trans2 calls on IPC$ */
+ case TRANSACT2_OPEN:
+ case TRANSACT2_GET_DFS_REFERRAL:
+ case TRANSACT2_QFILEINFO:
+ case TRANSACT2_QFSINFO:
+ case TRANSACT2_SETFSINFO:
+ break;
+ default:
+ reply_doserror(req, ERRSRV, ERRaccess);
+ END_PROFILE(SMBtrans2);
+ return;
+ }
}
if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
@@ -7312,8 +7415,9 @@ void reply_trans2(connection_struct *conn, struct smb_request *req)
Reply to a SMBtranss2
****************************************************************************/
-void reply_transs2(connection_struct *conn, struct smb_request *req)
+void reply_transs2(struct smb_request *req)
{
+ connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
int size;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index fefae38932..ed0406211d 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -31,7 +31,7 @@ static_decl_vfs;
struct vfs_init_function_entry {
char *name;
- vfs_op_tuple *vfs_op_tuples;
+ const vfs_op_tuple *vfs_op_tuples;
struct vfs_init_function_entry *prev, *next;
};
@@ -55,7 +55,7 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
return NULL;
}
-NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples)
+NTSTATUS smb_register_vfs(int version, const char *name, const vfs_op_tuple *vfs_op_tuples)
{
struct vfs_init_function_entry *entry = backends;
@@ -110,13 +110,13 @@ static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which,
bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
{
- vfs_op_tuple *ops;
+ const vfs_op_tuple *ops;
char *module_path = NULL;
char *module_name = NULL;
char *module_param = NULL, *p;
int i;
vfs_handle_struct *handle;
- struct vfs_init_function_entry *entry;
+ const struct vfs_init_function_entry *entry;
if (!conn||!vfs_object||!vfs_object[0]) {
DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c
index 77666bb664..ab7edde85d 100644
--- a/source3/torture/pdbtest.c
+++ b/source3/torture/pdbtest.c
@@ -364,24 +364,6 @@ int main(int argc, char **argv)
get_friendly_nt_error_msg(rv));
}
- pdb->setsampwent(pdb, False, 0);
- while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) {
- if (pdb_get_username(out) == NULL) {
- fprintf(stderr, "Got bad username through getsampwent()\n");
- error = True;
- break;
- }
- if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) {
- fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n");
- error = True;
- continue;
- }
- if (!samu_correct(out, in)) {
- printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n");
- }
- }
- pdb->endsampwent(pdb);
-
TALLOC_FREE(ctx);
if (error) {
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 082949e0af..05b41413b4 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -37,6 +37,7 @@ static const char *client_txt = "client_oplocks.txt";
static bool use_kerberos;
static fstring multishare_conn_fname;
static bool use_multishare_conn = False;
+static bool do_encrypt;
bool torture_showall = False;
@@ -95,6 +96,57 @@ void *shm_setup(int size)
return ret;
}
+/********************************************************************
+ Ensure a connection is encrypted.
+********************************************************************/
+
+static bool force_cli_encryption(struct cli_state *c,
+ const char *sharename)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+ NTSTATUS status;
+
+ if (!SERVER_HAS_UNIX_CIFS(c)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ return false;
+ }
+
+ if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ return false;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", sharename);
+ return false;
+ }
+
+ if (c->use_kerberos) {
+ status = cli_gss_smb_encryption_start(c);
+ } else {
+ status = cli_raw_ntlm_smb_encryption_start(c,
+ username,
+ password,
+ workgroup);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(status));
+ return false;
+ }
+
+ return true;
+}
+
static struct cli_state *open_nbt_connection(void)
{
@@ -235,6 +287,10 @@ static bool torture_open_connection_share(struct cli_state **c,
if (use_level_II_oplocks) (*c)->use_level_II_oplocks = True;
(*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
+ if (do_encrypt) {
+ return force_cli_encryption(*c,
+ sharename);
+ }
return True;
}
@@ -5425,7 +5481,7 @@ static void usage(void)
fstrcpy(workgroup, lp_workgroup());
- while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Ac:ks:b:")) != EOF) {
+ while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Aec:ks:b:")) != EOF) {
switch (opt) {
case 'p':
port_to_use = atoi(optarg);
@@ -5463,6 +5519,9 @@ static void usage(void)
case 'c':
client_txt = optarg;
break;
+ case 'e':
+ do_encrypt = true;
+ break;
case 'k':
#ifdef HAVE_KRB5
use_kerberos = True;
diff --git a/source3/utils/net.c b/source3/utils/net.c
index bf70d08d8b..586ea2fdb6 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -88,6 +88,7 @@ int opt_testmode = False;
int opt_have_ip = False;
struct sockaddr_storage opt_dest_ip;
+bool smb_encrypt;
extern bool AllowDebugChange;
@@ -178,9 +179,7 @@ NTSTATUS connect_to_service(struct cli_state **c,
service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
- if (NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- } else {
+ if (!NT_STATUS_IS_OK(nt_status)) {
d_fprintf(stderr, "Could not connect to server %s\n", server_name);
/* Display a nicer message depending on the result */
@@ -196,9 +195,40 @@ NTSTATUS connect_to_service(struct cli_state **c,
if (NT_STATUS_V(nt_status) ==
NT_STATUS_V(NT_STATUS_ACCOUNT_DISABLED))
d_fprintf(stderr, "The account was disabled.\n");
-
return nt_status;
}
+
+ if (smb_encrypt) {
+ nt_status = cli_force_encryption(*c,
+ opt_user_name,
+ opt_password,
+ opt_workgroup);
+
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_SUPPORTED)) {
+ d_printf("Encryption required and "
+ "server that doesn't support "
+ "UNIX extensions - failing connect\n");
+ } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNKNOWN_REVISION)) {
+ d_printf("Encryption required and "
+ "can't get UNIX CIFS extensions "
+ "version from server.\n");
+ } else if (NT_STATUS_EQUAL(nt_status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
+ d_printf("Encryption required and "
+ "share %s doesn't support "
+ "encryption.\n", service_name);
+ } else if (!NT_STATUS_IS_OK(nt_status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(nt_status));
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(*c);
+ *c = NULL;
+ }
+ }
+
+ return nt_status;
}
/****************************************************************************
@@ -287,12 +317,24 @@ NTSTATUS connect_to_ipc_krb5(struct cli_state **c,
SAFE_FREE(user_and_realm);
- if (NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- } else {
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status)));
return nt_status;
}
+
+ if (smb_encrypt) {
+ nt_status = cli_cm_force_encryption(*c,
+ user_and_realm,
+ opt_password,
+ opt_workgroup,
+ "IPC$");
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(*c);
+ *c = NULL;
+ }
+ }
+
+ return nt_status;
}
/**
@@ -988,6 +1030,7 @@ static struct functable net_func[] = {
{"port", 'p', POPT_ARG_INT, &opt_port},
{"myname", 'n', POPT_ARG_STRING, &opt_requester_name},
{"server", 'S', POPT_ARG_STRING, &opt_host},
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
{"container", 'c', POPT_ARG_STRING, &opt_container},
{"comment", 'C', POPT_ARG_STRING, &opt_comment},
{"maxusers", 'M', POPT_ARG_INT, &opt_maxusers},
@@ -1010,7 +1053,7 @@ static struct functable net_func[] = {
{"acls", 0, POPT_ARG_NONE, &opt_acls},
{"attrs", 0, POPT_ARG_NONE, &opt_attrs},
{"timestamps", 0, POPT_ARG_NONE, &opt_timestamps},
- {"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
+ {"exclude", 'X', POPT_ARG_STRING, &opt_exclude},
{"destination", 0, POPT_ARG_STRING, &opt_destination},
{"tallocreport", 0, POPT_ARG_NONE, &do_talloc_report},
@@ -1037,6 +1080,9 @@ static struct functable net_func[] = {
net_help(argc, argv);
exit(0);
break;
+ case 'e':
+ smb_encrypt=true;
+ break;
case 'I':
if (!interpret_string_addr(&opt_dest_ip,
poptGetOptArg(pc), 0)) {
diff --git a/source3/utils/net_conf.c b/source3/utils/net_conf.c
index 673d373177..38cdeacc11 100644
--- a/source3/utils/net_conf.c
+++ b/source3/utils/net_conf.c
@@ -2,7 +2,7 @@
* Samba Unix/Linux SMB client library
* Distributed SMB/CIFS Server Management Utility
* Local configuration interface
- * Copyright (C) Michael Adam 2007
+ * Copyright (C) Michael Adam 2007-2008
*
* 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
@@ -19,9 +19,12 @@
*/
/*
- * This is an interface to the configuration stored inside the
- * samba registry. In the future there might be support for other
- * configuration backends as well.
+ * This is an interface to Samba's configuration as made available
+ * by the libnet_conf interface (source/libnet/libnet_conf.c).
+ *
+ * This currently supports local interaction with the configuration
+ * stored in the registry. But other backends and remote access via
+ * rpc might get implemented in the future.
*/
#include "includes.h"
@@ -43,9 +46,9 @@ static int net_conf_import_usage(int argc, const char**argv)
d_printf("USAGE: net conf import [--test|-T] <filename> "
"[<servicename>]\n"
"\t[--test|-T] testmode - do not act, just print "
- "what would be done\n"
+ "what would be done\n"
"\t<servicename> only import service <servicename>, "
- "ignore the rest\n");
+ "ignore the rest\n");
return -1;
}
@@ -110,138 +113,6 @@ static int net_conf_delparm_usage(int argc, const char **argv)
* Helper functions
*/
-static char *format_value(TALLOC_CTX *mem_ctx, struct registry_value *value)
-{
- char *result = NULL;
-
- /* what if mem_ctx = NULL? */
-
- switch (value->type) {
- case REG_DWORD:
- result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
- break;
- case REG_SZ:
- case REG_EXPAND_SZ:
- result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
- break;
- case REG_MULTI_SZ: {
- uint32 j;
- for (j = 0; j < value->v.multi_sz.num_strings; j++) {
- result = talloc_asprintf(mem_ctx, "\"%s\" ",
- value->v.multi_sz.strings[j]);
- }
- break;
- }
- case REG_BINARY:
- result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
- (int)value->v.binary.length);
- break;
- default:
- result = talloc_asprintf(mem_ctx, "<unprintable>");
- break;
- }
- return result;
-}
-
-/*
- * delete a subkey of KEY_SMBCONF
- */
-static WERROR reg_delkey_internal(TALLOC_CTX *ctx, const char *keyname)
-{
- WERROR werr = WERR_OK;
- struct registry_key *key = NULL;
-
- werr = libnet_smbconf_open_basepath(ctx, REG_KEY_WRITE, &key);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = reg_deletekey_recursive(key, key, keyname);
- if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr, "Error deleting registry key %s\\%s: %s\n",
- KEY_SMBCONF, keyname, dos_errstr(werr));
- }
-
-done:
- TALLOC_FREE(key);
- return werr;
-}
-
-static WERROR list_values(TALLOC_CTX *ctx, struct registry_key *key)
-{
- WERROR werr = WERR_OK;
- uint32 idx = 0;
- struct registry_value *valvalue = NULL;
- char *valname = NULL;
-
- for (idx = 0;
- W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
- &valvalue));
- idx++)
- {
- d_printf("\t%s = %s\n", valname, format_value(ctx, valvalue));
- }
- if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
- d_fprintf(stderr, "Error enumerating values: %s\n",
- dos_errstr(werr));
- goto done;
- }
- werr = WERR_OK;
-
-done:
- return werr;
-}
-
-static WERROR drop_smbconf_internal(TALLOC_CTX *ctx)
-{
- char *path, *p;
- WERROR werr = WERR_OK;
- NT_USER_TOKEN *token;
- struct registry_key *parent_key = NULL;
- struct registry_key *new_key = NULL;
- TALLOC_CTX* tmp_ctx = NULL;
- enum winreg_CreateAction action;
-
- tmp_ctx = talloc_new(ctx);
- if (tmp_ctx == NULL) {
- werr = WERR_NOMEM;
- goto done;
- }
-
- if (!(token = registry_create_admin_token(tmp_ctx))) {
- /* what is the appropriate error code here? */
- werr = WERR_CAN_NOT_COMPLETE;
- goto done;
- }
-
- path = talloc_strdup(tmp_ctx, KEY_SMBCONF);
- if (path == NULL) {
- d_fprintf(stderr, "ERROR: out of memory!\n");
- werr = WERR_NOMEM;
- goto done;
- }
- p = strrchr(path, '\\');
- *p = '\0';
- werr = reg_open_path(tmp_ctx, path, REG_KEY_WRITE, token, &parent_key);
-
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = reg_deletekey_recursive(tmp_ctx, parent_key, p+1);
-
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
-
- werr = reg_createkey(tmp_ctx, parent_key, p+1, REG_KEY_WRITE,
- &new_key, &action);
-
-done:
- TALLOC_FREE(tmp_ctx);
- return werr;
-}
-
static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
struct share_params *share)
{
@@ -268,14 +139,14 @@ static char *parm_valstr(TALLOC_CTX *ctx, struct parm_struct *parm,
valstr = talloc_asprintf(ctx, "%s", BOOLSTR(!*(bool *)ptr));
break;
case P_ENUM:
- for (i = 0; parm->enum_list[i].name; i++) {
- if (*(int *)ptr == parm->enum_list[i].value)
+ for (i = 0; parm->enum_list[i].name; i++) {
+ if (*(int *)ptr == parm->enum_list[i].value)
{
valstr = talloc_asprintf(ctx, "%s",
- parm->enum_list[i].name);
- break;
- }
- }
+ parm->enum_list[i].name);
+ break;
+ }
+ }
break;
case P_OCTAL: {
char *o = octal_string(*(int *)ptr);
@@ -323,7 +194,6 @@ static int import_process_service(TALLOC_CTX *ctx,
struct parm_struct *parm;
int pnum = 0;
const char *servicename;
- struct registry_key *key;
WERROR werr;
char *valstr = NULL;
TALLOC_CTX *tmp_ctx = NULL;
@@ -340,23 +210,21 @@ static int import_process_service(TALLOC_CTX *ctx,
if (opt_testmode) {
d_printf("[%s]\n", servicename);
} else {
- if (libnet_smbconf_key_exists(tmp_ctx, servicename)) {
- werr = reg_delkey_internal(tmp_ctx, servicename);
+ if (libnet_conf_share_exists(servicename)) {
+ werr = libnet_conf_delete_share(servicename);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
}
- werr = libnet_smbconf_reg_createkey_internal(tmp_ctx, servicename, &key);
- if (!W_ERROR_IS_OK(werr)) {
- goto done;
- }
}
while ((parm = lp_next_parameter(share->service, &pnum, 0)))
{
- if ((share->service < 0 && parm->p_class == P_LOCAL)
+ if ((share->service < 0) && (parm->p_class == P_LOCAL)
&& !(parm->flags & FLAG_GLOBAL))
+ {
continue;
+ }
valstr = parm_valstr(tmp_ctx, parm, share);
@@ -364,9 +232,14 @@ static int import_process_service(TALLOC_CTX *ctx,
if (opt_testmode) {
d_printf("\t%s = %s\n", parm->label, valstr);
} else {
- werr = libnet_smbconf_reg_setvalue_internal(key,
- parm->label, valstr);
+ werr = libnet_conf_set_parameter(servicename,
+ parm->label,
+ valstr);
if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr,
+ "Error setting parameter '%s'"
+ ": %s\n", parm->label,
+ dos_errstr(werr));
goto done;
}
}
@@ -384,7 +257,7 @@ done:
return ret;
}
-/* return True iff there are nondefault globals */
+/* return true iff there are nondefault globals */
static bool globals_exist(void)
{
int i = 0;
@@ -392,25 +265,27 @@ static bool globals_exist(void)
while ((parm = lp_next_parameter(GLOBAL_SECTION_SNUM, &i, 0)) != NULL) {
if (parm->type != P_SEP) {
- return True;
+ return true;
}
}
- return False;
+ return false;
}
/*
* the conf functions
*/
-int net_conf_list(int argc, const char **argv)
+static int net_conf_list(int argc, const char **argv)
{
WERROR werr = WERR_OK;
int ret = -1;
TALLOC_CTX *ctx;
- struct registry_key *base_key = NULL;
- struct registry_key *sub_key = NULL;
- uint32 idx_key = 0;
- char *subkey_name = NULL;
+ uint32_t num_shares;
+ char **share_names;
+ uint32_t *num_params;
+ char ***param_names;
+ char ***param_values;
+ uint32_t share_count, param_count;
ctx = talloc_init("list");
@@ -419,54 +294,26 @@ int net_conf_list(int argc, const char **argv)
goto done;
}
- werr = libnet_smbconf_open_basepath(ctx, REG_KEY_READ, &base_key);
+ werr = libnet_conf_get_config(ctx, &num_shares, &share_names,
+ &num_params, &param_names,
+ &param_values);
if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error getting config: %s\n",
+ dos_errstr(werr));
goto done;
}
- if (libnet_smbconf_key_exists(ctx, GLOBAL_NAME)) {
- werr = reg_openkey(ctx, base_key, GLOBAL_NAME,
- REG_KEY_READ, &sub_key);
- if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr, "Error opening subkey '%s' : %s\n",
- subkey_name, dos_errstr(werr));
- goto done;
- }
- d_printf("[%s]\n", GLOBAL_NAME);
- if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
- goto done;
- }
- d_printf("\n");
- }
-
- for (idx_key = 0;
- W_ERROR_IS_OK(werr = reg_enumkey(ctx, base_key, idx_key,
- &subkey_name, NULL));
- idx_key++)
- {
- if (strequal(subkey_name, GLOBAL_NAME)) {
- continue;
- }
- d_printf("[%s]\n", subkey_name);
-
- werr = reg_openkey(ctx, base_key, subkey_name,
- REG_KEY_READ, &sub_key);
- if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr,
- "Error opening subkey '%s': %s\n",
- subkey_name, dos_errstr(werr));
- goto done;
- }
- if (!W_ERROR_IS_OK(list_values(ctx, sub_key))) {
- goto done;
+ for (share_count = 0; share_count < num_shares; share_count++) {
+ d_printf("[%s]\n", share_names[share_count]);
+ for (param_count = 0; param_count < num_params[share_count];
+ param_count++)
+ {
+ d_printf("\t%s = %s\n",
+ param_names[share_count][param_count],
+ param_values[share_count][param_count]);
}
d_printf("\n");
}
- if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
- d_fprintf(stderr, "Error enumerating subkeys: %s\n",
- dos_errstr(werr));
- goto done;
- }
ret = 0;
@@ -475,12 +322,12 @@ done:
return ret;
}
-int net_conf_import(int argc, const char **argv)
+static int net_conf_import(int argc, const char **argv)
{
int ret = -1;
const char *filename = NULL;
const char *servicename = NULL;
- bool service_found = False;
+ bool service_found = false;
TALLOC_CTX *ctx;
struct share_iterator *shares;
struct share_params *share;
@@ -504,10 +351,10 @@ int net_conf_import(int argc, const char **argv)
filename));
if (!lp_load(filename,
- False, /* global_only */
- True, /* save_defaults */
- False, /* add_ipc */
- True)) /* initialize_globals */
+ false, /* global_only */
+ true, /* save_defaults */
+ false, /* add_ipc */
+ true)) /* initialize_globals */
{
d_fprintf(stderr, "Error parsing configuration file.\n");
goto done;
@@ -521,7 +368,7 @@ int net_conf_import(int argc, const char **argv)
if (((servicename == NULL) && globals_exist()) ||
strequal(servicename, GLOBAL_NAME))
{
- service_found = True;
+ service_found = true;
if (import_process_service(ctx, &global_share) != 0) {
goto done;
}
@@ -540,7 +387,7 @@ int net_conf_import(int argc, const char **argv)
if ((servicename == NULL)
|| strequal(servicename, lp_servicename(share->service)))
{
- service_found = True;
+ service_found = true;
if (import_process_service(ctx, share)!= 0) {
goto done;
}
@@ -561,13 +408,12 @@ done:
return ret;
}
-int net_conf_listshares(int argc, const char **argv)
+static int net_conf_listshares(int argc, const char **argv)
{
WERROR werr = WERR_OK;
int ret = -1;
- struct registry_key *key;
- uint32 idx = 0;
- char *subkey_name = NULL;
+ uint32_t count, num_shares = 0;
+ char **share_names = NULL;
TALLOC_CTX *ctx;
ctx = talloc_init("listshares");
@@ -577,22 +423,14 @@ int net_conf_listshares(int argc, const char **argv)
goto done;
}
- werr = libnet_smbconf_open_basepath(ctx, SEC_RIGHTS_ENUM_SUBKEYS, &key);
+ werr = libnet_conf_get_share_names(ctx, &num_shares, &share_names);
if (!W_ERROR_IS_OK(werr)) {
goto done;
}
- for (idx = 0;
- W_ERROR_IS_OK(werr = reg_enumkey(ctx, key, idx,
- &subkey_name, NULL));
- idx++)
+ for (count = 0; count < num_shares; count++)
{
- d_printf("%s\n", subkey_name);
- }
- if (! W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
- d_fprintf(stderr, "Error enumerating subkeys: %s\n",
- dos_errstr(werr));
- goto done;
+ d_printf("%s\n", share_names[count]);
}
ret = 0;
@@ -602,7 +440,7 @@ done:
return ret;
}
-int net_conf_drop(int argc, const char **argv)
+static int net_conf_drop(int argc, const char **argv)
{
int ret = -1;
WERROR werr;
@@ -612,7 +450,7 @@ int net_conf_drop(int argc, const char **argv)
goto done;
}
- werr = drop_smbconf_internal(NULL);
+ werr = libnet_conf_drop();
if (!W_ERROR_IS_OK(werr)) {
d_fprintf(stderr, "Error deleting configuration: %s\n",
dos_errstr(werr));
@@ -625,12 +463,16 @@ done:
return ret;
}
-int net_conf_showshare(int argc, const char **argv)
+static int net_conf_showshare(int argc, const char **argv)
{
int ret = -1;
WERROR werr = WERR_OK;
- struct registry_key *key = NULL;
+ const char *sharename = NULL;
TALLOC_CTX *ctx;
+ uint32_t num_params;
+ uint32_t count;
+ char **param_names;
+ char **param_values;
ctx = talloc_init("showshare");
@@ -639,15 +481,21 @@ int net_conf_showshare(int argc, const char **argv)
goto done;
}
- werr = libnet_smbconf_open_path(ctx, argv[0], REG_KEY_READ, &key);
+ sharename = argv[0];
+
+ werr = libnet_conf_get_share(ctx, sharename, &num_params,
+ &param_names, &param_values);
if (!W_ERROR_IS_OK(werr)) {
+ d_printf("error getting share parameters: %s\n",
+ dos_errstr(werr));
goto done;
}
- d_printf("[%s]\n", argv[0]);
+ d_printf("[%s]\n", sharename);
- if (!W_ERROR_IS_OK(list_values(ctx, key))) {
- goto done;
+ for (count = 0; count < num_params; count++) {
+ d_printf("\t%s = %s\n", param_names[count],
+ param_values[count]);
}
ret = 0;
@@ -657,11 +505,16 @@ done:
return ret;
}
-int net_conf_addshare(int argc, const char **argv)
+/**
+ * Add a share, with a couple of standard parameters, partly optional.
+ *
+ * This is a high level utility function of the net conf utility,
+ * not a direct frontend to the libnet_conf API.
+ */
+static int net_conf_addshare(int argc, const char **argv)
{
int ret = -1;
WERROR werr = WERR_OK;
- struct registry_key *newkey = NULL;
char *sharename = NULL;
const char *path = NULL;
const char *comment = NULL;
@@ -713,7 +566,6 @@ int net_conf_addshare(int argc, const char **argv)
net_conf_addshare_usage(argc, argv);
goto done;
}
-
case 2:
path = argv[1];
sharename = strdup_lower(argv[0]);
@@ -747,6 +599,12 @@ int net_conf_addshare(int argc, const char **argv)
goto done;
}
+ if (libnet_conf_share_exists(sharename)) {
+ d_fprintf(stderr, "ERROR: share %s already exists.\n",
+ sharename);
+ goto done;
+ }
+
/* validate path */
if (path[0] != '/') {
@@ -776,46 +634,59 @@ int net_conf_addshare(int argc, const char **argv)
* create the share
*/
- werr = libnet_smbconf_reg_createkey_internal(NULL, argv[0], &newkey);
+ werr = libnet_conf_create_share(sharename);
if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error creating share %s: %s\n",
+ sharename, dos_errstr(werr));
goto done;
}
- /* add config params as values */
+ /*
+ * fill the share with parameters
+ */
- werr = libnet_smbconf_reg_setvalue_internal(newkey, "path", path);
- if (!W_ERROR_IS_OK(werr))
+ werr = libnet_conf_set_parameter(sharename, "path", path);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error setting parameter %s: %s\n",
+ "path", dos_errstr(werr));
goto done;
+ }
if (comment != NULL) {
- werr = libnet_smbconf_reg_setvalue_internal(newkey, "comment",
- comment);
- if (!W_ERROR_IS_OK(werr))
+ werr = libnet_conf_set_parameter(sharename, "comment", comment);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error setting parameter %s: %s\n",
+ "comment", dos_errstr(werr));
goto done;
+ }
}
- werr = libnet_smbconf_reg_setvalue_internal(newkey, "guest ok",
- guest_ok);
- if (!W_ERROR_IS_OK(werr))
+ werr = libnet_conf_set_parameter(sharename, "guest ok", guest_ok);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error setting parameter %s: %s\n",
+ "'guest ok'", dos_errstr(werr));
goto done;
+ }
- werr = libnet_smbconf_reg_setvalue_internal(newkey, "writeable",
- writeable);
- if (!W_ERROR_IS_OK(werr))
+ werr = libnet_conf_set_parameter(sharename, "writeable", writeable);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error setting parameter %s: %s\n",
+ "writeable", dos_errstr(werr));
goto done;
+ }
ret = 0;
done:
- TALLOC_FREE(newkey);
SAFE_FREE(sharename);
return ret;
}
-int net_conf_delshare(int argc, const char **argv)
+static int net_conf_delshare(int argc, const char **argv)
{
int ret = -1;
const char *sharename = NULL;
+ WERROR werr = WERR_OK;
if (argc != 1) {
net_conf_delshare_usage(argc, argv);
@@ -823,9 +694,14 @@ int net_conf_delshare(int argc, const char **argv)
}
sharename = argv[0];
- if (W_ERROR_IS_OK(reg_delkey_internal(NULL, sharename))) {
- ret = 0;
+ werr = libnet_conf_delete_share(sharename);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error deleting share %s: %s\n",
+ sharename, dos_errstr(werr));
+ goto done;
}
+
+ ret = 0;
done:
return ret;
}
@@ -837,9 +713,6 @@ static int net_conf_setparm(int argc, const char **argv)
char *service = NULL;
char *param = NULL;
const char *value_str = NULL;
- TALLOC_CTX *ctx;
-
- ctx = talloc_init("setparm");
if (argc != 3) {
net_conf_setparm_usage(argc, argv);
@@ -849,7 +722,16 @@ static int net_conf_setparm(int argc, const char **argv)
param = strdup_lower(argv[1]);
value_str = argv[2];
- werr = libnet_smbconf_setparm(ctx, service, param, value_str);
+ if (!libnet_conf_share_exists(service)) {
+ werr = libnet_conf_create_share(service);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error creating share '%s': %s\n",
+ service, dos_errstr(werr));
+ goto done;
+ }
+ }
+
+ werr = libnet_conf_set_parameter(service, param, value_str);
if (!W_ERROR_IS_OK(werr)) {
d_fprintf(stderr, "Error setting value '%s': %s\n",
@@ -861,7 +743,7 @@ static int net_conf_setparm(int argc, const char **argv)
done:
SAFE_FREE(service);
- TALLOC_FREE(ctx);
+ SAFE_FREE(param);
return ret;
}
@@ -869,10 +751,9 @@ static int net_conf_getparm(int argc, const char **argv)
{
int ret = -1;
WERROR werr = WERR_OK;
- struct registry_key *key = NULL;
char *service = NULL;
char *param = NULL;
- struct registry_value *value = NULL;
+ char *valstr = NULL;
TALLOC_CTX *ctx;
ctx = talloc_init("getparm");
@@ -884,26 +765,25 @@ static int net_conf_getparm(int argc, const char **argv)
service = strdup_lower(argv[0]);
param = strdup_lower(argv[1]);
- if (!libnet_smbconf_key_exists(ctx, service)) {
+ werr = libnet_conf_get_parameter(ctx, service, param, &valstr);
+
+ if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
d_fprintf(stderr,
- "ERROR: given service '%s' does not exist.\n",
+ "Error: given service '%s' does not exist.\n",
service);
goto done;
- }
-
- werr = libnet_smbconf_open_path(ctx, service, REG_KEY_READ, &key);
- if (!W_ERROR_IS_OK(werr)) {
+ } else if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
+ d_fprintf(stderr,
+ "Error: given parameter '%s' is not set.\n",
+ param);
goto done;
- }
-
- werr = reg_queryvalue(ctx, key, param, &value);
- if (!W_ERROR_IS_OK(werr)) {
- d_fprintf(stderr, "Error querying value '%s': %s.\n",
+ } else if (!W_ERROR_IS_OK(werr)) {
+ d_fprintf(stderr, "Error getting value '%s': %s.\n",
param, dos_errstr(werr));
goto done;
}
- d_printf("%s\n", format_value(ctx, value));
+ d_printf("%s\n", valstr);
ret = 0;
done:
@@ -919,9 +799,6 @@ static int net_conf_delparm(int argc, const char **argv)
WERROR werr = WERR_OK;
char *service = NULL;
char *param = NULL;
- TALLOC_CTX *ctx;
-
- ctx = talloc_init("delparm");
if (argc != 2) {
net_conf_delparm_usage(argc, argv);
@@ -930,7 +807,7 @@ static int net_conf_delparm(int argc, const char **argv)
service = strdup_lower(argv[0]);
param = strdup_lower(argv[1]);
- werr = libnet_smbconf_delparm(ctx, service, param);
+ werr = libnet_conf_delete_parameter(service, param);
if (W_ERROR_EQUAL(werr, WERR_NO_SUCH_SERVICE)) {
d_fprintf(stderr,
@@ -951,6 +828,8 @@ static int net_conf_delparm(int argc, const char **argv)
ret = 0;
done:
+ SAFE_FREE(service);
+ SAFE_FREE(param);
return ret;
}
@@ -967,15 +846,15 @@ int net_conf(int argc, const char **argv)
{"import", net_conf_import,
"Import configuration from file in smb.conf format."},
{"listshares", net_conf_listshares,
- "List the registry shares."},
+ "List the share names."},
{"drop", net_conf_drop,
- "Delete the complete configuration from registry."},
+ "Delete the complete configuration."},
{"showshare", net_conf_showshare,
- "Show the definition of a registry share."},
+ "Show the definition of a share."},
{"addshare", net_conf_addshare,
- "Create a new registry share."},
+ "Create a new share."},
{"delshare", net_conf_delshare,
- "Delete a registry share."},
+ "Delete a share."},
{"setparm", net_conf_setparm,
"Store a parameter."},
{"getparm", net_conf_getparm,
@@ -985,16 +864,8 @@ int net_conf(int argc, const char **argv)
{NULL, NULL, NULL}
};
- if (!registry_init_regdb()) {
- d_fprintf(stderr, "Error initializing the registry!\n");
- goto done;
- }
-
ret = net_run_function2(argc, argv, "net conf", func);
- regdb_close();
-
-done:
return ret;
}
diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c
index 2cb601f917..908be0512a 100644
--- a/source3/utils/net_help.c
+++ b/source3/utils/net_help.c
@@ -48,6 +48,7 @@ int net_common_flags_usage(int argc, const char **argv)
d_printf("\t-l or --long\t\t\tDisplay full information\n");
d_printf("\t-V or --version\t\t\tPrint samba version information\n");
d_printf("\t-P or --machine-pass\t\tAuthenticate as machine account\n");
+ d_printf("\t-e or --encrypt\t\tEncrypt SMB transport (UNIX extended servers only)\n");
return -1;
}
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index ab0cc73e49..155cda64df 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -682,10 +682,10 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
}
done:
if (!NT_STATUS_IS_OK(result)) {
- d_fprintf(stderr, "Failed to add user %s - %s\n", acct_name,
- nt_errstr(result));
+ d_fprintf(stderr, "Failed to add user '%s' with %s.\n",
+ acct_name, nt_errstr(result));
} else {
- d_printf("Added user %s\n", acct_name);
+ d_printf("Added user '%s'.\n", acct_name);
}
return result;
}
@@ -732,12 +732,16 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
POLICY_HND connect_pol, domain_pol, user_pol;
+ const char *acct_name;
if (argc < 1) {
d_printf("User must be specified\n");
rpc_user_usage(argc, argv);
return NT_STATUS_OK;
}
+
+ acct_name = argv[0];
+
/* Get sam policy and domain handles */
result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -762,7 +766,7 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
uint32 flags = 0x000003e8; /* Unknown */
result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
- flags, 1, &argv[0],
+ flags, 1, &acct_name,
&num_rids, &user_rids,
&name_types);
@@ -787,14 +791,14 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
goto done;
}
- /* Display results */
+ done:
if (!NT_STATUS_IS_OK(result)) {
- d_fprintf(stderr, "Failed to delete user account - %s\n", nt_errstr(result));
- } else {
- d_printf("Deleted user account\n");
- }
+ d_fprintf(stderr, "Failed to delete user '%s' with %s.\n",
+ acct_name, nt_errstr(result));
+ } else {
+ d_printf("Deleted user '%s'.\n", acct_name);
+ }
- done:
return result;
}
diff --git a/source3/utils/net_sam.c b/source3/utils/net_sam.c
index bd1f6cd686..52f8f911e1 100644
--- a/source3/utils/net_sam.c
+++ b/source3/utils/net_sam.c
@@ -1135,7 +1135,7 @@ static int net_sam_do_list(int argc, const char **argv,
}
}
- search->search_end(search);
+ pdb_search_destroy(search);
return 0;
}
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index 6884783396..e1d6709073 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -61,69 +61,85 @@ static int export_database (struct pdb_methods *in,
struct pdb_methods *out,
const char *username)
{
- struct samu *user = NULL;
NTSTATUS status;
+ struct pdb_search *u_search;
+ struct samr_displayentry userentry;
DEBUG(3, ("export_database: username=\"%s\"\n", username ? username : "(NULL)"));
- status = in->setsampwent(in, 0, 0);
- if ( NT_STATUS_IS_ERR(status) ) {
- fprintf(stderr, "Unable to set account database iterator for %s!\n",
- in->name);
+ u_search = pdb_search_init(PDB_USER_SEARCH);
+ if (u_search == NULL) {
+ DEBUG(0, ("pdb_search_init failed\n"));
return 1;
}
- if ( ( user = samu_new( NULL ) ) == NULL ) {
- fprintf(stderr, "export_database: Memory allocation failure!\n");
+ if (!in->search_users(in, u_search, 0)) {
+ DEBUG(0, ("Could not start searching users\n"));
+ pdb_search_destroy(u_search);
return 1;
}
- while ( NT_STATUS_IS_OK(in->getsampwent(in, user)) )
- {
- DEBUG(4, ("Processing account %s\n", user->username));
+ while (u_search->next_entry(u_search, &userentry)) {
+ struct samu *user;
+ struct samu *account;
+ DOM_SID user_sid;
- /* If we don't have a specific user or if we do and
- the login name matches */
+ DEBUG(4, ("Processing account %s\n", userentry.account_name));
- if ( !username || (strcmp(username, user->username) == 0)) {
- struct samu *account;
+ if ((username != NULL)
+ && (strcmp(username, userentry.account_name) != 0)) {
+ /*
+ * ignore unwanted users
+ */
+ continue;
+ }
- if ( (account = samu_new( NULL )) == NULL ) {
- fprintf(stderr, "export_database: Memory allocation failure!\n");
- TALLOC_FREE( user );
- in->endsampwent( in );
- return 1;
- }
+ user = samu_new(talloc_tos());
+ if (user == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ break;
+ }
- printf("Importing account for %s...", user->username);
- if ( !NT_STATUS_IS_OK(out->getsampwnam( out, account, user->username )) ) {
- status = out->add_sam_account(out, user);
- } else {
- status = out->update_sam_account( out, user );
- }
+ sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
- if ( NT_STATUS_IS_OK(status) ) {
- printf( "ok\n");
- } else {
- printf( "failed\n");
- }
+ status = in->getsampwsid(in, user, &user_sid);
- TALLOC_FREE( account );
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("getsampwsid failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(user);
+ continue;
}
- /* clean up and get ready for another run */
+ account = samu_new(NULL);
+ if (account == NULL) {
+ fprintf(stderr, "export_database: Memory allocation "
+ "failure!\n");
+ TALLOC_FREE( user );
+ pdb_search_destroy(u_search);
+ return 1;
+ }
- TALLOC_FREE( user );
+ printf("Importing account for %s...", user->username);
+ status = out->getsampwnam(out, account, user->username);
- if ( ( user = samu_new( NULL ) ) == NULL ) {
- fprintf(stderr, "export_database: Memory allocation failure!\n");
- return 1;
+ if (NT_STATUS_IS_OK(status)) {
+ status = out->update_sam_account( out, user );
+ } else {
+ status = out->add_sam_account(out, user);
+ }
+
+ if ( NT_STATUS_IS_OK(status) ) {
+ printf( "ok\n");
+ } else {
+ printf( "failed\n");
}
- }
- TALLOC_FREE( user );
+ TALLOC_FREE( account );
+ TALLOC_FREE( user );
+ }
- in->endsampwent(in);
+ pdb_search_destroy(u_search);
return 0;
}
@@ -326,33 +342,50 @@ static int print_user_info (struct pdb_methods *in, const char *username, bool v
**********************************************************/
static int print_users_list (struct pdb_methods *in, bool verbosity, bool smbpwdstyle)
{
- struct samu *sam_pwent=NULL;
- bool check;
-
- check = NT_STATUS_IS_OK(in->setsampwent(in, False, 0));
- if (!check) {
+ struct pdb_search *u_search;
+ struct samr_displayentry userentry;
+
+ u_search = pdb_search_init(PDB_USER_SEARCH);
+ if (u_search == NULL) {
+ DEBUG(0, ("pdb_search_init failed\n"));
return 1;
}
- check = True;
- if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ if (!in->search_users(in, u_search, 0)) {
+ DEBUG(0, ("Could not start searching users\n"));
+ pdb_search_destroy(u_search);
return 1;
}
- while (check && NT_STATUS_IS_OK(in->getsampwent (in, sam_pwent))) {
+ while (u_search->next_entry(u_search, &userentry)) {
+ struct samu *sam_pwent;
+ DOM_SID user_sid;
+ NTSTATUS status;
+
+ sam_pwent = samu_new(talloc_tos());
+ if (sam_pwent == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ break;
+ }
+
+ sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
+
+ status = in->getsampwsid(in, sam_pwent, &user_sid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("getsampwsid failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(sam_pwent);
+ continue;
+ }
+
if (verbosity)
printf ("---------------\n");
print_sam_info (sam_pwent, verbosity, smbpwdstyle);
TALLOC_FREE(sam_pwent);
-
- if ( (sam_pwent = samu_new( NULL )) == NULL ) {
- check = False;
- }
}
- if (check)
- TALLOC_FREE(sam_pwent);
-
- in->endsampwent(in);
+ pdb_search_destroy(u_search);
+
return 0;
}
@@ -361,38 +394,50 @@ static int print_users_list (struct pdb_methods *in, bool verbosity, bool smbpwd
**********************************************************/
static int fix_users_list (struct pdb_methods *in)
{
- struct samu *sam_pwent=NULL;
- bool check;
-
- check = NT_STATUS_IS_OK(in->setsampwent(in, False, 0));
- if (!check) {
+ struct pdb_search *u_search;
+ struct samr_displayentry userentry;
+
+ u_search = pdb_search_init(PDB_USER_SEARCH);
+ if (u_search == NULL) {
+ DEBUG(0, ("pdb_search_init failed\n"));
return 1;
}
- check = True;
- if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ if (!in->search_users(in, u_search, 0)) {
+ DEBUG(0, ("Could not start searching users\n"));
+ pdb_search_destroy(u_search);
return 1;
}
- while (check && NT_STATUS_IS_OK(in->getsampwent (in, sam_pwent))) {
- printf("Updating record for user %s\n", pdb_get_username(sam_pwent));
-
- if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
- printf("Update of user %s failed!\n", pdb_get_username(sam_pwent));
+ while (u_search->next_entry(u_search, &userentry)) {
+ struct samu *sam_pwent;
+ DOM_SID user_sid;
+ NTSTATUS status;
+
+ sam_pwent = samu_new(talloc_tos());
+ if (sam_pwent == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ break;
}
- TALLOC_FREE(sam_pwent);
- if ( (sam_pwent = samu_new( NULL )) == NULL ) {
- check = False;
+
+ sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
+
+ status = in->getsampwsid(in, sam_pwent, &user_sid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("getsampwsid failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(sam_pwent);
+ continue;
}
- if (!check) {
- fprintf(stderr, "Failed to initialise new struct samu structure (out of memory?)\n");
+
+ if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
+ printf("Update of user %s failed!\n",
+ pdb_get_username(sam_pwent));
}
-
- }
- if (check)
TALLOC_FREE(sam_pwent);
-
- in->endsampwent(in);
+ }
+ pdb_search_destroy(u_search);
return 0;
}
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 958f8e255e..134f561760 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -822,7 +822,7 @@ static int cacl_set(struct cli_state *cli, char *filename,
*******************************************************/
static struct cli_state *connect_one(const char *server, const char *share)
{
- struct cli_state *c;
+ struct cli_state *c = NULL;
struct sockaddr_storage ss;
NTSTATUS nt_status;
zero_addr(&ss);
@@ -834,20 +834,33 @@ static struct cli_state *connect_one(const char *server, const char *share)
}
}
- if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
- &ss, 0,
- share, "?????",
- get_cmdline_auth_info_username(),
- lp_workgroup(),
- get_cmdline_auth_info_password(),
- 0,
- get_cmdline_auth_info_signing_state(),
- NULL))) {
- return c;
- } else {
+ nt_status = cli_full_connection(&c, global_myname(), server,
+ &ss, 0,
+ share, "?????",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ get_cmdline_auth_info_use_kerberos() ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+ get_cmdline_auth_info_signing_state(),
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
return NULL;
}
+
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(c,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ share);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(c);
+ c = NULL;
+ }
+ }
+
+ return c;
}
/****************************************************************************
diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c
index e6aa5e86cf..508a2dc8ca 100644
--- a/source3/utils/smbcquotas.c
+++ b/source3/utils/smbcquotas.c
@@ -380,20 +380,33 @@ static struct cli_state *connect_one(const char *share)
}
}
- if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server,
- &ss, 0,
- share, "?????",
- get_cmdline_auth_info_username(),
- lp_workgroup(),
- get_cmdline_auth_info_password(),
- 0,
- get_cmdline_auth_info_signing_state(),
- NULL))) {
- return c;
- } else {
+ nt_status = cli_full_connection(&c, global_myname(), server,
+ &ss, 0,
+ share, "?????",
+ get_cmdline_auth_info_username(),
+ lp_workgroup(),
+ get_cmdline_auth_info_password(),
+ 0,
+ get_cmdline_auth_info_signing_state(),
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
return NULL;
}
+
+ if (get_cmdline_auth_info_smb_encrypt()) {
+ nt_status = cli_cm_force_encryption(c,
+ get_cmdline_auth_info_username(),
+ get_cmdline_auth_info_password(),
+ lp_workgroup(),
+ share);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(c);
+ return NULL;
+ }
+ }
+
+ return c;
}
/****************************************************************************
diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c
index 912d575c60..8db969722a 100644
--- a/source3/utils/smbfilter.c
+++ b/source3/utils/smbfilter.c
@@ -114,6 +114,30 @@ static void filter_request(char *buf)
}
+/****************************************************************************
+ Send an smb to a fd.
+****************************************************************************/
+
+static bool send_smb(int fd, char *buffer)
+{
+ size_t len;
+ size_t nwritten=0;
+ ssize_t ret;
+
+ len = smb_len(buffer) + 4;
+
+ while (nwritten < len) {
+ ret = write_data(fd,buffer+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ return false;
+ }
+ nwritten += ret;
+ }
+
+ return true;
+}
static void filter_child(int c, struct sockaddr_storage *dest_ss)
{
@@ -145,7 +169,7 @@ static void filter_child(int c, struct sockaddr_storage *dest_ss)
if (num <= 0) continue;
if (c != -1 && FD_ISSET(c, &fds)) {
- if (!receive_smb(c, packet, 0, NULL)) {
+ if (!receive_smb_raw(c, packet, 0, 0, NULL)) {
d_printf("client closed connection\n");
exit(0);
}
@@ -156,7 +180,7 @@ static void filter_child(int c, struct sockaddr_storage *dest_ss)
}
}
if (s != -1 && FD_ISSET(s, &fds)) {
- if (!receive_smb(s, packet, 0, NULL)) {
+ if (!receive_smb_raw(s, packet, 0, 0, NULL)) {
d_printf("server closed connection\n");
exit(0);
}
diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c
index ac662e6ace..63b7f48626 100644
--- a/source3/utils/smbget.c
+++ b/source3/utils/smbget.c
@@ -521,9 +521,11 @@ int main(int argc, const char **argv)
int c = 0;
const char *file = NULL;
char *rcfile = NULL;
+ bool smb_encrypt = false;
TALLOC_CTX *frame = talloc_stackframe();
struct poptOption long_options[] = {
{"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },
+ {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },
{"resume", 'r', POPT_ARG_NONE, &_resume, 0, "Automatically resume aborted files" },
{"recursive", 'R', POPT_ARG_NONE, &_recursive, 0, "Recursively download files" },
{"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },
@@ -568,6 +570,9 @@ int main(int argc, const char **argv)
case 'a':
username = ""; password = "";
break;
+ case 'e':
+ smb_encrypt = true;
+ break;
}
}
@@ -586,6 +591,13 @@ int main(int argc, const char **argv)
return 1;
}
+ if (smb_encrypt) {
+ SMBCCTX *smb_ctx = smbc_set_context(NULL);
+ smbc_option_set(smb_ctx,
+ CONST_DISCARD(char *, "smb_encrypt_level"),
+ "require");
+ }
+
columns = get_num_cols();
total_start_time = time(NULL);
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index c9b2a52388..3aba824b0b 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -1270,12 +1270,24 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
d.domain_type = domains[i].trust_type;
d.domain_trust_attribs = domains[i].trust_attributes;
} else {
+ /* Look up the record in the cache */
+ struct winbindd_tdc_domain *parent;
+
DEBUG(10,("trusted_domains(ads): Inheriting trust "
"flags for domain %s\n", d.alt_name));
+
+ parent = wcache_tdc_fetch_domain(NULL, domain->name);
+ if (parent) {
+ d.domain_flags = parent->trust_flags;
+ d.domain_type = parent->trust_type;
+ d.domain_trust_attribs = parent->trust_attribs;
+ } else {
d.domain_flags = domain->domain_flags;
d.domain_type = domain->domain_type;
d.domain_trust_attribs = domain->domain_trust_attribs;
}
+ TALLOC_FREE(parent);
+ }
wcache_tdc_add_domain( &d );
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 7fb42a6dca..99e401d53f 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -601,8 +601,34 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
- werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
+ if (our_domain->active_directory) {
+ struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL;
+
+ werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ NULL,
+ NULL,
+ DS_RETURN_DNS_NAME,
+ &domain_info);
+ if (W_ERROR_IS_OK(werr)) {
+ fstrcpy(tmp, domain_info->domain_controller_name);
+ if (strlen(domain->alt_name) == 0) {
+ fstrcpy(domain->alt_name,
+ CONST_DISCARD(char*, domain_info->domain_name));
+ }
+ if (strlen(domain->forest_name) == 0) {
+ fstrcpy(domain->forest_name,
+ CONST_DISCARD(char*, domain_info->dns_forest_name));
+ }
+ }
+ } else {
+
+ werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx,
+ our_domain->dcname,
domain->name, &tmp);
+ }
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
@@ -978,6 +1004,7 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
char *p;
fstring my_acct_name;
fstring my_mailslot;
+ size_t sid_size;
if (dc_ss->ss_family != AF_INET) {
return false;
@@ -1019,7 +1046,9 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
SIVAL(p, 0, 0x80);
p+=4;
- SIVAL(p, 0, sid_size(sid));
+ sid_size = ndr_size_dom_sid(sid, 0);
+
+ SIVAL(p, 0, sid_size);
p+=4;
p = ALIGN4(p, outbuf);
@@ -1027,12 +1056,12 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
return false;
}
- sid_linearize(p, sid_size(sid), sid);
- if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
+ if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
return false;
}
+ sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
- p += sid_size(sid);
+ p += sid_size;
SIVAL(p, 0, 1);
SSVAL(p, 4, 0xffff);
@@ -1866,9 +1895,17 @@ no_lsarpc_ds:
if (dns_name)
fstrcpy(domain->alt_name, dns_name);
- if ( forest_name )
+ /* See if we can set some domain trust flags about
+ ourself */
+
+ if ( forest_name ) {
fstrcpy(domain->forest_name, forest_name);
+ if (strequal(domain->forest_name, domain->alt_name)) {
+ domain->domain_flags = DS_DOMAIN_TREE_ROOT;
+ }
+ }
+
if (dom_sid)
sid_copy(&domain->sid, dom_sid);
} else {
diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c
index fbd2fee692..62e8d1c40b 100644
--- a/source3/winbindd/winbindd_group.c
+++ b/source3/winbindd/winbindd_group.c
@@ -1494,9 +1494,18 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
s->username = talloc_strdup( state->mem_ctx, state->request.data.username );
}
- /* Get info for the domain */
+ /* Get info for the domain (either by short domain name or
+ DNS name in the case of a UPN) */
s->domain = find_domain_from_name_noinit(s->domname);
+ if (!s->domain) {
+ char *p = strchr(s->username, '@');
+
+ if (p) {
+ s->domain = find_domain_from_name_noinit(p+1);
+ }
+
+ }
if (s->domain == NULL) {
DEBUG(7, ("could not find domain entry for domain %s\n",
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index ffb47692cb..f5e1226447 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -456,6 +456,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
/* no cache; hit the wire */
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 70468b6bcd..cc12d4b7ea 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -500,9 +500,13 @@ void rescan_trusted_domains( void )
((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
return;
- /* clear the TRUSTDOM cache first */
-
- wcache_tdc_clear();
+ /* I use to clear the cache here and start over but that
+ caused problems in child processes that needed the
+ trust dom list early on. Removing it means we
+ could have some trusted domains listed that have been
+ removed from our primary domain's DC until a full
+ restart. This should be ok since I think this is what
+ Windows does as well. */
/* this will only add new domains we didn't already know about
in the domain_list()*/