diff options
Diffstat (limited to 'source3')
69 files changed, 1744 insertions, 492 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 1376f4c07a..f87cb88801 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -681,7 +681,7 @@ GROUPDB_OBJ = groupdb/mapping.o groupdb/mapping_tdb.o groupdb/mapping_ldb.o PROFILE_OBJ = profile/profile.o PROFILES_OBJ = utils/profiles.o \ - $(LIBSAMBA_OBJ) \ + $(LIBSMB_ERR_OBJ) \ $(PARAM_OBJ) \ $(LIB_OBJ) $(LIB_DUMMY_OBJ) \ $(POPT_LIB_OBJ) @@ -740,6 +740,7 @@ VFS_ONEFS_SHADOW_COPY_OBJ = modules/vfs_onefs_shadow_copy.o modules/onefs_shadow PERFCOUNT_ONEFS_OBJ = modules/perfcount_onefs.o PERFCOUNT_TEST_OBJ = modules/perfcount_test.o VFS_DIRSORT_OBJ = modules/vfs_dirsort.o +VFS_SCANNEDONLY_OBJ = modules/vfs_scannedonly.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -860,7 +861,7 @@ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(PRINTBASE_OBJ) $(LIBSMB_O STATUS_OBJ = utils/status.o utils/status_profile.o \ $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - $(LIBSAMBA_OBJ) $(FNAME_UTIL_OBJ) + $(LIBSMB_ERR_OBJ) $(FNAME_UTIL_OBJ) SMBCONTROL_OBJ = utils/smbcontrol.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSMB_ERR_OBJ) $(POPT_LIB_OBJ) $(PRINTBASE_OBJ) @@ -875,7 +876,7 @@ SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \ TESTPARM_OBJ = utils/testparm.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - $(LIBSAMBA_OBJ) + $(LIBSMB_ERR_OBJ) TEST_LP_LOAD_OBJ = param/test_lp_load.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ @@ -1038,7 +1039,7 @@ CIFS_UMOUNT_OBJ = ../client/umount.cifs.o ../client/mtab.o CIFS_UPCALL_OBJ = ../client/cifs.upcall.o NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) \ - $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSAMBA_OBJ) + $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \ torture/denytest.o torture/mangle_test.o \ @@ -1053,7 +1054,7 @@ MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLI $(LIB_NONSMBD_OBJ) \ $(LIBNDR_GEN_OBJ0) -MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \ +MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_ERR_OBJ) $(LDB_OBJ) \ $(LIB_NONSMBD_OBJ) \ $(LIBNDR_GEN_OBJ0) @@ -1070,7 +1071,7 @@ PDBTEST_OBJ = torture/pdbtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ) -SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSAMBA_OBJ) +SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) LOG2PCAP_OBJ = utils/log2pcaphex.o @@ -1092,18 +1093,18 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ EVTLOGADM_OBJ0 = utils/eventlogadm.o EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ - $(LIBSAMBA_OBJ) \ + $(LIBSMB_ERR_OBJ) \ registry/reg_eventlog.o $(LIB_EVENTLOG_OBJ) \ ../librpc/gen_ndr/ndr_eventlog.o \ ../librpc/gen_ndr/ndr_lsa.o SHARESEC_OBJ0 = utils/sharesec.o SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ - $(LIBSAMBA_OBJ) \ + $(LIBSMB_ERR_OBJ) \ $(POPT_LIB_OBJ) TALLOCTORT_OBJ = @tallocdir@/testsuite.o @tallocdir@/testsuite_main.o \ - $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSAMBA_OBJ) + $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) REPLACETORT_OBJ = @libreplacedir@/test/testsuite.o \ @libreplacedir@/test/getifaddrs.o \ @@ -1119,8 +1120,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) \ $(LIBNDR_GEN_OBJ0) WINBIND_WINS_NSS_OBJ = ../nsswitch/wins.o $(PARAM_OBJ) \ - $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) \ - $(LIBNDR_GEN_OBJ0) $(LDB_OBJ) + $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNMB_OBJ) PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o ../lib/util/asn1.o @@ -1334,12 +1334,12 @@ RPC_OPEN_TCP_OBJ = torture/rpc_open_tcp.o \ DBWRAP_TOOL_OBJ = utils/dbwrap_tool.o \ $(PARAM_OBJ) \ $(LIB_NONSMBD_OBJ) \ - $(LIBSAMBA_OBJ) + $(LIBSMB_ERR_OBJ) DBWRAP_TORTURE_OBJ = utils/dbwrap_torture.o \ $(PARAM_OBJ) \ $(LIB_NONSMBD_OBJ) \ - $(LIBSAMBA_OBJ) \ + $(LIBSMB_ERR_OBJ) \ $(POPT_LIB_OBJ) SPLIT_TOKENS_OBJ = utils/split_tokens.o \ @@ -2831,6 +2831,10 @@ bin/dirsort.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_DIRSORT_OBJ) @echo "Building plugin $@" @$(SHLD_MODULE) $(VFS_DIRSORT_OBJ) +bin/scannedonly.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_SCANNEDONLY_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(VFS_SCANNEDONLY_OBJ) + ######################################################### ## IdMap NSS plugins diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c index 3741f29779..f8f048a6f2 100644 --- a/source3/auth/auth_builtin.c +++ b/source3/auth/auth_builtin.c @@ -34,8 +34,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { /* mark this as 'not for me' */ NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; @@ -77,8 +77,8 @@ static NTSTATUS auth_init_guest(struct auth_context *auth_context, const char *o static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; fstring user; @@ -130,8 +130,8 @@ static NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, co static NTSTATUS check_fixed_challenge_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source3/auth/auth_compat.c b/source3/auth/auth_compat.c index 77a994828f..e90036f3ff 100644 --- a/source3/auth/auth_compat.c +++ b/source3/auth/auth_compat.c @@ -35,10 +35,12 @@ SMB hash return True if the password is correct, False otherwise ****************************************************************************/ -NTSTATUS check_plaintext_password(const char *smb_name, DATA_BLOB plaintext_password, auth_serversupplied_info **server_info) +NTSTATUS check_plaintext_password(const char *smb_name, + DATA_BLOB plaintext_password, + struct auth_serversupplied_info **server_info) { struct auth_context *plaintext_auth_context = NULL; - auth_usersupplied_info *user_info = NULL; + struct auth_usersupplied_info *user_info = NULL; uint8_t chal[8]; NTSTATUS nt_status; if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { @@ -72,9 +74,9 @@ static NTSTATUS pass_check_smb(struct auth_context *actx, { NTSTATUS nt_status; - auth_serversupplied_info *server_info = NULL; + struct auth_serversupplied_info *server_info = NULL; if (encrypted) { - auth_usersupplied_info *user_info = NULL; + struct auth_usersupplied_info *user_info = NULL; if (actx == NULL) { return NT_STATUS_INTERNAL_ERROR; } diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index c527360321..a07aa617c4 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -251,10 +251,10 @@ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); ************************************************************************/ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, + const struct auth_usersupplied_info *user_info, const char *domain, uchar chal[8], - auth_serversupplied_info **server_info, + struct auth_serversupplied_info **server_info, const char *dc_name, struct sockaddr_storage *dc_ss) @@ -372,8 +372,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; const char *domain = lp_workgroup(); @@ -441,8 +441,8 @@ static NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char static NTSTATUS check_trustdomain_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; unsigned char trust_md4_password[16]; diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index ebfed83d41..bfd12281c4 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -27,7 +27,7 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, const struct auth_context *auth_context, const char *ncalrpc_sockname, uint8_t schannel_key[16], - const auth_usersupplied_info *user_info, + const struct auth_usersupplied_info *user_info, struct netr_SamInfo3 **pinfo3, NTSTATUS *schannel_bind_result) { @@ -153,8 +153,8 @@ static char *mymachinepw(TALLOC_CTX *mem_ctx) static NTSTATUS check_netlogond_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { TALLOC_CTX *frame = talloc_stackframe(); struct netr_SamInfo3 *info3 = NULL; diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index 4243a24ca7..88f0e69443 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -85,7 +85,7 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, { AUTH_NTLMSSP_STATE *auth_ntlmssp_state = (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context; - auth_usersupplied_info *user_info = NULL; + struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; bool username_was_mapped; diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index f0500b3611..1dd8fc950e 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -33,21 +33,23 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, - struct samu *sampass, - const auth_usersupplied_info *user_info, + const char *username, + uint32_t acct_ctrl, + const uint8_t *lm_pw, + const uint8_t *nt_pw, + const struct auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { - uint32 acct_ctrl; - const uint8 *lm_pw, *nt_pw; - struct samr_Password lm_hash, nt_hash, client_lm_hash, client_nt_hash; - const char *username = pdb_get_username(sampass); - bool got_lm = false, got_nt = false; + struct samr_Password _lm_hash, _nt_hash, _client_lm_hash, _client_nt_hash; + struct samr_Password *lm_hash = NULL; + struct samr_Password *nt_hash = NULL; + struct samr_Password *client_lm_hash = NULL; + struct samr_Password *client_nt_hash = NULL; - *user_sess_key = data_blob(NULL, 0); - *lm_sess_key = data_blob(NULL, 0); + *user_sess_key = data_blob_null; + *lm_sess_key = data_blob_null; - acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username)); @@ -58,34 +60,35 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, } } - lm_pw = pdb_get_lanman_passwd(sampass); - nt_pw = pdb_get_nt_passwd(sampass); if (lm_pw) { - memcpy(lm_hash.hash, lm_pw, sizeof(lm_hash.hash)); + memcpy(_lm_hash.hash, lm_pw, sizeof(_lm_hash.hash)); + lm_hash = &_lm_hash; } if (nt_pw) { - memcpy(nt_hash.hash, nt_pw, sizeof(nt_hash.hash)); + memcpy(_nt_hash.hash, nt_pw, sizeof(_nt_hash.hash)); + nt_hash = &_nt_hash; } - if (user_info->lm_interactive_pwd.data && sizeof(client_lm_hash.hash) == user_info->lm_interactive_pwd.length) { - memcpy(client_lm_hash.hash, user_info->lm_interactive_pwd.data, sizeof(lm_hash.hash)); - got_lm = true; + if (user_info->lm_interactive_pwd.data && sizeof(_client_lm_hash.hash) == user_info->lm_interactive_pwd.length) { + memcpy(_client_lm_hash.hash, user_info->lm_interactive_pwd.data, sizeof(_lm_hash.hash)); + client_lm_hash = &_client_lm_hash; } - if (user_info->nt_interactive_pwd.data && sizeof(client_nt_hash.hash) == user_info->nt_interactive_pwd.length) { - memcpy(client_nt_hash.hash, user_info->nt_interactive_pwd.data, sizeof(nt_hash.hash)); - got_nt = true; + if (user_info->nt_interactive_pwd.data && sizeof(_client_nt_hash.hash) == user_info->nt_interactive_pwd.length) { + memcpy(_client_nt_hash.hash, user_info->nt_interactive_pwd.data, sizeof(_nt_hash.hash)); + client_nt_hash = &_client_nt_hash; } - if (got_lm || got_nt) { - *user_sess_key = data_blob(mem_ctx, 16); + + if (client_lm_hash || client_nt_hash) { + *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16); if (!user_sess_key->data) { return NT_STATUS_NO_MEMORY; } SMBsesskeygen_ntv1(nt_pw, user_sess_key->data); return hash_password_check(mem_ctx, lp_lanman_auth(), - got_lm ? &client_lm_hash : NULL, - got_nt ? &client_nt_hash : NULL, + client_lm_hash, + client_nt_hash, username, - lm_pw ? &lm_hash: NULL, - nt_pw ? &nt_hash : NULL); + lm_hash, + nt_hash); } else { return ntlm_password_check(mem_ctx, lp_lanman_auth(), lp_ntlm_auth(), @@ -95,8 +98,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, username, user_info->smb_name, user_info->client_domain, - lm_pw ? &lm_hash: NULL, - nt_pw ? &nt_hash : NULL, + lm_hash, + nt_hash, user_sess_key, lm_sess_key); } } @@ -165,7 +168,7 @@ static bool logon_hours_ok(struct samu *sampass) static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, struct samu *sampass, - const auth_usersupplied_info *user_info) + const struct auth_usersupplied_info *user_info) { uint32 acct_ctrl = pdb_get_acct_ctrl(sampass); char *workstation_list; @@ -278,6 +281,75 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/** + * Check whether the given password is one of the last two + * password history entries. If so, the bad pwcount should + * not be incremented even thought the actual password check + * failed. + */ +static bool need_to_increment_bad_pw_count( + const struct auth_context *auth_context, + struct samu* sampass, + const struct auth_usersupplied_info *user_info) +{ + uint8_t i; + const uint8_t *pwhistory; + uint32_t pwhistory_len; + uint32_t policy_pwhistory_len; + uint32_t acct_ctrl; + const char *username; + TALLOC_CTX *mem_ctx = talloc_stackframe(); + bool result = true; + + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, + &policy_pwhistory_len); + if (policy_pwhistory_len == 0) { + goto done; + } + + pwhistory = pdb_get_pw_history(sampass, &pwhistory_len); + if (!pwhistory || pwhistory_len == 0) { + goto done; + } + + acct_ctrl = pdb_get_acct_ctrl(sampass); + username = pdb_get_username(sampass); + + for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) { + static const uint8_t zero16[SALTED_MD5_HASH_LEN]; + const uint8_t *salt; + const uint8_t *nt_pw; + NTSTATUS status; + DATA_BLOB user_sess_key = data_blob_null; + DATA_BLOB lm_sess_key = data_blob_null; + + salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; + nt_pw = salt + PW_HISTORY_SALT_LEN; + + if (memcmp(zero16, nt_pw, NT_HASH_LEN) == 0) { + /* skip zero password hash */ + continue; + } + + if (memcmp(zero16, salt, PW_HISTORY_SALT_LEN) != 0) { + /* skip nonzero salt (old format entry) */ + continue; + } + + status = sam_password_ok(auth_context, mem_ctx, + username, acct_ctrl, NULL, nt_pw, + user_info, &user_sess_key, &lm_sess_key); + if (NT_STATUS_IS_OK(status)) { + result = false; + break; + } + } + +done: + TALLOC_FREE(mem_ctx); + return result; +} + /**************************************************************************** check if a username/password is OK assuming the password is a 24 byte SMB hash supplied in the user_info structure @@ -287,8 +359,8 @@ return an NT_STATUS constant. static NTSTATUS check_sam_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { struct samu *sampass=NULL; bool ret; @@ -297,6 +369,10 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, DATA_BLOB user_sess_key = data_blob_null; DATA_BLOB lm_sess_key = data_blob_null; bool updated_autolock = False, updated_badpw = False; + uint32_t acct_ctrl; + const char *username; + const uint8_t *nt_pw; + const uint8_t *lm_pw; if (!user_info || !auth_context) { return NT_STATUS_UNSUCCESSFUL; @@ -305,7 +381,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, /* the returned struct gets kept on the server_info, by means of a steal further down */ - if ( !(sampass = samu_new( mem_ctx )) ) { + sampass = samu_new(mem_ctx); + if (sampass == NULL) { return NT_STATUS_NO_MEMORY; } @@ -322,16 +399,22 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, return NT_STATUS_NO_SUCH_USER; } + acct_ctrl = pdb_get_acct_ctrl(sampass); + username = pdb_get_username(sampass); + nt_pw = pdb_get_nt_passwd(sampass); + lm_pw = pdb_get_lanman_passwd(sampass); + /* see if autolock flag needs to be updated */ - if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) + if (acct_ctrl & ACB_NORMAL) pdb_update_autolock_flag(sampass, &updated_autolock); /* Quit if the account was locked out. */ - if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) { - DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", pdb_get_username(sampass))); + if (acct_ctrl & ACB_AUTOLOCK) { + DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } - nt_status = sam_password_ok(auth_context, mem_ctx, sampass, + nt_status = sam_password_ok(auth_context, mem_ctx, + username, acct_ctrl, lm_pw, nt_pw, user_info, &user_sess_key, &lm_sess_key); /* Notify passdb backend of login success/failure. If not @@ -340,10 +423,19 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { + bool increment_bad_pw_count = false; + if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && - pdb_get_acct_ctrl(sampass) &ACB_NORMAL && + acct_ctrl & ACB_NORMAL && NT_STATUS_IS_OK(update_login_attempts_status)) - { + { + increment_bad_pw_count = + need_to_increment_bad_pw_count(auth_context, + sampass, + user_info); + } + + if (increment_bad_pw_count) { pdb_increment_bad_password_count(sampass); updated_badpw = True; } else { @@ -351,18 +443,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, &updated_badpw); } if (updated_autolock || updated_badpw){ + NTSTATUS status; + become_root(); - if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass))) - DEBUG(1, ("Failed to modify entry.\n")); + status = pdb_update_sam_account(sampass); unbecome_root(); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to modify entry: %s\n", + nt_errstr(status))); + } } - data_blob_free(&user_sess_key); - data_blob_free(&lm_sess_key); - TALLOC_FREE(sampass); - return nt_status; + goto done; } - if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && + if ((acct_ctrl & ACB_NORMAL) && (pdb_get_bad_password_count(sampass) > 0)){ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); @@ -370,30 +465,36 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, } if (updated_autolock || updated_badpw){ + NTSTATUS status; + become_root(); - if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass))) - DEBUG(1, ("Failed to modify entry.\n")); + status = pdb_update_sam_account(sampass); unbecome_root(); - } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to modify entry: %s\n", + nt_errstr(status))); + } + } nt_status = sam_account_ok(mem_ctx, sampass, user_info); if (!NT_STATUS_IS_OK(nt_status)) { - TALLOC_FREE(sampass); - data_blob_free(&user_sess_key); - data_blob_free(&lm_sess_key); - return nt_status; + goto done; } become_root(); nt_status = make_server_info_sam(server_info, sampass); unbecome_root(); + /* + * sampass has been stolen to server_info. + * So NULL it out to prevent segfaults. + */ + sampass = NULL; if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); - data_blob_free(&user_sess_key); - data_blob_free(&lm_sess_key); - return nt_status; + goto done; } (*server_info)->user_session_key = @@ -408,6 +509,10 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, (*server_info)->nss_token |= user_info->was_mapped; +done: + TALLOC_FREE(sampass); + data_blob_free(&user_sess_key); + data_blob_free(&lm_sess_key); return nt_status; } @@ -431,8 +536,8 @@ Check SAM security (above) but with a few extra checks. static NTSTATUS check_samstrict_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { bool is_local_name, is_my_domain; diff --git a/source3/auth/auth_script.c b/source3/auth/auth_script.c index 6cbace71e8..be1ae81501 100644 --- a/source3/auth/auth_script.c +++ b/source3/auth/auth_script.c @@ -40,8 +40,8 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { const char *script = lp_parm_const_string( GLOBAL_SECTION_SNUM, "auth_script", "script", NULL); char *secret_str; diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 287b50b080..ec92787dce 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -270,8 +270,8 @@ static DATA_BLOB auth_get_challenge_server(const struct auth_context *auth_conte static NTSTATUS check_smbserver_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { struct server_security_state *state = talloc_get_type_abort( my_private_data, struct server_security_state); diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index 58c765226d..3e2df9a123 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -85,8 +85,8 @@ static bool update_smbpassword_file(const char *user, const char *password) static NTSTATUS check_unix_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 8167a80a4f..de552cf57e 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -33,7 +33,7 @@ auth_serversupplied_info struct. ****************************************************************************/ -static void sort_sid_array_for_smbd(auth_serversupplied_info *result, +static void sort_sid_array_for_smbd(struct auth_serversupplied_info *result, const DOM_SID *pgroup_sid) { unsigned int i; @@ -107,7 +107,7 @@ static int _smb_create_user(const char *domain, const char *unix_username, const Create an auth_usersupplied_data structure ****************************************************************************/ -static NTSTATUS make_user_info(auth_usersupplied_info **user_info, +static NTSTATUS make_user_info(struct auth_usersupplied_info **user_info, const char *smb_name, const char *internal_username, const char *client_domain, @@ -121,7 +121,7 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); - *user_info = SMB_MALLOC_P(auth_usersupplied_info); + *user_info = SMB_MALLOC_P(struct auth_usersupplied_info); if (*user_info == NULL) { DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info))); return NT_STATUS_NO_MEMORY; @@ -188,7 +188,7 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, Create an auth_usersupplied_data structure after appropriate mapping. ****************************************************************************/ -NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, +NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -252,7 +252,7 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, Decrypt and encrypt the passwords. ****************************************************************************/ -bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, +bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -290,7 +290,7 @@ bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, Decrypt and encrypt the passwords. ****************************************************************************/ -bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, +bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -402,7 +402,7 @@ bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, Create an auth_usersupplied_data structure ****************************************************************************/ -bool make_user_info_for_reply(auth_usersupplied_info **user_info, +bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const uint8 chal[8], @@ -460,7 +460,7 @@ bool make_user_info_for_reply(auth_usersupplied_info **user_info, Create an auth_usersupplied_data structure ****************************************************************************/ -NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, +NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, DATA_BLOB lm_resp, DATA_BLOB nt_resp) @@ -478,7 +478,7 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, Create a guest user_info blob, for anonymous authenticaion. ****************************************************************************/ -bool make_user_info_guest(auth_usersupplied_info **user_info) +bool make_user_info_guest(struct auth_usersupplied_info **user_info) { NTSTATUS nt_status; @@ -494,7 +494,7 @@ bool make_user_info_guest(auth_usersupplied_info **user_info) return NT_STATUS_IS_OK(nt_status) ? True : False; } -static int server_info_dtor(auth_serversupplied_info *server_info) +static int server_info_dtor(struct auth_serversupplied_info *server_info) { TALLOC_FREE(server_info->sam_account); ZERO_STRUCTP(server_info); @@ -505,11 +505,11 @@ static int server_info_dtor(auth_serversupplied_info *server_info) Make a server_info struct. Free with TALLOC_FREE(). ***************************************************************************/ -static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx) +static struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx) { struct auth_serversupplied_info *result; - result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info); + result = TALLOC_ZERO_P(mem_ctx, struct auth_serversupplied_info); if (result == NULL) { DEBUG(0, ("talloc failed\n")); return NULL; @@ -562,12 +562,12 @@ static bool is_our_machine_account(const char *username) Make (and fill) a user_info struct from a struct samu ***************************************************************************/ -NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, +NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info, struct samu *sampass) { struct passwd *pwd; gid_t *gids; - auth_serversupplied_info *result; + struct auth_serversupplied_info *result; const char *username = pdb_get_username(sampass); NTSTATUS status; @@ -701,7 +701,7 @@ static NTSTATUS log_nt_token(NT_USER_TOKEN *token) * server_info->sids (the info3/sam groups). Find the unix gids. */ -NTSTATUS create_local_token(auth_serversupplied_info *server_info) +NTSTATUS create_local_token(struct auth_serversupplied_info *server_info) { NTSTATUS status; size_t i; @@ -1140,7 +1140,7 @@ bool user_in_group(const char *username, const char *groupname) to a struct samu ***************************************************************************/ -NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, +NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, char *unix_username, struct passwd *pwd) { @@ -1151,7 +1151,7 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, TALLOC_CTX *mem_ctx = NULL; DOM_SID u_sid; enum lsa_SidType type; - auth_serversupplied_info *result; + struct auth_serversupplied_info *result; if ( !(sampass = samu_new( NULL )) ) { return NT_STATUS_NO_MEMORY; @@ -1261,7 +1261,7 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, the guest gid, then create one. ***************************************************************************/ -static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info) +static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info) { NTSTATUS status; struct samu *sampass = NULL; @@ -1274,8 +1274,7 @@ static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_inf return NT_STATUS_NO_MEMORY; } - sid_copy(&guest_sid, get_global_sam_sid()); - sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST); + sid_compose(&guest_sid, get_global_sam_sid(), DOMAIN_USER_RID_GUEST); become_root(); ret = pdb_getsampwsid(sampass, &guest_sid); @@ -1355,9 +1354,9 @@ NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx, - const auth_serversupplied_info *src) + const struct auth_serversupplied_info *src) { - auth_serversupplied_info *dst; + struct auth_serversupplied_info *dst; dst = make_server_info(mem_ctx); if (dst == NULL) { @@ -1433,7 +1432,7 @@ bool server_info_set_session_key(struct auth_serversupplied_info *info, return (info->user_session_key.data != NULL); } -static auth_serversupplied_info *guest_info = NULL; +static struct auth_serversupplied_info *guest_info = NULL; bool init_guest_info(void) { @@ -1444,7 +1443,7 @@ bool init_guest_info(void) } NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx, - auth_serversupplied_info **server_info) + struct auth_serversupplied_info **server_info) { *server_info = copy_serverinfo(mem_ctx, guest_info); return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; @@ -1620,7 +1619,7 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser, NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, - auth_serversupplied_info **server_info, + struct auth_serversupplied_info **server_info, struct netr_SamInfo3 *info3) { char zeros[16]; @@ -1637,7 +1636,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; - auth_serversupplied_info *result; + struct auth_serversupplied_info *result; /* Here is where we should check the list of @@ -1645,13 +1644,12 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, matches. */ - sid_copy(&user_sid, info3->base.domain_sid); - if (!sid_append_rid(&user_sid, info3->base.rid)) { + if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) { return NT_STATUS_INVALID_PARAMETER; } - sid_copy(&group_sid, info3->base.domain_sid); - if (!sid_append_rid(&group_sid, info3->base.primary_gid)) { + if (!sid_compose(&group_sid, info3->base.domain_sid, + info3->base.primary_gid)) { return NT_STATUS_INVALID_PARAMETER; } @@ -1873,7 +1871,7 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, const struct wbcAuthUserInfo *info, - auth_serversupplied_info **server_info) + struct auth_serversupplied_info **server_info) { char zeros[16]; @@ -1890,7 +1888,7 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; - auth_serversupplied_info *result; + struct auth_serversupplied_info *result; result = make_server_info(NULL); if (result == NULL) { @@ -2114,7 +2112,7 @@ NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, Free a user_info struct ***************************************************************************/ -void free_user_info(auth_usersupplied_info **user_info) +void free_user_info(struct auth_usersupplied_info **user_info) { DEBUG(5,("attempting to free (and zero) a user_info structure\n")); if (*user_info != NULL) { diff --git a/source3/auth/auth_wbc.c b/source3/auth/auth_wbc.c index 580c8b550d..85b05efb36 100644 --- a/source3/auth/auth_wbc.c +++ b/source3/auth/auth_wbc.c @@ -47,8 +47,8 @@ static NTSTATUS check_wbc_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index d1b00a3268..74723e6af4 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -30,8 +30,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; diff --git a/source3/configure.in b/source3/configure.in index e3f53b45c2..d17cdac846 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -439,6 +439,7 @@ default_shared_modules="$default_shared_modules vfs_acl_tdb" default_shared_modules="$default_shared_modules vfs_smb_traffic_analyzer" default_shared_modules="$default_shared_modules vfs_preopen" default_shared_modules="$default_shared_modules vfs_catia" +default_shared_modules="$default_shared_modules vfs_scannedonly" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_rpcecho pdb_ads" @@ -6552,6 +6553,7 @@ SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_ SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS) SMB_MODULE(vfs_onefs_shadow_copy, \$(VFS_ONEFS_SHADOW_COPY), "bin/onefs_shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_dirsort, \$(VFS_DIRSORT_OBJ), "bin/dirsort.$SHLIBEXT", VFS) +SMB_MODULE(vfs_scannedonly, \$(VFS_SCANNEDONLY_OBJ), "bin/scannedonly.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 12d0bd365c..579486b874 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -519,8 +519,7 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, DEBUG(10, ("Creating alias %s with gid %u and rid %u\n", name, (unsigned int)gid, (unsigned int)new_rid)); - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, new_rid); + sid_compose(&sid, get_global_sam_sid(), new_rid); map.gid = gid; sid_copy(&map.sid, &sid); diff --git a/source3/include/auth.h b/source3/include/auth.h index 7d778b92d0..115143fb73 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -typedef struct auth_usersupplied_info { +struct auth_usersupplied_info { DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB lm_interactive_pwd; @@ -38,9 +38,9 @@ typedef struct auth_usersupplied_info { uint32 logon_parameters; -} auth_usersupplied_info; +}; -typedef struct auth_serversupplied_info { +struct auth_serversupplied_info { bool guest; DOM_SID *sids; /* These SIDs are preliminary between @@ -77,7 +77,7 @@ typedef struct auth_serversupplied_info { * smb request. See set_current_user_info. */ char *sanitized_username; -} auth_serversupplied_info; +}; struct auth_context { DATA_BLOB challenge; @@ -110,7 +110,7 @@ typedef struct auth_methods void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info); + struct auth_serversupplied_info **server_info); /* If you are using this interface, then you are probably * getting something wrong. This interface is only for diff --git a/source3/include/proto.h b/source3/include/proto.h index 5b16120294..8e8b35cb5a 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -38,7 +38,9 @@ NTSTATUS auth_builtin_init(void); /* The following definitions come from auth/auth_compat.c */ -NTSTATUS check_plaintext_password(const char *smb_name, DATA_BLOB plaintext_password, auth_serversupplied_info **server_info); +NTSTATUS check_plaintext_password(const char *smb_name, + DATA_BLOB plaintext_password, + struct auth_serversupplied_info **server_info); bool password_ok(struct auth_context *actx, bool global_encrypted, const char *session_workgroup, const char *smb_name, DATA_BLOB password_blob); @@ -71,7 +73,7 @@ NTSTATUS auth_unix_init(void); /* The following definitions come from auth/auth_util.c */ -NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, +NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -79,7 +81,7 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd, DATA_BLOB *plaintext, bool encrypted); -bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, +bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -88,7 +90,7 @@ bool make_user_info_netlogon_network(auth_usersupplied_info **user_info, int lm_pwd_len, const uchar *nt_network_pwd, int nt_pwd_len); -bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, +bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, @@ -97,19 +99,19 @@ bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, const uchar lm_interactive_pwd[16], const uchar nt_interactive_pwd[16], const uchar *dc_sess_key); -bool make_user_info_for_reply(auth_usersupplied_info **user_info, +bool make_user_info_for_reply(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const uint8 chal[8], DATA_BLOB plaintext_password); -NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, +NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, DATA_BLOB lm_resp, DATA_BLOB nt_resp); -bool make_user_info_guest(auth_usersupplied_info **user_info) ; -NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, +bool make_user_info_guest(struct auth_usersupplied_info **user_info) ; +NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info, struct samu *sampass); -NTSTATUS create_local_token(auth_serversupplied_info *server_info); +NTSTATUS create_local_token(struct auth_serversupplied_info *server_info); NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, bool is_guest, uid_t *uid, gid_t *gid, @@ -117,7 +119,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, struct nt_user_token **token); bool user_in_group_sid(const char *username, const DOM_SID *group_sid); bool user_in_group(const char *username, const char *groupname); -NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, +NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info, char *unix_username, struct passwd *pwd); NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx, @@ -125,26 +127,26 @@ NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx, bool is_guest, struct auth_serversupplied_info **presult); struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx, - const auth_serversupplied_info *src); + const struct auth_serversupplied_info *src); bool init_guest_info(void); bool server_info_set_session_key(struct auth_serversupplied_info *info, DATA_BLOB session_key); NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx, - auth_serversupplied_info **server_info); + struct auth_serversupplied_info **server_info); bool copy_current_user(struct current_user *dst, struct current_user *src); struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser, fstring save_username, bool create ); NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, - auth_serversupplied_info **server_info, + struct auth_serversupplied_info **server_info, struct netr_SamInfo3 *info3); NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, const struct wbcAuthUserInfo *info, - auth_serversupplied_info **server_info); -void free_user_info(auth_usersupplied_info **user_info); + struct auth_serversupplied_info **server_info); +void free_user_info(struct auth_usersupplied_info **user_info); bool make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) ; bool is_trusted_domain(const char* dom_name); @@ -1286,7 +1288,6 @@ void security_acl_map_generic(struct security_acl *sa, const struct generic_mapp void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping); NTSTATUS se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, uint32 acc_desired, uint32 *acc_granted); -NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size); /* The following definitions come from lib/util_sec.c */ @@ -6116,6 +6117,9 @@ NTSTATUS pass_oem_change(char *user, uchar password_encrypted_with_nt_hash[516], const uchar old_nt_hash_encrypted[16], enum samPwdChangeReason *reject_reason); +bool password_in_history(uint8_t nt_pw[NT_HASH_LEN], + uint32_t pw_history_len, + const uint8_t *pw_history); NTSTATUS check_password_complexity(const char *username, const char *password, enum samPwdChangeReason *samr_reject_reason); @@ -6713,7 +6717,7 @@ void invalidate_all_vuids(struct smbd_server_connection *sconn); int register_initial_vuid(struct smbd_server_connection *sconn); int register_existing_vuid(struct smbd_server_connection *sconn, uint16 vuid, - auth_serversupplied_info *server_info, + struct auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name); void add_session_user(struct smbd_server_connection *sconn, const char *user); diff --git a/source3/include/smb.h b/source3/include/smb.h index b23ea647ec..bc7a90d549 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -451,6 +451,7 @@ typedef struct files_struct { bool aio_write_behind; bool lockdb_clean; bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */ + bool delete_on_close; bool posix_open; struct smb_filename *fsp_name; diff --git a/source3/lib/time.c b/source3/lib/time.c index 5286af37fd..dffc03b1cf 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -198,17 +198,17 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires) void srv_put_dos_date(char *buf,int offset,time_t unixdate) { - push_dos_date(buf, offset, unixdate, server_zone_offset); + push_dos_date((uint8_t *)buf, offset, unixdate, server_zone_offset); } void srv_put_dos_date2(char *buf,int offset, time_t unixdate) { - push_dos_date2(buf, offset, unixdate, server_zone_offset); + push_dos_date2((uint8_t *)buf, offset, unixdate, server_zone_offset); } void srv_put_dos_date3(char *buf,int offset,time_t unixdate) { - push_dos_date3(buf, offset, unixdate, server_zone_offset); + push_dos_date3((uint8_t *)buf, offset, unixdate, server_zone_offset); } void round_timespec(enum timestamp_set_resolution res, struct timespec *ts) @@ -439,17 +439,17 @@ struct timespec interpret_long_date(const char *p) void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate) { - push_dos_date(buf, offset, unixdate, cli->serverzone); + push_dos_date((uint8_t *)buf, offset, unixdate, cli->serverzone); } void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate) { - push_dos_date2(buf, offset, unixdate, cli->serverzone); + push_dos_date2((uint8_t *)buf, offset, unixdate, cli->serverzone); } void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate) { - push_dos_date3(buf, offset, unixdate, cli->serverzone); + push_dos_date3((uint8_t *)buf, offset, unixdate, cli->serverzone); } time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr) diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index 0da7442d19..e5562b5289 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -246,43 +246,3 @@ done: return NT_STATUS_OK; } - -/******************************************************************* - samr_make_sam_obj_sd - ********************************************************************/ - -NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) -{ - DOM_SID adm_sid; - DOM_SID act_sid; - - SEC_ACE ace[3]; - - SEC_ACL *psa = NULL; - - sid_copy(&adm_sid, &global_sid_Builtin); - sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); - - sid_copy(&act_sid, &global_sid_Builtin); - sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); - - /*basic access for every one*/ - init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, - GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ, 0); - - /*full access for builtin aliases Administrators and Account Operators*/ - init_sec_ace(&ace[1], &adm_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, GENERIC_RIGHTS_SAM_ALL_ACCESS, 0); - init_sec_ace(&ace[2], &act_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, GENERIC_RIGHTS_SAM_ALL_ACCESS, 0); - - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) - return NT_STATUS_NO_MEMORY; - - if ((*psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1, - SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, - psa, sd_size)) == NULL) - return NT_STATUS_NO_MEMORY; - - return NT_STATUS_OK; -} diff --git a/source3/libnet/libnet_samsync_passdb.c b/source3/libnet/libnet_samsync_passdb.c index 41a9b3d9f3..51f96dc398 100644 --- a/source3/libnet/libnet_samsync_passdb.c +++ b/source3/libnet/libnet_samsync_passdb.c @@ -318,8 +318,7 @@ static NTSTATUS fetch_account_info(TALLOC_CTX *mem_ctx, goto done; } - sid_copy(&user_sid, get_global_sam_sid()); - sid_append_rid(&user_sid, r->rid); + sid_compose(&user_sid, get_global_sam_sid(), r->rid); DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_fstring(sid_string, &user_sid), account)); @@ -395,8 +394,7 @@ static NTSTATUS fetch_group_info(TALLOC_CTX *mem_ctx, fstrcpy(comment, r->description.string); /* add the group to the mapping table */ - sid_copy(&group_sid, get_global_sam_sid()); - sid_append_rid(&group_sid, rid); + sid_compose(&group_sid, get_global_sam_sid(), rid); sid_to_fstring(sid_string, &group_sid); if (pdb_getgrsid(&map, group_sid)) { @@ -459,8 +457,7 @@ static NTSTATUS fetch_group_mem_info(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - sid_copy(&group_sid, get_global_sam_sid()); - sid_append_rid(&group_sid, rid); + sid_compose(&group_sid, get_global_sam_sid(), rid); if (!get_domain_group_from_sid(group_sid, &map)) { DEBUG(0, ("Could not find global group %d\n", rid)); @@ -491,8 +488,7 @@ static NTSTATUS fetch_group_mem_info(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - sid_copy(&member_sid, get_global_sam_sid()); - sid_append_rid(&member_sid, r->rids[i]); + sid_compose(&member_sid, get_global_sam_sid(), r->rids[i]); if (!pdb_getsampwsid(member, &member_sid)) { DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n", @@ -587,8 +583,7 @@ static NTSTATUS fetch_alias_info(TALLOC_CTX *mem_ctx, fstrcpy(comment, r->description.string); /* Find out whether the group is already mapped */ - sid_copy(&alias_sid, dom_sid); - sid_append_rid(&alias_sid, rid); + sid_compose(&alias_sid, dom_sid, rid); sid_to_fstring(sid_string, &alias_sid); if (pdb_getgrsid(&map, alias_sid)) { diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 31216b8240..fa79ebcea3 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1573,6 +1573,8 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx, char *tmp = NULL; uint8_t *bytes; + *psmbreq = NULL; + req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state); if (req == NULL) { return NULL; @@ -1708,6 +1710,9 @@ struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + if (subreq == NULL) { + return req; + } status = cli_smb_req_send(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 12901826ee..7339acb4d7 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -113,8 +113,7 @@ void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3) NETSAMLOGON_TDB)); return; } - sid_copy(&user_sid, info3->base.domain_sid); - sid_append_rid(&user_sid, info3->base.rid); + sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); /* Prepare key as DOMAIN-SID/USER-RID string */ slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid)); @@ -151,8 +150,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) return false; } - sid_copy(&user_sid, info3->base.domain_sid); - sid_append_rid(&user_sid, info3->base.rid); + sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); /* Prepare key as DOMAIN-SID/USER-RID string */ slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid)); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 26018f90db..095d0b17b9 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -1459,6 +1459,9 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USE } TALLOC_FREE(lck); + + fsp->delete_on_close = delete_on_close; + return True; } diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 1eec448083..aeb9ce37ea 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -760,6 +760,108 @@ static SMB_STRUCT_DIR *opendir_acl_common(vfs_handle_struct *handle, return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); } +static int acl_common_remove_object(vfs_handle_struct *handle, + const char *path, + bool is_directory) +{ + connection_struct *conn = handle->conn; + struct file_id id; + files_struct *fsp = NULL; + int ret = 0; + char *parent_dir = NULL; + const char *final_component = NULL; + struct smb_filename local_fname; + int saved_errno = 0; + + if (!parent_dirname(talloc_tos(), path, + &parent_dir, &final_component)) { + saved_errno = ENOMEM; + goto out; + } + + DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n", + is_directory ? "directory" : "file", + parent_dir, final_component )); + + /* cd into the parent dir to pin it. */ + ret = SMB_VFS_CHDIR(conn, parent_dir); + if (ret == -1) { + saved_errno = errno; + goto out; + } + + ZERO_STRUCT(local_fname); + local_fname.base_name = CONST_DISCARD(char *,final_component); + + /* Must use lstat here. */ + ret = SMB_VFS_LSTAT(conn, &local_fname); + if (ret == -1) { + saved_errno = errno; + goto out; + } + + /* Ensure we have this file open with DELETE access. */ + id = vfs_file_id_from_sbuf(conn, &local_fname.st); + for (fsp = file_find_di_first(id); fsp; file_find_di_next(fsp)) { + if (fsp->access_mask & DELETE_ACCESS && + fsp->delete_on_close) { + /* We did open this for delete, + * allow the delete as root. + */ + break; + } + } + + if (!fsp) { + DEBUG(10,("acl_common_remove_object: %s %s/%s " + "not an open file\n", + is_directory ? "directory" : "file", + parent_dir, final_component )); + saved_errno = EACCES; + goto out; + } + + if (is_directory) { + ret = SMB_VFS_NEXT_RMDIR(handle, final_component); + } else { + ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname); + } + if (ret == -1) { + saved_errno = errno; + } + + out: + + TALLOC_FREE(parent_dir); + + vfs_ChDir(conn, conn->connectpath); + if (saved_errno) { + errno = saved_errno; + } + return ret; +} + +static int rmdir_acl_common(struct vfs_handle_struct *handle, + const char *path) +{ + int ret; + + ret = SMB_VFS_NEXT_RMDIR(handle, path); + if (!(ret == -1 && (errno == EACCES || errno == EPERM))) { + DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n", + path, + strerror(errno) )); + return ret; + } + + become_root(); + ret = acl_common_remove_object(handle, + path, + true); + unbecome_root(); + return ret; +} + static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle, struct smb_request *req, uint16_t root_dir_fid, @@ -857,3 +959,28 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle, /* NOTREACHED */ return status; } + +static int unlink_acl_common(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) +{ + int ret; + + ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); + if (!(ret == -1 && (errno == EACCES || errno == EPERM))) { + DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n", + smb_fname->base_name, + strerror(errno) )); + return ret; + } + /* Don't do anything fancy for streams. */ + if (smb_fname->stream_name) { + return ret; + } + + become_root(); + ret = acl_common_remove_object(handle, + smb_fname->base_name, + false); + unbecome_root(); + return ret; +} diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index a1088ab63c..2afe69d764 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -265,7 +265,7 @@ static int unlink_acl_tdb(vfs_handle_struct *handle, goto out; } - ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp); + ret = unlink_acl_common(handle, smb_fname_tmp); if (ret == -1) { goto out; @@ -413,6 +413,7 @@ static struct vfs_fn_pointers vfs_acl_tdb_fns = { .connect_fn = connect_acl_tdb, .opendir = opendir_acl_common, .mkdir = mkdir_acl_common, + .rmdir = rmdir_acl_common, .open = open_acl_common, .create_file = create_file_acl_common, .unlink = unlink_acl_tdb, diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index 625ef91e8f..18f2d42784 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -199,8 +199,10 @@ static struct vfs_fn_pointers vfs_acl_xattr_fns = { .connect_fn = connect_acl_xattr, .opendir = opendir_acl_common, .mkdir = mkdir_acl_common, + .rmdir = rmdir_acl_common, .open = open_acl_common, .create_file = create_file_acl_common, + .unlink = unlink_acl_common, .fget_nt_acl = fget_nt_acl_common, .get_nt_acl = get_nt_acl_common, .fset_nt_acl = fset_nt_acl_common, diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 7edbb8783c..35fa740dd0 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -695,12 +695,13 @@ static char *capdecode(TALLOC_CTX *ctx, const char *from) size_t len = 0; for (p1 = from; *p1; len++) { - if (is_hex(from)) { + if (is_hex(p1)) { p1 += 3; } else { p1++; } } + len++; to = TALLOC_ARRAY(ctx, char, len); if (!to) { diff --git a/source3/modules/vfs_scannedonly.c b/source3/modules/vfs_scannedonly.c new file mode 100644 index 0000000000..ff16d78c3f --- /dev/null +++ b/source3/modules/vfs_scannedonly.c @@ -0,0 +1,995 @@ +/* + * scannedonly VFS module for Samba 3.5 + * + * Copyright 2007,2008,2009 (C) Olivier Sessink + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * ABOUT SCANNEDONLY + * + * scannedonly implements a 'filter' like vfs module that talks over a + * unix domain socket or over UDP to a anti-virus engine. + * + * files that are clean have a corresponding .scanned:{filename} file + * in the same directory. So why the .scanned: files? They take up + * only an inode, because they are 0 bytes. To test if the file is + * scanned only a stat() call on the filesystem is needed which is + * very quick compared to a database lookup. All modern filesystems + * use database technology such as balanced trees for lookups anyway. + * The number of inodes in modern filesystems is also not limiting + * anymore. The .scanned: files are also easy scriptable. You can + * remove them with a simple find command or create them with a + * simple touch command. Extended filesystem attributes have similar + * properties, but are not supported on all filesystems, so that + * would limit the usage of the module (and attributes are not as + * easily scriptable) + * + * files that are not clean are sent to the AV-engine. Only the + * filename is sent over the socket. The protocol is very simple: + * a newline separated list of filenames inside each datagram. + * + * a file AV-scan may be requested multiple times, the AV-engine + * should also check if the file has been scanned already. Requests + * can also be dropped by the AV-engine (and we thus don't need the + * reliability of TCP). + * + */ + +#include "includes.h" + +#include "config.h" + +#define SENDBUFFERSIZE 1450 + +struct Tscannedonly { + int socket; + int domain_socket; + int portnum; + int scanning_message_len; + int recheck_time_open; + int recheck_tries_open; + int recheck_size_open; + int recheck_time_readdir; + int recheck_tries_readdir; + bool show_special_files; + bool rm_hidden_files_on_rmdir; + bool hide_nonscanned_files; + bool allow_nonscanned_files; + char *socketname; + char *scanhost; + char *scanning_message; + char *p_scanned; /* prefix for scanned files */ + char *p_virus; /* prefix for virus containing files */ + char *p_failed; /* prefix for failed to scan files */ + char gsendbuffer[SENDBUFFERSIZE + 1]; +}; + +#define STRUCTSCANO(var) ((struct Tscannedonly *)var) + +struct scannedonly_DIR { + char *base; + int notify_loop_done; + SMB_STRUCT_DIR *DIR; +}; +#define SCANNEDONLY_DEBUG 9 +/*********************/ +/* utility functions */ +/*********************/ + +static char *real_path_from_notify_path(TALLOC_CTX *ctx, + struct Tscannedonly *so, + const char *path) +{ + char *name; + int len, pathlen; + + name = strrchr(path, '/'); + if (!name) { + return NULL; + } + pathlen = name - path; + name++; + len = strlen(name); + if (len <= so->scanning_message_len) { + return NULL; + } + + if (strcmp(name + (len - so->scanning_message_len), + so->scanning_message) != 0) { + return NULL; + } + + return talloc_strndup(ctx,path, + pathlen + len - so->scanning_message_len); +} + +static char *cachefile_name(TALLOC_CTX *ctx, + const char *shortname, + const char *base, + const char *p_scanned) +{ + return talloc_asprintf(ctx, "%s%s%s", base, p_scanned, shortname); +} + +static char *name_w_ending_slash(TALLOC_CTX *ctx, const char *name) +{ + int len = strlen(name); + if (name[len - 1] == '/') { + return talloc_strdup(ctx,name); + } else { + return talloc_asprintf(ctx, "%s/", name); + } +} + +static char *cachefile_name_f_fullpath(TALLOC_CTX *ctx, + const char *fullpath, + const char *p_scanned) +{ + const char *base; + char *tmp, *cachefile, *shortname; + tmp = strrchr(fullpath, '/'); + if (tmp) { + base = talloc_strndup(ctx, fullpath, (tmp - fullpath) + 1); + shortname = tmp + 1; + } else { + base = ""; + shortname = (char *)fullpath; + } + cachefile = cachefile_name(ctx, shortname, base, p_scanned); + DEBUG(SCANNEDONLY_DEBUG, + ("cachefile_name_f_fullpath cachefile=%s\n", cachefile)); + return cachefile; +} + +static char *path_plus_name(TALLOC_CTX *ctx, const char *base, + const char *filename) +{ + return talloc_asprintf(ctx, "%s%s", base,filename); +} + +static char *construct_full_path(TALLOC_CTX *ctx, vfs_handle_struct * handle, + const char *somepath, bool ending_slash) +{ + char *tmp; + + if (!somepath) { + return NULL; + } + if (somepath[0] == '/') { + if (ending_slash) { + return name_w_ending_slash(ctx,somepath); + } + return talloc_strdup(ctx,somepath); + } + tmp=(char *)somepath; + if (tmp[0]=='.'&&tmp[1]=='/') { + tmp+=2; + } + /* vfs_GetWd() seems to return a path with a slash */ + if (ending_slash) { + return talloc_asprintf(ctx, "%s%s/", + vfs_GetWd(ctx, handle->conn),tmp); + } + return talloc_asprintf(ctx, "%s%s", + vfs_GetWd(ctx, handle->conn),tmp); +} + +static int connect_to_scanner(vfs_handle_struct * handle) +{ + struct Tscannedonly *so = (struct Tscannedonly *)handle->data; + + if (so->domain_socket) { + struct sockaddr_un saun; + DEBUG(SCANNEDONLY_DEBUG, ("socket=%s\n", so->socketname)); + if ((so->socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + DEBUG(2, ("failed to create socket %s\n", + so->socketname)); + return -1; + } + saun.sun_family = AF_UNIX; + strncpy(saun.sun_path, so->socketname, + sizeof(saun.sun_path) - 1); + if (connect(so->socket, (struct sockaddr *)(void *)&saun, + SUN_LEN(&saun)) < 0) { + DEBUG(2, ("failed to connect to socket %s\n", + so->socketname)); + return -1; + } + DEBUG(SCANNEDONLY_DEBUG,("bound %s to socket %d\n", + saun.sun_path, so->socket)); + + } else { + so->socket = open_udp_socket(so->scanhost, so->portnum); + if (so->socket < 0) { + DEBUG(2,("failed to open UDP socket to %s:%d\n", + so->scanhost,so->portnum)); + return -1; + } + } + + {/* increasing the socket buffer is done because we have large bursts + of UDP packets or DGRAM's on a domain socket whenever we hit a + large directory with lots of unscanned files. */ + int sndsize; + socklen_t size = sizeof(int); + getsockopt(so->socket, SOL_SOCKET, SO_RCVBUF, + (char *)&sndsize, &size); + DEBUG(SCANNEDONLY_DEBUG, ("current socket buffer size=%d\n", + sndsize)); + sndsize = 262144; + if (setsockopt(so->socket, SOL_SOCKET, SO_RCVBUF, + (char *)&sndsize, + (int)sizeof(sndsize)) != 0) { + DEBUG(SCANNEDONLY_DEBUG, + ("error setting socket buffer %s (%d)\n", + strerror(errno), errno)); + } + } + set_blocking(so->socket, false); + return 0; +} + +static void flush_sendbuffer(vfs_handle_struct * handle) +{ + struct Tscannedonly *so = (struct Tscannedonly *)handle->data; + int ret, len, loop = 10; + if (so->gsendbuffer[0] == '\0') { + return; + } + + do { + loop--; + len = strlen(so->gsendbuffer); + ret = send(so->socket, so->gsendbuffer, len, MSG_DONTWAIT); + if (ret == len) { + so->gsendbuffer[0] = '\0'; + break; + } + if (ret == -1) { + DEBUG(3,("scannedonly flush_sendbuffer: " + "error sending on socket %d to scanner:" + " %s (%d)\n", + so->socket, strerror(errno), errno)); + if (errno == ECONNREFUSED || errno == ENOTCONN + || errno == ECONNRESET) { + if (connect_to_scanner(handle) == -1) + break; /* connecting fails, abort */ + /* try again */ + } else if (errno != EINTR) { + /* on EINTR we just try again, all remaining + other errors we log the error + and try again ONCE */ + loop = 1; + DEBUG(3,("scannedonly flush_sendbuffer: " + "error sending data to scanner: %s " + "(%d)\n", strerror(errno), errno)); + } + } else { + /* --> partial write: Resend all filenames that were + not or not completely written. a partial filename + written means the filename will not arrive correctly, + so resend it completely */ + int pos = 0; + while (pos < len) { + char *tmp = strchr(so->gsendbuffer+pos, '\n'); + if (tmp && tmp - so->gsendbuffer < ret) + pos = tmp - so->gsendbuffer + 1; + else + break; + } + memmove(so->gsendbuffer, so->gsendbuffer + pos, + SENDBUFFERSIZE - ret); + /* now try again */ + } + } while (loop > 0); + + if (so->gsendbuffer[0] != '\0') { + DEBUG(2, + ("scannedonly flush_sendbuffer: " + "failed to send files to AV scanner, " + "discarding files.")); + so->gsendbuffer[0] = '\0'; + } +} + +static void notify_scanner(vfs_handle_struct * handle, const char *scanfile) +{ + char *tmp; + int tmplen, gsendlen; + struct Tscannedonly *so = (struct Tscannedonly *)handle->data; + TALLOC_CTX *ctx=talloc_tos(); + if (scanfile[0] != '/') { + tmp = construct_full_path(ctx,handle, scanfile, false); + } else { + tmp = (char *)scanfile; + } + tmplen = strlen(tmp); + gsendlen = strlen(so->gsendbuffer); + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly notify_scanner: tmp=%s, tmplen=%d, gsendlen=%d\n", + tmp, tmplen, gsendlen)); + if (gsendlen + tmplen >= SENDBUFFERSIZE) { + flush_sendbuffer(handle); + } + strlcat(so->gsendbuffer, tmp, SENDBUFFERSIZE + 1); + strlcat(so->gsendbuffer, "\n", SENDBUFFERSIZE + 1); +} + +static bool is_scannedonly_file(struct Tscannedonly *so, const char *shortname) +{ + if (shortname[0]!='.') { + return false; + } + if (strncmp(shortname, so->p_scanned, strlen(so->p_scanned)) == 0) { + return true; + } + if (strncmp(shortname, so->p_virus, strlen(so->p_virus)) == 0) { + return true; + } + if (strncmp(shortname, so->p_failed, strlen(so->p_failed)) == 0) { + return true; + } + return false; +} + +static bool timespec_is_newer(struct timespec *base, struct timespec *test) +{ + return timespec_compare(base,test) < 0; +} + +/* +vfs_handle_struct *handle the scannedonly handle +scannedonly_DIR * sDIR the scannedonly struct if called from _readdir() +or NULL +fullpath is a full path starting from / or a relative path to the +current working directory +shortname is the filename without directory components +basename, is the directory without file name component +allow_nonexistant return TRUE if stat() on the requested file fails +recheck_time, the time in milliseconds to wait for the daemon to +create a .scanned file +recheck_tries, the number of tries to wait +recheck_size, size in Kb of files that should not be waited for +loop : boolean if we should try to loop over all files in the directory +and send a notify to the scanner for all files that need scanning +*/ +static bool scannedonly_allow_access(vfs_handle_struct * handle, + struct scannedonly_DIR *sDIR, + struct smb_filename *smb_fname, + const char *shortname, + const char *base_name, + int allow_nonexistant, + int recheck_time, int recheck_tries, + int recheck_size, int loop) +{ + struct smb_filename *cache_smb_fname; + TALLOC_CTX *ctx=talloc_tos(); + char *cachefile; + int retval; + int didloop; + DEBUG(SCANNEDONLY_DEBUG, + ("smb_fname->base_name=%s, shortname=%s, base_name=%s\n" + ,smb_fname->base_name,shortname,base_name)); + + if (ISDOT(shortname) || ISDOTDOT(shortname)) { + return true; + } + if (is_scannedonly_file(STRUCTSCANO(handle->data), shortname)) { + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_allow_access, %s is a scannedonly file, " + "return 0\n", shortname)); + return false; + } + + if (!VALID_STAT(smb_fname->st)) { + DEBUG(SCANNEDONLY_DEBUG,("stat %s\n",smb_fname->base_name)); + retval = SMB_VFS_NEXT_STAT(handle, smb_fname); + if (retval != 0) { + /* failed to stat this file?!? --> hide it */ + DEBUG(SCANNEDONLY_DEBUG,("no valid stat, return" + " allow_nonexistant=%d\n", + allow_nonexistant)); + return allow_nonexistant; + } + } + if (!S_ISREG(smb_fname->st.st_ex_mode)) { + DEBUG(SCANNEDONLY_DEBUG, + ("%s is not a regular file, ISDIR=%d\n", + smb_fname->base_name, + S_ISDIR(smb_fname->st.st_ex_mode))); + return (STRUCTSCANO(handle->data)-> + show_special_files || + S_ISDIR(smb_fname->st.st_ex_mode)); + } + if (smb_fname->st.st_ex_size == 0) { + DEBUG(SCANNEDONLY_DEBUG,("empty file, return 1\n")); + return true; /* empty files cannot contain viruses ! */ + } + cachefile = cachefile_name(ctx, + shortname, + base_name, + STRUCTSCANO(handle->data)->p_scanned); + create_synthetic_smb_fname(ctx, cachefile,NULL,NULL,&cache_smb_fname); + if (!VALID_STAT(cache_smb_fname->st)) { + retval = SMB_VFS_NEXT_STAT(handle, cache_smb_fname); + } + if (retval == 0 && VALID_STAT(cache_smb_fname->st)) { + if (timespec_is_newer(&smb_fname->st.st_ex_mtime, + &cache_smb_fname->st.st_ex_mtime)) { + talloc_free(cache_smb_fname); + return true; + } + /* no cachefile or too old */ + SMB_VFS_NEXT_UNLINK(handle, cache_smb_fname); + retval = -1; + } + + notify_scanner(handle, smb_fname->base_name); + + didloop = 0; + if (loop && sDIR && !sDIR->notify_loop_done) { + /* check the rest of the directory and notify the + scanner if some file needs scanning */ + long offset; + SMB_STRUCT_DIRENT *dire; + + offset = SMB_VFS_NEXT_TELLDIR(handle, sDIR->DIR); + dire = SMB_VFS_NEXT_READDIR(handle, sDIR->DIR, NULL); + while (dire) { + char *fpath2; + struct smb_filename *smb_fname2; + fpath2 = path_plus_name(ctx,base_name, dire->d_name); + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_allow_access in loop, " + "found %s\n", fpath2)); + create_synthetic_smb_fname(ctx, fpath2,NULL,NULL, + &smb_fname2); + scannedonly_allow_access(handle, NULL, + smb_fname2, + dire->d_name, + base_name, 0, 0, 0, 0, 0); + talloc_free(fpath2); + talloc_free(smb_fname2); + dire = SMB_VFS_NEXT_READDIR(handle, sDIR->DIR,NULL); + } + sDIR->notify_loop_done = 1; + didloop = 1; + SMB_VFS_NEXT_SEEKDIR(handle, sDIR->DIR, offset); + } + if (recheck_time > 0 + && ((recheck_size > 0 + && smb_fname->st.st_ex_size < (1024 * recheck_size)) + || didloop)) { + int i = 0; + flush_sendbuffer(handle); + while (retval != 0 /*&& errno == ENOENT */ + && i < recheck_tries) { + struct timespec req = { 0, recheck_time * 10000 }; + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_allow_access, wait (try=%d " + "(max %d), %d ms) for %s\n", + i, recheck_tries, + recheck_time, cache_smb_fname->base_name)); + nanosleep(&req, NULL); + retval = SMB_VFS_NEXT_STAT(handle, cache_smb_fname); + i++; + } + } + /* still no cachefile, or still too old, return 0 */ + if (retval != 0 + || !timespec_is_newer(&smb_fname->st.st_ex_mtime, + &cache_smb_fname->st.st_ex_mtime)) { + DEBUG(SCANNEDONLY_DEBUG, + ("retval=%d, return 0\n",retval)); + return false; + } + return true; +} + +/*********************/ +/* VFS functions */ +/*********************/ + +static SMB_STRUCT_DIR *scannedonly_opendir(vfs_handle_struct * handle, + const char *fname, + const char *mask, uint32 attr) +{ + SMB_STRUCT_DIR *DIRp; + struct scannedonly_DIR *sDIR; + + DIRp = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr); + if (!DIRp) { + return NULL; + } + + sDIR = TALLOC_P(NULL, struct scannedonly_DIR); + if (fname[0] != '/') { + sDIR->base = construct_full_path(sDIR,handle, fname, true); + } else { + sDIR->base = name_w_ending_slash(sDIR, fname); + } + sDIR->DIR = DIRp; + sDIR->notify_loop_done = 0; + return (SMB_STRUCT_DIR *) sDIR; +} + +static SMB_STRUCT_DIRENT *scannedonly_readdir(vfs_handle_struct *handle, + SMB_STRUCT_DIR * dirp, + SMB_STRUCT_STAT *sbuf) +{ + SMB_STRUCT_DIRENT *result; + int allowed = 0; + char *tmp; + struct smb_filename *smb_fname; + char *notify_name; + int namelen; + SMB_STRUCT_DIRENT *newdirent; + TALLOC_CTX *ctx=talloc_tos(); + + struct scannedonly_DIR *sDIR = (struct scannedonly_DIR *)dirp; + if (!dirp) { + return NULL; + } + + result = SMB_VFS_NEXT_READDIR(handle, sDIR->DIR, sbuf); + + if (!result) + return NULL; + + if (is_scannedonly_file(STRUCTSCANO(handle->data), result->d_name)) { + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_readdir, %s is a scannedonly file, " + "skip to next entry\n", result->d_name)); + return scannedonly_readdir(handle, dirp, NULL); + } + + tmp = path_plus_name(ctx,sDIR->base, result->d_name); + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_readdir, check access to %s (sbuf=%p)\n", + tmp,sbuf)); + + /* even if we don't hide nonscanned files or we allow non scanned + files we call allow_access because it will notify the daemon to + scan these files */ + create_synthetic_smb_fname(ctx, tmp,NULL, + sbuf?VALID_STAT(*sbuf)?sbuf:NULL:NULL, + &smb_fname); + allowed = scannedonly_allow_access( + handle, sDIR, smb_fname, + result->d_name, + sDIR->base, 0, + STRUCTSCANO(handle->data)->hide_nonscanned_files + ? STRUCTSCANO(handle->data)->recheck_time_readdir + : 0, + STRUCTSCANO(handle->data)->recheck_tries_readdir, + -1, + 1); + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_readdir access to %s (%s) = %d\n", tmp, + result->d_name, allowed)); + if (allowed) { + return result; + } + DEBUG(SCANNEDONLY_DEBUG, + ("hide_nonscanned_files=%d, allow_nonscanned_files=%d\n", + STRUCTSCANO(handle->data)->hide_nonscanned_files, + STRUCTSCANO(handle->data)->allow_nonscanned_files + )); + + if (!STRUCTSCANO(handle->data)->hide_nonscanned_files + || STRUCTSCANO(handle->data)->allow_nonscanned_files) { + return result; + } + + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_readdir, readdir listing for %s not " + "allowed, notify user\n", result->d_name)); + notify_name = talloc_asprintf( + ctx,"%s %s",result->d_name, + STRUCTSCANO(handle->data)->scanning_message); + namelen = strlen(notify_name); + newdirent = (SMB_STRUCT_DIRENT *)TALLOC_ARRAY( + ctx, char, sizeof(SMB_STRUCT_DIRENT) + namelen + 1); + if (!newdirent) { + return NULL; + } + memcpy(newdirent, result, sizeof(SMB_STRUCT_DIRENT)); + memcpy(&newdirent->d_name, notify_name, namelen + 1); + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_readdir, return newdirent at %p with " + "notification %s\n", newdirent, newdirent->d_name)); + return newdirent; +} + +static void scannedonly_seekdir(struct vfs_handle_struct *handle, + SMB_STRUCT_DIR * dirp, long offset) +{ + struct scannedonly_DIR *sDIR = (struct scannedonly_DIR *)dirp; + SMB_VFS_NEXT_SEEKDIR(handle, sDIR->DIR, offset); +} + +static long scannedonly_telldir(struct vfs_handle_struct *handle, + SMB_STRUCT_DIR * dirp) +{ + struct scannedonly_DIR *sDIR = (struct scannedonly_DIR *)dirp; + return SMB_VFS_NEXT_TELLDIR(handle, sDIR->DIR); +} + +static void scannedonly_rewinddir(struct vfs_handle_struct *handle, + SMB_STRUCT_DIR * dirp) +{ + struct scannedonly_DIR *sDIR = (struct scannedonly_DIR *)dirp; + SMB_VFS_NEXT_REWINDDIR(handle, sDIR->DIR); +} + +static int scannedonly_closedir(vfs_handle_struct * handle, + SMB_STRUCT_DIR * dirp) +{ + int retval; + struct scannedonly_DIR *sDIR = (struct scannedonly_DIR *)dirp; + flush_sendbuffer(handle); + retval = SMB_VFS_NEXT_CLOSEDIR(handle, sDIR->DIR); + TALLOC_FREE(sDIR); + return retval; +} + +static int scannedonly_stat(vfs_handle_struct * handle, + struct smb_filename *smb_fname) +{ + int ret; + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + DEBUG(SCANNEDONLY_DEBUG, ("scannedonly_stat: %s returned %d\n", + smb_fname->base_name, ret)); + if (ret != 0 && errno == ENOENT) { + TALLOC_CTX *ctx=talloc_tos(); + char *test_base_name, *tmp_base_name = smb_fname->base_name; + /* possibly this was a fake name (file is being scanned for + viruses.txt): check for that and create the real name and + stat the real name */ + test_base_name = real_path_from_notify_path( + ctx, + STRUCTSCANO(handle->data), + smb_fname->base_name); + if (test_base_name) { + smb_fname->base_name = test_base_name; + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + DEBUG(5, ("_stat: %s returned %d\n", + test_base_name, ret)); + smb_fname->base_name = tmp_base_name; + } + } + return ret; +} + +static int scannedonly_lstat(vfs_handle_struct * handle, + struct smb_filename *smb_fname) +{ + int ret; + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + DEBUG(SCANNEDONLY_DEBUG, ("scannedonly_lstat: %s returned %d\n", + smb_fname->base_name, ret)); + if (ret != 0 && errno == ENOENT) { + TALLOC_CTX *ctx=talloc_tos(); + char *test_base_name, *tmp_base_name = smb_fname->base_name; + /* possibly this was a fake name (file is being scanned for + viruses.txt): check for that and create the real name and + stat the real name */ + test_base_name = real_path_from_notify_path( + ctx, STRUCTSCANO(handle->data), smb_fname->base_name); + if (test_base_name) { + smb_fname->base_name = test_base_name; + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + DEBUG(5, ("_lstat: %s returned %d\n", + test_base_name, ret)); + smb_fname->base_name = tmp_base_name; + } + } + return ret; +} + +static int scannedonly_open(vfs_handle_struct * handle, + struct smb_filename *smb_fname, + files_struct * fsp, int flags, mode_t mode) +{ + const char *base; + char *tmp, *shortname; + int allowed, write_access = 0; + TALLOC_CTX *ctx=talloc_tos(); + /* if open for writing ignore it */ + if ((flags & O_ACCMODE) == O_WRONLY) { + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + } + if ((flags & O_ACCMODE) == O_RDWR) { + write_access = 1; + } + /* check if this file is scanned already */ + tmp = strrchr(smb_fname->base_name, '/'); + if (tmp) { + base = talloc_strndup(ctx,smb_fname->base_name, + (tmp - smb_fname->base_name) + 1); + shortname = tmp + 1; + } else { + base = ""; + shortname = (char *)smb_fname->base_name; + } + allowed = scannedonly_allow_access( + handle, NULL, smb_fname, shortname, + base, + write_access, + STRUCTSCANO(handle->data)->recheck_time_open, + STRUCTSCANO(handle->data)->recheck_tries_open, + STRUCTSCANO(handle->data)->recheck_size_open, + 0); + flush_sendbuffer(handle); + DEBUG(SCANNEDONLY_DEBUG, ("scannedonly_open: allow=%d for %s\n", + allowed, smb_fname->base_name)); + if (allowed + || STRUCTSCANO(handle->data)->allow_nonscanned_files) { + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + } + errno = EACCES; + return -1; +} + +static int scannedonly_close(vfs_handle_struct * handle, files_struct * fsp) +{ + /* we only have to notify the scanner + for files that were open readwrite or writable. */ + if (fsp->can_write) { + TALLOC_CTX *ctx = talloc_tos(); + notify_scanner(handle, construct_full_path( + ctx,handle, + fsp->fsp_name->base_name,false)); + flush_sendbuffer(handle); + } + return SMB_VFS_NEXT_CLOSE(handle, fsp); +} + +static int scannedonly_rename(vfs_handle_struct * handle, + const struct smb_filename *smb_fname_src, + const struct smb_filename *smb_fname_dst) +{ + /* rename the cache file before we pass the actual rename on */ + struct smb_filename *smb_fname_src_tmp = NULL; + struct smb_filename *smb_fname_dst_tmp = NULL; + char *cachefile_src, *cachefile_dst; + TALLOC_CTX *ctx = talloc_tos(); + + /* Setup temporary smb_filename structs. */ + cachefile_src = cachefile_name_f_fullpath( + ctx, + smb_fname_src->base_name, + STRUCTSCANO(handle->data)->p_scanned); + cachefile_dst = cachefile_name_f_fullpath( + ctx, + smb_fname_dst->base_name, + STRUCTSCANO(handle->data)->p_scanned); + + create_synthetic_smb_fname(ctx, cachefile_src,NULL,NULL, + &smb_fname_src_tmp); + create_synthetic_smb_fname(ctx, cachefile_dst,NULL,NULL, + &smb_fname_dst_tmp); + + if (SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp, smb_fname_dst_tmp) + != 0) { + DEBUG(SCANNEDONLY_DEBUG, + ("failed to rename %s into %s\n", cachefile_src, + cachefile_dst)); + } + return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); +} + +static int scannedonly_unlink(vfs_handle_struct * handle, + const struct smb_filename *smb_fname) +{ + /* unlink the 'scanned' file too */ + struct smb_filename *smb_fname_cache = NULL; + char * cachefile; + TALLOC_CTX *ctx = talloc_tos(); + + cachefile = cachefile_name_f_fullpath( + ctx, + smb_fname->base_name, + STRUCTSCANO(handle->data)->p_scanned); + create_synthetic_smb_fname(ctx, cachefile,NULL,NULL, + &smb_fname_cache); + if (SMB_VFS_NEXT_UNLINK(handle, smb_fname_cache) != 0) { + DEBUG(SCANNEDONLY_DEBUG, ("_unlink: failed to unlink %s\n", + smb_fname_cache->base_name)); + } + return SMB_VFS_NEXT_UNLINK(handle, smb_fname); +} + +static int scannedonly_rmdir(vfs_handle_struct * handle, const char *path) +{ + /* if there are only .scanned: .virus: or .failed: files, we delete + those, because the client cannot see them */ + DIR *dirp; + SMB_STRUCT_DIRENT *dire; + TALLOC_CTX *ctx = talloc_tos(); + bool only_deletable_files = true, have_files = false; + char *path_w_slash; + + if (!STRUCTSCANO(handle->data)->rm_hidden_files_on_rmdir) + return SMB_VFS_NEXT_RMDIR(handle, path); + + path_w_slash = name_w_ending_slash(ctx,path); + dirp = SMB_VFS_NEXT_OPENDIR(handle, path, NULL, 0); + while ((dire = SMB_VFS_NEXT_READDIR(handle, dirp, NULL)) != NULL) { + if (ISDOT(dire->d_name) || ISDOTDOT(dire->d_name)) { + continue; + } + have_files = true; + if (!is_scannedonly_file(STRUCTSCANO(handle->data), + dire->d_name)) { + struct smb_filename *smb_fname = NULL; + char *fullpath; + int retval; + + if (STRUCTSCANO(handle->data)->show_special_files) { + only_deletable_files = false; + break; + } + /* stat the file and see if it is a + special file */ + fullpath = path_plus_name(ctx,path_w_slash, + dire->d_name); + create_synthetic_smb_fname(ctx, fullpath,NULL,NULL, + &smb_fname); + retval = SMB_VFS_NEXT_STAT(handle, smb_fname); + if (retval == 0 + && S_ISREG(smb_fname->st.st_ex_mode)) { + only_deletable_files = false; + } + TALLOC_FREE(fullpath); + TALLOC_FREE(smb_fname); + break; + } + } + DEBUG(SCANNEDONLY_DEBUG, + ("path=%s, have_files=%d, only_deletable_files=%d\n", + path, have_files, only_deletable_files)); + if (have_files && only_deletable_files) { + DEBUG(SCANNEDONLY_DEBUG, + ("scannedonly_rmdir, remove leftover scannedonly " + "files from %s\n", path_w_slash)); + SMB_VFS_NEXT_REWINDDIR(handle, dirp); + while ((dire = SMB_VFS_NEXT_READDIR(handle, dirp, NULL)) + != NULL) { + char *fullpath; + struct smb_filename *smb_fname = NULL; + if (ISDOT(dire->d_name) || ISDOTDOT(dire->d_name)) { + continue; + } + fullpath = path_plus_name(ctx,path_w_slash, + dire->d_name); + create_synthetic_smb_fname(ctx, fullpath,NULL,NULL, + &smb_fname); + DEBUG(SCANNEDONLY_DEBUG, ("unlink %s\n", fullpath)); + SMB_VFS_NEXT_UNLINK(handle, smb_fname); + TALLOC_FREE(fullpath); + TALLOC_FREE(smb_fname); + } + } + return SMB_VFS_NEXT_CLOSEDIR(handle, dirp); +} + +static void free_scannedonly_data(void **data) +{ + SAFE_FREE(*data); +} + +static int scannedonly_connect(struct vfs_handle_struct *handle, + const char *service, const char *user) +{ + + struct Tscannedonly *so; + + so = SMB_MALLOC_P(struct Tscannedonly); + handle->data = (void *)so; + handle->free_data = free_scannedonly_data; + so->gsendbuffer[0]='\0'; + so->domain_socket = + lp_parm_bool(SNUM(handle->conn), "scannedonly", + "domain_socket", True); + so->socketname = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", "socketname", + "/var/lib/scannedonly/scan"); + so->portnum = + lp_parm_int(SNUM(handle->conn), "scannedonly", "portnum", + 2020); + so->scanhost = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", "scanhost", + "localhost"); + + so->show_special_files = + lp_parm_bool(SNUM(handle->conn), "scannedonly", + "show_special_files", True); + so->rm_hidden_files_on_rmdir = + lp_parm_bool(SNUM(handle->conn), "scannedonly", + "rm_hidden_files_on_rmdir", True); + so->hide_nonscanned_files = + lp_parm_bool(SNUM(handle->conn), "scannedonly", + "hide_nonscanned_files", False); + so->allow_nonscanned_files = + lp_parm_bool(SNUM(handle->conn), "scannedonly", + "allow_nonscanned_files", False); + so->scanning_message = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", + "scanning_message", + "is being scanned for viruses"); + so->scanning_message_len = strlen(so->scanning_message); + so->recheck_time_open = + lp_parm_int(SNUM(handle->conn), "scannedonly", + "recheck_time_open", 50); + so->recheck_tries_open = + lp_parm_int(SNUM(handle->conn), "scannedonly", + "recheck_tries_open", 100); + so->recheck_size_open = + lp_parm_int(SNUM(handle->conn), "scannedonly", + "recheck_size_open", 100); + so->recheck_time_readdir = + lp_parm_int(SNUM(handle->conn), "scannedonly", + "recheck_time_readdir", 50); + so->recheck_tries_readdir = + lp_parm_int(SNUM(handle->conn), "scannedonly", + "recheck_tries_readdir", 20); + + so->p_scanned = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", + "pref_scanned", + ".scanned:"); + so->p_virus = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", + "pref_virus", + ".virus:"); + so->p_failed = + (char *)lp_parm_const_string(SNUM(handle->conn), + "scannedonly", + "pref_failed", + ".failed:"); + connect_to_scanner(handle); + + return SMB_VFS_NEXT_CONNECT(handle, service, user); +} + +/* VFS operations structure */ +static struct vfs_fn_pointers vfs_scannedonly_fns = { + .opendir = scannedonly_opendir, + .readdir = scannedonly_readdir, + .seekdir = scannedonly_seekdir, + .telldir = scannedonly_telldir, + .rewind_dir = scannedonly_rewinddir, + .closedir = scannedonly_closedir, + .rmdir = scannedonly_rmdir, + .stat = scannedonly_stat, + .lstat = scannedonly_lstat, + .open = scannedonly_open, + .close_fn = scannedonly_close, + .rename = scannedonly_rename, + .unlink = scannedonly_unlink, + .connect_fn = scannedonly_connect +}; + +NTSTATUS vfs_scannedonly_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "scannedonly", + &vfs_scannedonly_fns); +} diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c index 312160c026..a3de30e808 100644 --- a/source3/modules/vfs_zfsacl.c +++ b/source3/modules/vfs_zfsacl.c @@ -106,6 +106,7 @@ static bool zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) ace_t *acebuf; SMB4ACE_T *smbace; TALLOC_CTX *mem_ctx; + bool have_special_id = false; /* allocate the field of ZFS aces */ mem_ctx = talloc_tos(); @@ -140,8 +141,17 @@ static bool zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) aceprop->who.special_id)); continue; /* don't add it !!! */ } + have_special_id = true; } } + + if (!have_special_id + && lp_parm_bool(fsp->conn->params->service, "zfsacl", + "denymissingspecial", false)) { + errno = EACCES; + return false; + } + SMB_ASSERT(i == naces); /* store acl */ diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index a197c51ac8..6149f974ac 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -75,8 +75,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* It's our own domain, lookup the name in passdb */ if (lookup_global_sam_name(name, flags, &rid, &type)) { - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); + sid_compose(&sid, get_global_sam_sid(), rid); goto ok; } TALLOC_FREE(tmp_ctx); @@ -96,8 +95,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, /* Explicit request for a name in BUILTIN */ if (lookup_builtin_name(name, &rid)) { - sid_copy(&sid, &global_sid_Builtin); - sid_append_rid(&sid, rid); + sid_compose(&sid, &global_sid_Builtin, rid); type = SID_NAME_ALIAS; goto ok; } @@ -215,8 +213,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, lookup_builtin_name(name, &rid)) { domain = talloc_strdup(tmp_ctx, builtin_domain_name()); - sid_copy(&sid, &global_sid_Builtin); - sid_append_rid(&sid, rid); + sid_compose(&sid, &global_sid_Builtin, rid); type = SID_NAME_ALIAS; goto ok; } @@ -230,8 +227,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx, lookup_global_sam_name(name, flags, &rid, &type)) { domain = talloc_strdup(tmp_ctx, get_global_sam_name()); - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); + sid_compose(&sid, get_global_sam_sid(), rid); goto ok; } @@ -544,8 +540,7 @@ static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, if (sid_check_is_wellknown_domain(domain_sid, NULL)) { for (i=0; i<num_rids; i++) { DOM_SID sid; - sid_copy(&sid, domain_sid); - sid_append_rid(&sid, rids[i]); + sid_compose(&sid, domain_sid, rids[i]); if (lookup_wellknown_sid(mem_ctx, &sid, domain_name, &(*names)[i])) { if ((*names)[i] == NULL) { @@ -1192,9 +1187,8 @@ static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid) static bool legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid) { enum lsa_SidType type; - uint32 rid; - if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) { + if (sid_check_is_in_our_domain(psid)) { union unid_t id; bool ret; @@ -1235,7 +1229,6 @@ done: static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid) { - uint32 rid; GROUP_MAP map; union unid_t id; enum lsa_SidType type; @@ -1257,7 +1250,7 @@ static bool legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid) return false; } - if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) { + if (sid_check_is_in_our_domain(psid)) { bool ret; become_root(); diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index b2c3b948f1..3ced150803 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -216,8 +216,7 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p return NT_STATUS_ACCESS_DENIED; } - sid_copy( &user_sid, get_global_sam_sid() ); - sid_append_rid( &user_sid, user_rid ); + sid_compose(&user_sid, get_global_sam_sid(), user_rid); if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) { DEBUG(3, ("pdb_set_user_sid failed\n")); diff --git a/source3/passdb/pdb_compat.c b/source3/passdb/pdb_compat.c index 9967eb53ad..b65be70758 100644 --- a/source3/passdb/pdb_compat.c +++ b/source3/passdb/pdb_compat.c @@ -60,10 +60,9 @@ bool pdb_set_user_sid_from_rid (struct samu *sampass, uint32 rid, enum pdb_value return False; } - sid_copy(&u_sid, global_sam_sid); - - if (!sid_append_rid(&u_sid, rid)) + if (!sid_compose(&u_sid, global_sam_sid, rid)) { return False; + } if (!pdb_set_user_sid(sampass, &u_sid, flag)) return False; @@ -87,10 +86,9 @@ bool pdb_set_group_sid_from_rid (struct samu *sampass, uint32 grid, enum pdb_val return False; } - sid_copy(&g_sid, global_sam_sid); - - if (!sid_append_rid(&g_sid, grid)) + if (!sid_compose(&g_sid, global_sam_sid, grid)) { return False; + } if (!pdb_set_group_sid(sampass, &g_sid, flag)) return False; diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 30775e49fe..d7fc02f807 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -239,8 +239,7 @@ const DOM_SID *pdb_get_group_sid(struct samu *sampass) /* Just set it to the 'Domain Users' RID of 512 which will always resolve to a name */ - sid_copy( gsid, get_global_sam_sid() ); - sid_append_rid( gsid, DOMAIN_GROUP_RID_USERS ); + sid_compose(gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS); sampass->group_sid = gsid; @@ -552,8 +551,8 @@ bool pdb_set_group_sid(struct samu *sampass, const DOM_SID *g_sid, enum pdb_valu if ( sid_to_gid( g_sid, &gid ) ) { sid_copy(sampass->group_sid, g_sid); } else { - sid_copy( sampass->group_sid, get_global_sam_sid() ); - sid_append_rid( sampass->group_sid, DOMAIN_GROUP_RID_USERS ); + sid_compose(sampass->group_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_USERS); } DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", @@ -876,6 +875,7 @@ bool pdb_set_lanman_passwd(struct samu *sampass, const uint8 pwd[LM_HASH_LEN], e bool pdb_set_pw_history(struct samu *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag) { if (historyLen && pwd){ + data_blob_free(&(sampass->nt_pw_his)); sampass->nt_pw_his = data_blob_talloc(sampass, pwd, historyLen*PW_HISTORY_ENTRY_LEN); if (!sampass->nt_pw_his.length) { @@ -980,6 +980,9 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) { uchar new_lanman_p16[LM_HASH_LEN]; uchar new_nt_p16[NT_HASH_LEN]; + uchar *pwhistory; + uint32 pwHistLen; + uint32 current_history_len; if (!plaintext) return False; @@ -1009,68 +1012,80 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) return False; - /* Store the password history. */ - if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { - uchar *pwhistory; - uint32 pwHistLen; - pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); - if (pwHistLen != 0){ - uint32 current_history_len; - /* We need to make sure we don't have a race condition here - the - account policy history length can change between when the pw_history - was first loaded into the struct samu struct and now.... JRA. */ - pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); - - if (current_history_len != pwHistLen) { - /* After closing and reopening struct samu the history - values will sync up. We can't do this here. */ - - /* current_history_len > pwHistLen is not a problem - we - have more history than we need. */ - - if (current_history_len < pwHistLen) { - /* Ensure we have space for the needed history. */ - uchar *new_history = (uchar *)TALLOC(sampass, - pwHistLen*PW_HISTORY_ENTRY_LEN); - if (!new_history) { - return False; - } - - /* And copy it into the new buffer. */ - if (current_history_len) { - memcpy(new_history, pwhistory, - current_history_len*PW_HISTORY_ENTRY_LEN); - } - /* Clearing out any extra space. */ - memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN], - '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN); - /* Finally replace it. */ - pwhistory = new_history; - } - } - if (pwhistory && pwHistLen){ - /* Make room for the new password in the history list. */ - if (pwHistLen > 1) { - memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], - pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN ); - } - /* Create the new salt as the first part of the history entry. */ - generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN); - - /* Generate the md5 hash of the salt+new password as the second - part of the history entry. */ - - E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]); - pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); - } else { - DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n")); - } - } else { - /* Set the history length to zero. */ - pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) { + /* + * No password history for non-user accounts + */ + return true; + } + + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); + + if (pwHistLen == 0) { + /* Set the history length to zero. */ + pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + return true; + } + + /* + * We need to make sure we don't have a race condition here - + * the account policy history length can change between when + * the pw_history was first loaded into the struct samu struct + * and now.... JRA. + */ + pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); + + if ((current_history_len != 0) && (pwhistory == NULL)) { + DEBUG(1, ("pdb_set_plaintext_passwd: pwhistory == NULL!\n")); + return false; + } + + if (current_history_len < pwHistLen) { + /* + * Ensure we have space for the needed history. This + * also takes care of an account which did not have + * any history at all so far, i.e. pwhistory==NULL + */ + uchar *new_history = talloc_zero_array( + sampass, uchar, + pwHistLen*PW_HISTORY_ENTRY_LEN); + + if (!new_history) { + return False; } + + memcpy(new_history, pwhistory, + current_history_len*PW_HISTORY_ENTRY_LEN); + + pwhistory = new_history; } + /* + * Make room for the new password in the history list. + */ + if (pwHistLen > 1) { + memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory, + (pwHistLen-1)*PW_HISTORY_ENTRY_LEN ); + } + + /* + * Fill the salt area with 0-s: this indicates that + * a plain nt hash is stored in the has area. + * The old format was to store a 16 byte salt and + * then an md5hash of the nt_hash concatenated with + * the salt. + */ + memset(pwhistory, 0, PW_HISTORY_SALT_LEN); + + /* + * Store the plain nt hash in the second 16 bytes. + * The old format was to store the md5 hash of + * the salt+newpw. + */ + memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt_p16, SALTED_MD5_HASH_LEN); + + pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); + return True; } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index de46254dde..bd85ded138 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -1472,8 +1472,7 @@ static bool lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n", (unsigned int)rid)); - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); + sid_compose(&sid, get_global_sam_sid(), rid); /* see if the passdb can help us with the name of the user */ diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 90ac8e5ffa..30b27d4596 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -915,9 +915,9 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN); - if ((pwhist = TALLOC_ARRAY(ctx, uint8, - pwHistLen * PW_HISTORY_ENTRY_LEN)) == - NULL){ + pwhist = TALLOC_ARRAY(ctx, uint8, + pwHistLen * PW_HISTORY_ENTRY_LEN); + if (pwhist == NULL) { DEBUG(0, ("init_sam_from_ldap: talloc failed!\n")); goto fn_exit; } @@ -6394,9 +6394,8 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location) trim_char( uri, '\"', '\"' ); nt_status = pdb_init_ldapsam_common(pdb_method, uri); - if (uri) { - TALLOC_FREE(uri); - } + + TALLOC_FREE(uri); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; diff --git a/source3/passdb/util_unixsids.c b/source3/passdb/util_unixsids.c index ad51253058..afda253c70 100644 --- a/source3/passdb/util_unixsids.c +++ b/source3/passdb/util_unixsids.c @@ -37,14 +37,12 @@ bool sid_check_is_in_unix_users(const DOM_SID *sid) bool uid_to_unix_users_sid(uid_t uid, DOM_SID *sid) { - sid_copy(sid, &global_sid_Unix_Users); - return sid_append_rid(sid, (uint32_t)uid); + return sid_compose(sid, &global_sid_Unix_Users, uid); } bool gid_to_unix_groups_sid(gid_t gid, DOM_SID *sid) { - sid_copy(sid, &global_sid_Unix_Groups); - return sid_append_rid(sid, (uint32_t)gid); + return sid_compose(sid, &global_sid_Unix_Groups, gid); } const char *unix_users_domain_name(void) @@ -55,17 +53,20 @@ const char *unix_users_domain_name(void) bool lookup_unix_user_name(const char *name, DOM_SID *sid) { struct passwd *pwd; + bool ret; pwd = getpwnam_alloc(talloc_autofree_context(), name); if (pwd == NULL) { return False; } - sid_copy(sid, &global_sid_Unix_Users); - sid_append_rid(sid, (uint32_t)pwd->pw_uid); /* For 64-bit uid's we have enough - * space ... */ + /* + * For 64-bit uid's we have enough space in the whole SID, + * should they become necessary + */ + ret = sid_compose(sid, &global_sid_Unix_Users, pwd->pw_uid); TALLOC_FREE(pwd); - return True; + return ret; } bool sid_check_is_unix_groups(const DOM_SID *sid) @@ -98,8 +99,9 @@ bool lookup_unix_group_name(const char *name, DOM_SID *sid) return False; } - sid_copy(sid, &global_sid_Unix_Groups); - sid_append_rid(sid, (uint32_t)grp->gr_gid); /* For 64-bit uid's we have enough - * space ... */ - return True; + /* + * For 64-bit gid's we have enough space in the whole SID, + * should they become necessary + */ + return sid_compose(sid, &global_sid_Unix_Groups, grp->gr_gid); } diff --git a/source3/passdb/util_wellknown.c b/source3/passdb/util_wellknown.c index 2af68b7e7c..0c45faab46 100644 --- a/source3/passdb/util_wellknown.c +++ b/source3/passdb/util_wellknown.c @@ -160,8 +160,8 @@ bool lookup_wellknown_name(TALLOC_CTX *mem_ctx, const char *name, for (j=0; users[j].name != NULL; j++) { if ( strequal(users[j].name, name) ) { - sid_copy(sid, special_domains[i].sid); - sid_append_rid(sid, users[j].rid); + sid_compose(sid, special_domains[i].sid, + users[j].rid); *domain = talloc_strdup( mem_ctx, special_domains[i].name); return True; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 1f306512af..7aef424961 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -5398,8 +5398,8 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) if ( IS_DC ) { DOM_SID domadmins_sid; - sid_copy(&domadmins_sid, get_global_sam_sid()); - sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS); + sid_compose(&domadmins_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_ADMINS); sa = PRINTER_ACE_FULL_CONTROL; init_sec_ace(&ace[i++], &domadmins_sid, diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 03884479f9..e484209cbe 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -154,10 +154,8 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, uint8_t authoritative; int validation_level = 3; fstring clnt_name_slash; - uint8 zeros[16]; ZERO_STRUCT(ret_creds); - ZERO_STRUCT(zeros); logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel); if (!logon) { @@ -302,7 +300,6 @@ 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; - uint8 zeros[16]; struct netr_Authenticator clnt_creds; struct netr_Authenticator ret_creds; union netr_LogonLevel *logon = NULL; @@ -314,7 +311,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, *info3 = NULL; - ZERO_STRUCT(zeros); ZERO_STRUCT(ret_creds); ZERO_STRUCT(lm); @@ -414,7 +410,6 @@ 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; - uint8 zeros[16]; union netr_LogonLevel *logon = NULL; struct netr_NetworkInfo *network_info; uint8_t authoritative; @@ -425,8 +420,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, *info3 = NULL; - ZERO_STRUCT(zeros); - ZERO_STRUCT(lm); ZERO_STRUCT(nt); diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index e903f0e974..857040ec8b 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -335,8 +335,7 @@ static NTSTATUS make_lsa_object_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); /* Add Full Access for Domain Admins */ - sid_copy(&adm_sid, get_global_sam_sid()); - sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS); + sid_compose(&adm_sid, get_global_sam_sid(), DOMAIN_GROUP_RID_ADMINS); init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 8f4381cde1..66f3bd3130 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -1057,8 +1057,8 @@ static NTSTATUS _netr_LogonSamLogon_base(pipes_struct *p, NTSTATUS status = NT_STATUS_OK; union netr_LogonLevel *logon = r->in.logon; const char *nt_username, *nt_domain, *nt_workstation; - auth_usersupplied_info *user_info = NULL; - auth_serversupplied_info *server_info = NULL; + struct auth_usersupplied_info *user_info = NULL; + struct auth_serversupplied_info *server_info = NULL; struct auth_context *auth_context = NULL; uint8_t pipe_session_key[16]; bool process_creds = true; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 6b40385744..3626cbdf2a 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -145,8 +145,8 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd /* Add Full Access for Domain Admins if we are a DC */ if ( IS_DC ) { - sid_copy( &domadmin_sid, get_global_sam_sid() ); - sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); + sid_compose(&domadmin_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_ADMINS); init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); } @@ -266,8 +266,8 @@ void map_max_allowed_access(const NT_USER_TOKEN *nt_token, /* Full access for DOMAIN\Domain Admins. */ if ( IS_DC ) { DOM_SID domadmin_sid; - sid_copy( &domadmin_sid, get_global_sam_sid() ); - sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); + sid_compose(&domadmin_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_ADMINS); if (is_sid_in_token(nt_token, &domadmin_sid)) { *pacc_requested |= GENERIC_ALL_ACCESS; return; @@ -5837,8 +5837,9 @@ NTSTATUS _samr_CreateDomainGroup(pipes_struct *p, return status; } - if (!sid_equal(&dinfo->sid, get_global_sam_sid())) + if (!sid_check_is_domain(&dinfo->sid)) { return NT_STATUS_ACCESS_DENIED; + } name = r->in.name->string; if (name == NULL) { @@ -5898,8 +5899,9 @@ NTSTATUS _samr_CreateDomAlias(pipes_struct *p, return result; } - if (!sid_equal(&dinfo->sid, get_global_sam_sid())) + if (!sid_check_is_domain(&dinfo->sid)) { return NT_STATUS_ACCESS_DENIED; + } name = r->in.alias_name->string; @@ -6277,8 +6279,9 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, /* this should not be hard-coded like this */ - if (!sid_equal(&dinfo->sid, get_global_sam_sid())) + if (!sid_check_is_domain(&dinfo->sid)) { return NT_STATUS_ACCESS_DENIED; + } sid_compose(&info_sid, &dinfo->sid, r->in.rid); diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index d35557e5bd..a2d1d0716d 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -1033,6 +1033,13 @@ WERROR _srvsvc_NetFileEnum(pipes_struct *p, return WERR_UNKNOWN_LEVEL; } + if (!nt_token_check_sid(&global_sid_Builtin_Administrators, + p->server_info->ptok)) { + DEBUG(1, ("Enumerating files only allowed for " + "administrators\n")); + return WERR_ACCESS_DENIED; + } + ctx = talloc_tos(); ctr3 = r->in.info_ctr->ctr.ctr3; if (!ctr3) { @@ -1185,6 +1192,13 @@ WERROR _srvsvc_NetConnEnum(pipes_struct *p, DEBUG(5,("_srvsvc_NetConnEnum: %d\n", __LINE__)); + if (!nt_token_check_sid(&global_sid_Builtin_Administrators, + p->server_info->ptok)) { + DEBUG(1, ("Enumerating connections only allowed for " + "administrators\n")); + return WERR_ACCESS_DENIED; + } + switch (r->in.info_ctr->level) { case 0: werr = init_srv_conn_info_0(r->in.info_ctr->ctr.ctr0, @@ -1216,6 +1230,13 @@ WERROR _srvsvc_NetSessEnum(pipes_struct *p, DEBUG(5,("_srvsvc_NetSessEnum: %d\n", __LINE__)); + if (!nt_token_check_sid(&global_sid_Builtin_Administrators, + p->server_info->ptok)) { + DEBUG(1, ("Enumerating sessions only allowed for " + "administrators\n")); + return WERR_ACCESS_DENIED; + } + switch (r->in.info_ctr->level) { case 0: werr = init_srv_sess_info_0(p, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 2da36b2fe6..dcefc82bba 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1008,6 +1008,59 @@ static NTSTATUS check_oem_password(const char *user, return NT_STATUS_WRONG_PASSWORD; } +bool password_in_history(uint8_t nt_pw[NT_HASH_LEN], + uint32_t pw_history_len, + const uint8_t *pw_history) +{ + static const uint8_t zero_md5_nt_pw[SALTED_MD5_HASH_LEN] = { 0, }; + int i; + + dump_data(100, nt_pw, NT_HASH_LEN); + dump_data(100, pw_history, PW_HISTORY_ENTRY_LEN * pw_history_len); + + for (i=0; i<pw_history_len; i++) { + uint8_t new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN]; + const uint8_t *current_salt; + const uint8_t *old_nt_pw_salted_md5_hash; + + current_salt = &pw_history[i*PW_HISTORY_ENTRY_LEN]; + old_nt_pw_salted_md5_hash = current_salt + PW_HISTORY_SALT_LEN; + + if (memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, + SALTED_MD5_HASH_LEN) == 0) { + /* Ignore zero valued entries. */ + continue; + } + + if (memcmp(zero_md5_nt_pw, current_salt, + PW_HISTORY_SALT_LEN) == 0) + { + /* + * New format: zero salt and then plain nt hash. + * Directly compare the hashes. + */ + if (memcmp(nt_pw, old_nt_pw_salted_md5_hash, + SALTED_MD5_HASH_LEN) == 0) + { + return true; + } + } else { + /* + * Old format: md5sum of salted nt hash. + * Create salted version of new pw to compare. + */ + E_md5hash(current_salt, nt_pw, new_nt_pw_salted_md5_hash); + + if (memcmp(new_nt_pw_salted_md5_hash, + old_nt_pw_salted_md5_hash, + SALTED_MD5_HASH_LEN) == 0) { + return true; + } + } + } + return false; +} + /*********************************************************** This routine takes the given password and checks it against the password history. Returns True if this password has been @@ -1017,11 +1070,8 @@ static NTSTATUS check_oem_password(const char *user, static bool check_passwd_history(struct samu *sampass, const char *plaintext) { uchar new_nt_p16[NT_HASH_LEN]; - uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN]; const uint8 *nt_pw; const uint8 *pwhistory; - bool found = False; - int i; uint32 pwHisLen, curr_pwHisLen; pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHisLen); @@ -1048,30 +1098,13 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext) return True; } - dump_data(100, new_nt_p16, NT_HASH_LEN); - dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); - - memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN); - for (i=0; i<pwHisLen; i++) { - uchar new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN]; - const uchar *current_salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; - const uchar *old_nt_pw_salted_md5_hash = &pwhistory[(i*PW_HISTORY_ENTRY_LEN)+ - PW_HISTORY_SALT_LEN]; - if (!memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) { - /* Ignore zero valued entries. */ - continue; - } - /* Create salted versions of new to compare. */ - E_md5hash(current_salt, new_nt_p16, new_nt_pw_salted_md5_hash); - - if (!memcmp(new_nt_pw_salted_md5_hash, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) { - DEBUG(1,("check_passwd_history: proposed new password for user %s found in history list !\n", - pdb_get_username(sampass) )); - found = True; - break; - } + if (password_in_history(new_nt_p16, pwHisLen, pwhistory)) { + DEBUG(1,("check_passwd_history: proposed new password for " + "user %s found in history list !\n", + pdb_get_username(sampass) )); + return true; } - return found; + return false; } /*********************************************************** @@ -1156,7 +1189,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw } } - /* removed calculation here, becuase passdb now calculates + /* removed calculation here, because passdb now calculates based on policy. jmcd */ if ((can_change_time != 0) && (time(NULL) < can_change_time)) { DEBUG(1, ("user %s cannot change password now, must " diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 05c3c709a1..ca1ac47fa0 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -336,6 +336,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, become_user(conn, fsp->vuid); became_user = True; } + fsp->delete_on_close = true; set_delete_on_close_lck(lck, True, ¤t_user.ut); if (became_user) { unbecome_user(); @@ -481,6 +482,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, * the delete on close flag. JRA. */ + fsp->delete_on_close = false; set_delete_on_close_lck(lck, False, NULL); done: @@ -924,6 +926,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, struct share_mode_lock *lck = NULL; bool delete_dir = False; NTSTATUS status = NT_STATUS_OK; + NTSTATUS status1 = NT_STATUS_OK; /* * NT can set delete_on_close of the last open @@ -958,6 +961,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, } send_stat_cache_delete_message(fsp->fsp_name->base_name); set_delete_on_close_lck(lck, True, ¤t_user.ut); + fsp->delete_on_close = true; if (became_user) { unbecome_user(); } @@ -1022,9 +1026,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, fsp, NT_STATUS_OK); } - status = fd_close(fsp); + status1 = fd_close(fsp); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status1)) { DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n", fsp_str_dbg(fsp), fsp->fh->fd, errno, strerror(errno))); @@ -1042,6 +1046,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, out: TALLOC_FREE(lck); + if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) { + status = status1; + } return status; } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 5ce4a7b099..3fe3218762 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1227,14 +1227,6 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, goto out; } - /* If it's a dfs symlink, ignore _hide xxxx_ options */ - if (lp_host_msdfs() && - lp_msdfs_root(SNUM(conn)) && - is_msdfs_link(conn, entry, NULL)) { - ret = true; - goto out; - } - /* Create an smb_filename with stream_name == NULL. */ status = create_synthetic_smb_fname(talloc_tos(), entry, NULL, pst, &smb_fname_base); diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 7d0a552956..631efce677 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -54,6 +54,17 @@ bool can_access_file_acl(struct connection_struct *conn, status = se_access_check(secdesc, conn->server_info->ptok, access_mask, &access_granted); ret = NT_STATUS_IS_OK(status); + + if (DEBUGLEVEL >= 10) { + DEBUG(10,("can_access_file_acl for file %s " + "access_mask 0x%x, access_granted 0x%x " + "access %s\n", + smb_fname_str_dbg(smb_fname), + (unsigned int)access_mask, + (unsigned int)access_granted, + ret ? "ALLOWED" : "DENIED" )); + NDR_PRINT_DEBUG(security_descriptor, secdesc); + } out: TALLOC_FREE(secdesc); return ret; diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 68fa795ba2..e6db5ec414 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -122,7 +122,6 @@ int conn_ctx_stack_ndx = 0; struct vfs_init_function_entry *backends = NULL; char *sparse_buf = NULL; -char *LastDir = NULL; /* Current number of oplocks we have outstanding. */ int32_t exclusive_oplocks_open = 0; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 0db61f87a3..3cc967f4fd 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -131,7 +131,6 @@ extern int conn_ctx_stack_ndx; struct vfs_init_function_entry; extern struct vfs_init_function_entry *backends; extern char *sparse_buf; -extern char *LastDir; /* Current number of oplocks we have outstanding. */ extern int32_t exclusive_oplocks_open; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 7ee6c9b59c..27115021bf 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1569,7 +1569,9 @@ static bool check_share_info(int uLevel, char* id) } break; case 1: - if (strcmp(id,"B13BWz") != 0) { + /* Level-2 descriptor is allowed (and ignored) */ + if (strcmp(id,"B13BWz") != 0 && + strcmp(id,"B13BWzWWWzB9B") != 0) { return False; } break; @@ -2616,7 +2618,7 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, */ { - auth_serversupplied_info *server_info = NULL; + struct auth_serversupplied_info *server_info = NULL; DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 755ff5d6cd..2e63f7a395 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -248,7 +248,7 @@ static int register_homes_share(const char *username) int register_existing_vuid(struct smbd_server_connection *sconn, uint16 vuid, - auth_serversupplied_info *server_info, + struct auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 828053811b..7342420a89 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1109,6 +1109,10 @@ uint32_t map_canon_ace_perms(int snum, } } + if ((perms & S_IWUSR) && lp_dos_filemode(snum)) { + nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|DELETE_ACCESS); + } + DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n", (unsigned int)perms, (unsigned int)nt_mask )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b2d98bfbc0..b6316aac46 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5368,8 +5368,12 @@ void reply_rmdir(struct smb_request *req) goto out; } - close_file(req, fsp, NORMAL_CLOSE); - reply_outbuf(req, 0, 0); + status = close_file(req, fsp, NORMAL_CLOSE); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + } else { + reply_outbuf(req, 0, 0); + } dptr_closepath(sconn, smb_dname->base_name, req->smbpid); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 612cf2231a..ae99127db2 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -41,7 +41,7 @@ struct pending_auth_data { is set approriately */ static NTSTATUS do_map_to_guest(NTSTATUS status, - auth_serversupplied_info **server_info, + struct auth_serversupplied_info **server_info, const char *user, const char *domain) { if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { @@ -128,10 +128,10 @@ static void reply_sesssetup_blob(struct smb_request *req, Do a 'guest' logon, getting back the ****************************************************************************/ -static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) +static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info) { struct auth_context *auth_context; - auth_usersupplied_info *user_info = NULL; + struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; unsigned char chal[8]; @@ -244,7 +244,7 @@ static void reply_spnego_kerberos(struct smb_request *req, NTSTATUS ret = NT_STATUS_OK; struct PAC_DATA *pac_data = NULL; DATA_BLOB ap_rep, ap_rep_wrapped, response; - auth_serversupplied_info *server_info = NULL; + struct auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob_null; uint8 tok_id[2]; DATA_BLOB nullblob = data_blob_null; @@ -1388,8 +1388,8 @@ void reply_sesssetup_and_X(struct smb_request *req) const char *native_os; const char *native_lanman; const char *primary_domain; - auth_usersupplied_info *user_info = NULL; - auth_serversupplied_info *server_info = NULL; + struct auth_usersupplied_info *user_info = NULL; + struct auth_serversupplied_info *server_info = NULL; uint16 smb_flag2 = req->flags2; NTSTATUS nt_status; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2ce61eed30..5acec70f54 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -706,26 +706,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p, int vfs_ChDir(connection_struct *conn, const char *path) { - int res; - - if (!LastDir) { - LastDir = SMB_STRDUP(""); - } - - if (strcsequal(path,".")) - return(0); - - if (*path == '/' && strcsequal(LastDir,path)) - return(0); - - DEBUG(4,("vfs_ChDir to %s\n",path)); - - res = SMB_VFS_CHDIR(conn,path); - if (!res) { - SAFE_FREE(LastDir); - LastDir = SMB_STRDUP(path); - } - return(res); + return SMB_VFS_CHDIR(conn,path); } /******************************************************************* diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index 7180a953bb..e82c7b14f2 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -299,8 +299,7 @@ static int net_groupmap_add(struct net_context *c, int argc, const char **argv) /* append the rid to our own domain/machine SID if we don't have a full SID */ if ( !string_sid[0] ) { - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); + sid_compose(&sid, get_global_sam_sid(), rid); sid_to_fstring(string_sid, &sid); } @@ -610,8 +609,7 @@ static int net_groupmap_set(struct net_context *c, int argc, const char **argv) } } - sid_copy(&map.sid, get_global_sam_sid()); - sid_append_rid(&map.sid, c->opt_rid); + sid_compose(&map.sid, get_global_sam_sid(), c->opt_rid); map.sid_name_use = SID_NAME_DOM_GRP; fstrcpy(map.nt_name, ntgroup); @@ -795,8 +793,7 @@ static bool print_alias_memberships(TALLOC_CTX *mem_ctx, for (i = 0; i < num_alias_rids; i++) { DOM_SID alias; - sid_copy(&alias, domain_sid); - sid_append_rid(&alias, alias_rids[i]); + sid_compose(&alias, domain_sid, alias_rids[i]); printf("%s\n", sid_string_tos(&alias)); } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 7dc8c1dd2c..762af716f5 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -3889,8 +3889,8 @@ static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd, sid_array.sids[j].sid); } - sid_copy(&alias.sid, domain_sid); - sid_append_rid(&alias.sid, groups->entries[i].idx); + sid_compose(&alias.sid, domain_sid, + groups->entries[i].idx); push_alias(mem_ctx, &alias); } @@ -5450,8 +5450,7 @@ static NTSTATUS rpc_trustdom_del_internals(struct net_context *c, } /* append the rid to the domain sid */ - sid_copy(&trust_acct_sid, domain_sid); - if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) { + if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) { goto done; } diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 57e4251543..e018c28c30 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -223,7 +223,7 @@ DATA_BLOB get_challenge(void) static DATA_BLOB chal; if (opt_challenge.length) return opt_challenge; - + chal = data_blob(NULL, 8); generate_random_buffer(chal.data, chal.length); @@ -242,7 +242,7 @@ static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain, if (!p) { return False; } - + fstrcpy(user, p+1); fstrcpy(domain, domuser); domain[PTR_DIFF(p, domuser)] = 0; @@ -300,23 +300,23 @@ int get_pam_winbind_config() { int ctrl = 0; dictionary *d = NULL; - + if (!opt_pam_winbind_conf || !*opt_pam_winbind_conf) { opt_pam_winbind_conf = PAM_WINBIND_CONFIG_FILE; } d = iniparser_load(CONST_DISCARD(char *, opt_pam_winbind_conf)); - + if (!d) { return 0; } - + if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:krb5_auth"), false)) { ctrl |= WINBIND_KRB5_AUTH; } iniparser_freedict(d); - + return ctrl; } @@ -438,7 +438,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username, } request.data.auth_crap.nt_resp_len = nt_response->length; } - + result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); SAFE_FREE(request.extra_data.data); @@ -451,7 +451,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username, winbindd_free_response(&response); return nt_status; } - + nt_status = (NT_STATUS(response.data.auth.nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { if (error_string) @@ -533,7 +533,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, old_lm_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_lm_hash_enc)); request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = old_lm_hash_enc.length; } - + result = winbindd_request_response(WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, &request, &response); /* Display response */ @@ -546,7 +546,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, winbindd_free_response(&response); return nt_status; } - + nt_status = (NT_STATUS(response.data.auth.nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { @@ -557,7 +557,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, } winbindd_free_response(&response); - + return nt_status; } @@ -585,7 +585,7 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB memcpy(lm_session_key->data, lm_key, 8); memset(lm_session_key->data+8, '\0', 8); } - + if (memcmp(user_sess_key, zeros, 16) != 0) { *user_session_key = data_blob_talloc(ntlmssp_state, user_sess_key, 16); } @@ -611,7 +611,7 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *u struct samr_Password lm_pw, nt_pw; nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash); - + nt_status = ntlm_password_check(ntlmssp_state, true, true, 0, &ntlmssp_state->chal, @@ -621,7 +621,7 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *u ntlmssp_state->user, ntlmssp_state->domain, &lm_pw, &nt_pw, user_session_key, lm_session_key); - + if (NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state, "%s%c%s", ntlmssp_state->domain, @@ -674,7 +674,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntl if (opt_password) { status = ntlmssp_set_password(*client_ntlmssp_state, opt_password); - + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set password: %s\n", nt_errstr(status))); @@ -689,7 +689,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntl static NTSTATUS ntlm_auth_start_ntlmssp_server(struct ntlmssp_state **ntlmssp_state) { NTSTATUS status = ntlmssp_server_start(ntlmssp_state); - + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not start NTLMSSP server: %s\n", nt_errstr(status))); @@ -1091,7 +1091,7 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state, { char *user, *pass; user=buf; - + pass=(char *)memchr(buf,' ',length); if (!pass) { DEBUG(2, ("Password not found. Denying access\n")); @@ -1100,12 +1100,12 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state, } *pass='\0'; pass++; - + if (state->helper_mode == SQUID_2_5_BASIC) { rfc1738_unescape(user); rfc1738_unescape(pass); } - + if (check_plaintext_auth(user, pass, False)) { x_fprintf(x_stdout, "OK\n"); } else { @@ -1513,7 +1513,7 @@ static void manage_client_ntlmssp_targ(struct spnego_data spnego) status = ntlmssp_update(client_ntlmssp_state, spnego.negTokenTarg.responseToken, &request); - + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from " "ntlmssp_client_update, got: %s\n", @@ -1530,7 +1530,7 @@ static void manage_client_ntlmssp_targ(struct spnego_data spnego) spnego.negTokenTarg.supportedMech = (char *)OID_NTLMSSP; spnego.negTokenTarg.responseToken = request; spnego.negTokenTarg.mechListMIC = null_blob; - + spnego_write_data(ctx, &to_server, &spnego); data_blob_free(&request); @@ -1684,7 +1684,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, /* We asked for a password and obviously got it :-) */ opt_password = SMB_STRNDUP((const char *)request.data, request.length); - + if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); x_fprintf(x_stdout, "BH Out of memory\n"); @@ -1812,7 +1812,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, static char *plaintext_password; static bool ntlm_server_1_user_session_key; static bool ntlm_server_1_lm_session_key; - + if (strequal(buf, ".")) { if (!full_username && !username) { x_fprintf(x_stdout, "Error: No username supplied!\n"); @@ -1842,7 +1842,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, if (full_username && !username) { fstring fstr_user; fstring fstr_domain; - + if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) { /* username might be 'tainted', don't print into our new-line deleimianted stream */ x_fprintf(x_stdout, "Error: Could not parse into domain and username\n"); @@ -1859,7 +1859,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, if (ntlm_server_1_lm_session_key) flags |= WBFLAG_PAM_LMKEY; - + if (ntlm_server_1_user_session_key) flags |= WBFLAG_PAM_USER_SESSION_KEY; @@ -1928,13 +1928,13 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, parameter = strstr_m(request, ":: "); if (!parameter) { parameter = strstr_m(request, ": "); - + if (!parameter) { DEBUG(0, ("Parameter not found!\n")); x_fprintf(x_stdout, "Error: Parameter not found!\n.\n"); return; } - + parameter[0] ='\0'; parameter++; parameter[0] ='\0'; @@ -2015,7 +2015,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, new_nt_pswd = data_blob(NULL, 516); old_nt_hash_enc = data_blob(NULL, 16); - + /* Calculate the MD4 hash (NT compatible) of the * password */ E_md4hash(oldpswd, old_nt_hash); @@ -2023,7 +2023,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, /* E_deshash returns false for 'long' passwords (> 14 DOS chars). - + Therefore, don't send a buffer encrypted with the truncated hash (it could allow an even easier @@ -2052,12 +2052,12 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, encode_pw_buffer(new_nt_pswd.data, newpswd, STR_UNICODE); - + arcfour_crypt(new_nt_pswd.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.data); } - + if (!full_username && !username) { x_fprintf(x_stdout, "Error: No username supplied!\n"); } else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) && @@ -2066,11 +2066,11 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, "blobs supplied!\n"); } else { char *error_string = NULL; - + if (full_username && !username) { fstring fstr_user; fstring fstr_domain; - + if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) { @@ -2088,7 +2088,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, username = smb_xstrdup(fstr_user); domain = smb_xstrdup(fstr_domain); } - + } if(!NT_STATUS_IS_OK(contact_winbind_change_pswd_auth_crap( @@ -2128,13 +2128,13 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, parameter = strstr_m(request, ":: "); if (!parameter) { parameter = strstr_m(request, ": "); - + if (!parameter) { DEBUG(0, ("Parameter not found!\n")); x_fprintf(x_stdout, "Error: Parameter not found!\n.\n"); return; } - + parameter[0] ='\0'; parameter++; parameter[0] ='\0'; diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 06eedef920..ac41dc0ad0 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -68,8 +68,7 @@ static int get_sid_from_cli_string(DOM_SID *sid, const char *str_sid) "a complete SID or RID!\n"); return -1; } - sid_copy(sid, get_global_sam_sid()); - sid_append_rid(sid, rid); + sid_compose(sid, get_global_sam_sid(), rid); } return 0; diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 7d4dd2b5ab..1227b2a052 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -193,8 +193,7 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, if (!hashed_domains[h_domain].sid) continue; - sid_copy(ids[i]->sid, hashed_domains[h_domain].sid); - sid_append_rid(ids[i]->sid, h_rid); + sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid); ids[i]->status = ID_MAPPED; } diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 189b088809..8bfe751a8b 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -97,8 +97,7 @@ static int convert_fn(struct db_record *rec, void *private_data) rid = atoi(p); - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); + sid_compose(&sid, &domain->sid, rid); sid_to_fstring(keystr, &sid); key2 = string_term_tdb_data(keystr); diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index d15fb86d86..f647a3ffaf 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -880,8 +880,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, goto done; } - sid_copy(&primary_group, &domain->sid); - sid_append_rid(&primary_group, primary_group_rid); + sid_compose(&primary_group, &domain->sid, primary_group_rid); count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 68972dd18d..b7b5e6d7ed 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2986,8 +2986,7 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain, return; } - sid_copy(&sid, info3->base.domain_sid); - sid_append_rid(&sid, info3->base.rid); + sid_compose(&sid, info3->base.domain_sid, info3->base.rid); /* Clear U/SID cache entry */ fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid)); diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c index 921110a0be..2f71aaae52 100644 --- a/source3/winbindd/winbindd_ccache_access.c +++ b/source3/winbindd/winbindd_ccache_access.c @@ -116,7 +116,7 @@ static NTSTATUS do_ntlm_auth_with_hashes(const char *username, data_blob_free(&reply); goto done; } - *auth_msg = reply; + *auth_msg = data_blob(reply.data, reply.length); status = NT_STATUS_OK; done: diff --git a/source3/winbindd/winbindd_cred_cache.c b/source3/winbindd/winbindd_cred_cache.c index e63e73221e..df09bbe1bd 100644 --- a/source3/winbindd/winbindd_cred_cache.c +++ b/source3/winbindd/winbindd_cred_cache.c @@ -523,11 +523,10 @@ NTSTATUS add_ccache_to_list(const char *princ_name, "user krb5 ccache %s with %s\n", ccname, error_message(ret))); return krb5_to_nt_status(ret); - } else { - DEBUG(10, ("add_ccache_to_list: successfully destroyed " - "krb5 ccache %s for user %s\n", ccname, - username)); } + DEBUG(10, ("add_ccache_to_list: successfully destroyed " + "krb5 ccache %s for user %s\n", ccname, + username)); } #endif @@ -545,11 +544,11 @@ NTSTATUS add_ccache_to_list(const char *princ_name, /* FIXME: in this case we still might want to have a krb5 cred * event handler created - gd * Add ticket refresh handler here */ - + if (!lp_winbind_refresh_tickets() || renew_until <= 0) { return NT_STATUS_OK; } - + if (!entry->event) { if (postponed_request) { t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0); @@ -586,7 +585,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name, DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n")); } - + return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c index 98a16ee937..46c7a06f7c 100644 --- a/source3/winbindd/winbindd_creds.c +++ b/source3/winbindd/winbindd_creds.c @@ -4,17 +4,17 @@ Winbind daemon - cached credentials funcions Copyright (C) Guenther Deschner 2005 - + 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/>. */ @@ -66,10 +66,8 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain, if (info3 != NULL) { - DOM_SID sid; - sid_copy(&sid, info3->base.domain_sid); - sid_append_rid(&sid, info3->base.rid); - sid_copy(&cred_sid, &sid); + sid_compose(&cred_sid, info3->base.domain_sid, + info3->base.rid); info3->base.user_flags |= NETLOGON_CACHED_ACCOUNT; } else if (user_sid != NULL) { diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 357b6463d5..4658231a5c 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -195,8 +195,8 @@ static NTSTATUS append_afs_token(TALLOC_CTX *mem_ctx, DOM_SID user_sid; fstring sidstr; - sid_copy(&user_sid, info3->base.domain_sid); - sid_append_rid(&user_sid, info3->base.rid); + sid_compose(&user_sid, info3->base.domain_sid, + info3->base.rid); sid_to_fstring(sidstr, &user_sid); afsname = talloc_string_sub(mem_ctx, afsname, "%s", sidstr); diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index 2146953639..87494db2bb 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -612,9 +612,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; for (i=0;i<(*num_groups);i++) { - sid_copy(&((*user_grpsids)[i]), &domain->sid); - sid_append_rid(&((*user_grpsids)[i]), - rid_array->rids[i].rid); + sid_compose(&((*user_grpsids)[i]), &domain->sid, + rid_array->rids[i].rid); } return NT_STATUS_OK; |