mirror of
https://git.freebsd.org/ports.git
synced 2025-06-27 23:50:30 -04:00
(CVE-2012-1182): - Update samba36 to 3.6.4; - Update samba35 to 3.5.14; - Update samba34 to 3.4.16; All samba users are advised to update. Security: baf37cd2-8351-11e1-894e-00215c6a37bb With hat: secteam@
1611 lines
52 KiB
Diff
1611 lines
52 KiB
Diff
0001-s3-Fix-bug-8238-KB2536276-prevents-access-to-sha.patch
|
|
samba-3.4-check-bad-password-count.patch
|
|
samba-3.4-net-trustdom-list-tidyup.patch
|
|
samba3-3.4-honor-all-loopback-ips.patch
|
|
samba3-3.4.15-nmbd-bind-explicit.patch
|
|
samba3-3.4.4-fix-account-unlock.patch
|
|
|
|
From 0b0c5596034a007b71785a0f36aaf40cf74b234d Mon Sep 17 00:00:00 2001
|
|
From: Volker Lendecke <vl@samba.org>
|
|
Date: Thu, 16 Jun 2011 22:20:49 +0200
|
|
Subject: [PATCH] s3: Fix bug 8238 -- KB2536276 prevents access to shares
|
|
|
|
Without this we were not sending the workgroup name in the negprot reply if
|
|
plain text passwords are used.
|
|
---
|
|
source3/smbd/negprot.c | 1 +
|
|
1 files changed, 1 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
|
|
index 81d29d9..51ad80d 100644
|
|
--- a/source3/smbd/negprot.c
|
|
+++ b/source3/smbd/negprot.c
|
|
@@ -382,6 +382,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
|
|
reply_nterror(req, NT_STATUS_NO_MEMORY);
|
|
return;
|
|
}
|
|
+ p += ret;
|
|
DEBUG(3,("not using SPNEGO\n"));
|
|
} else {
|
|
DATA_BLOB spnego_blob = negprot_spnego();
|
|
--
|
|
1.5.6.5
|
|
|
|
source3/auth/auth_sam.c | 159 +++++++++++++++++++++++++++++++++---------
|
|
source3/include/proto.h | 3 +
|
|
source3/passdb/pdb_get_set.c | 132 +++++++++++++++++++----------------
|
|
source3/smbd/chgpasswd.c | 87 ++++++++++++++++-------
|
|
4 files changed, 262 insertions(+), 119 deletions(-)
|
|
|
|
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
|
|
index fdfa292..24e7898 100644
|
|
--- a/source3/auth/auth_sam.c
|
|
+++ b/source3/auth/auth_sam.c
|
|
@@ -32,16 +32,14 @@
|
|
|
|
static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
|
|
TALLOC_CTX *mem_ctx,
|
|
- struct samu *sampass,
|
|
+ const char *username,
|
|
+ uint32_t acct_ctrl,
|
|
+ const uint8_t *lm_pw,
|
|
+ const uint8_t *nt_pw,
|
|
const auth_usersupplied_info *user_info,
|
|
DATA_BLOB *user_sess_key,
|
|
DATA_BLOB *lm_sess_key)
|
|
{
|
|
- uint32 acct_ctrl;
|
|
- const uint8 *lm_pw, *nt_pw;
|
|
- const char *username = pdb_get_username(sampass);
|
|
-
|
|
- 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));
|
|
@@ -52,9 +50,6 @@ 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);
|
|
-
|
|
return ntlm_password_check(mem_ctx, &auth_context->challenge,
|
|
&user_info->lm_resp, &user_info->nt_resp,
|
|
&user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd,
|
|
@@ -240,6 +235,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 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(AP_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
|
|
@@ -259,6 +323,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;
|
|
@@ -267,7 +335,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;
|
|
}
|
|
|
|
@@ -284,16 +353,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
|
|
@@ -302,10 +377,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 {
|
|
@@ -313,18 +397,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);
|
|
@@ -332,30 +419,32 @@ 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 = 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 =
|
|
@@ -370,6 +459,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;
|
|
}
|
|
|
|
diff --git a/source3/include/proto.h b/source3/include/proto.h
|
|
index d2ae62c..2c72bc6 100644
|
|
--- a/source3/include/proto.h
|
|
+++ b/source3/include/proto.h
|
|
@@ -6179,6 +6179,9 @@ NTSTATUS pass_oem_change(char *user,
|
|
uchar password_encrypted_with_nt_hash[516],
|
|
const uchar old_nt_hash_encrypted[16],
|
|
uint32 *reject_reason);
|
|
+bool password_in_history(uint8_t nt_pw[NT_HASH_LEN],
|
|
+ uint32_t pw_history_len,
|
|
+ const uint8_t *pw_history);
|
|
NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, bool as_root, uint32 *samr_reject_reason);
|
|
|
|
/* The following definitions come from smbd/close.c */
|
|
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
|
|
index c79caf2..6e6b82b 100644
|
|
--- a/source3/passdb/pdb_get_set.c
|
|
+++ b/source3/passdb/pdb_get_set.c
|
|
@@ -979,6 +979,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;
|
|
@@ -1008,68 +1011,79 @@ 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(AP_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(AP_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 has 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);
|
|
+
|
|
+ /*
|
|
+ * Generate the md5 hash of the salt+new password as the
|
|
+ * second part of the history entry.
|
|
+ */
|
|
+ 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/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
|
|
index 61c3afb..046cc2c 100644
|
|
--- a/source3/smbd/chgpasswd.c
|
|
+++ b/source3/smbd/chgpasswd.c
|
|
@@ -1007,6 +1007,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
|
|
@@ -1016,11 +1069,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(AP_PASSWORD_HISTORY, &pwHisLen);
|
|
@@ -1047,30 +1097,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;
|
|
}
|
|
|
|
/***********************************************************
|
|
@@ -1116,7 +1149,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 "
|
|
--- a/source3/utils/net_rpc.c 2009-10-28 11:37:35.336126630 +0100
|
|
+++ b/source3/utils/net_rpc.c 2009-10-28 14:18:50.555361309 +0100
|
|
@@ -5709,7 +5709,9 @@
|
|
const char **argv)
|
|
{
|
|
fstring str_sid;
|
|
- sid_to_fstring(str_sid, domain_sid);
|
|
+ if (!sid_to_fstring(str_sid, domain_sid)) {
|
|
+ return NT_STATUS_UNSUCCESSFUL;
|
|
+ }
|
|
d_printf("%s\n", str_sid);
|
|
return NT_STATUS_OK;
|
|
}
|
|
@@ -6182,14 +6184,14 @@
|
|
&ndr_table_lsarpc.syntax_id, 0,
|
|
rpc_query_domain_sid, argc,
|
|
argv))
|
|
- d_fprintf(stderr, "couldn't get domain's sid\n");
|
|
+ d_printf("strange - couldn't get domain's sid\n");
|
|
|
|
cli_shutdown(remote_cli);
|
|
-
|
|
} else {
|
|
d_fprintf(stderr, "domain controller is not "
|
|
"responding: %s\n",
|
|
nt_errstr(nt_status));
|
|
+ d_printf("couldn't get domain's sid\n");
|
|
};
|
|
};
|
|
|
|
commit b6afe7ef236a454d8a6abf104b8846f817378f73
|
|
Author: Björn Jacke <bj@sernet.de>
|
|
Date: Thu Oct 15 02:02:30 2009 +0200
|
|
|
|
util: cope the all loopback addresses IPv4 knows
|
|
|
|
The fact that we just recogniced 127.0.0.1 as loopback IP address and not the
|
|
rest of the 127.0.0.0/8 IP address range we used the lo interface for sending
|
|
packages even though we should send them to some more physical interface. This
|
|
way we ended up with failing WINS registration and so on like in #6348.
|
|
On the lo interface sendto() returned "Invalid Argument" (EINVAL).
|
|
|
|
diff --git a/lib/util/util_net.c b/lib/util/util_net.c
|
|
index 0ce495e..0511a28 100644
|
|
--- a/lib/util/util_net.c
|
|
+++ b/lib/util/util_net.c
|
|
@@ -351,13 +351,11 @@ bool is_broadcast_addr(const struct sockaddr *pss)
|
|
}
|
|
|
|
/**
|
|
- * Check if an IPv7 is 127.0.0.1
|
|
+ * Check if an IPv4 is in IN_LOOPBACKNET (127.0.0.0/8)
|
|
*/
|
|
bool is_loopback_ip_v4(struct in_addr ip)
|
|
{
|
|
- struct in_addr a;
|
|
- a.s_addr = htonl(INADDR_LOOPBACK);
|
|
- return(ip.s_addr == a.s_addr);
|
|
+ return ((ntohl(ip.s_addr) & IN_CLASSA_NET) == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT));
|
|
}
|
|
|
|
/**
|
|
From 981b5a14807883eaf9be4a4b95bb85955ecad690 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Thu, 28 Jan 2010 11:04:05 +0100
|
|
Subject: [PATCH 1/4] s3:nmbd: also listen explicit on the subnet broadcast
|
|
addresses
|
|
|
|
And send replies always via the unicast address of the subnet.
|
|
|
|
This behavior is off by default (as before)
|
|
and can be enabled with "nmbd:bind explicit broadcast = yes".
|
|
|
|
metze
|
|
(cherry picked from commit 30a1bc365071befd07e68e24ca4fa3843159ab13)
|
|
---
|
|
source3/include/nameserv.h | 5 +-
|
|
source3/libsmb/namequery.c | 6 +-
|
|
source3/libsmb/nmblib.c | 9 ++-
|
|
source3/nmbd/nmbd.c | 5 +-
|
|
source3/nmbd/nmbd_packets.c | 197 ++++++++++++++++++++++++++++--------------
|
|
source3/nmbd/nmbd_subnetdb.c | 123 +++++++++++++++++---------
|
|
6 files changed, 230 insertions(+), 115 deletions(-)
|
|
|
|
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
|
|
index 496d87e..53ffd6f 100644
|
|
--- a/source3/include/nameserv.h
|
|
+++ b/source3/include/nameserv.h
|
|
@@ -434,7 +434,9 @@ struct subnet_record {
|
|
struct in_addr mask_ip;
|
|
struct in_addr myip;
|
|
int nmb_sock; /* socket to listen for unicast 137. */
|
|
+ int nmb_bcast; /* socket to listen for broadcast 137. */
|
|
int dgram_sock; /* socket to listen for unicast 138. */
|
|
+ int dgram_bcast; /* socket to listen for broadcast 138. */
|
|
};
|
|
|
|
/* A resource record. */
|
|
@@ -530,7 +532,8 @@ struct packet_struct
|
|
bool locked;
|
|
struct in_addr ip;
|
|
int port;
|
|
- int fd;
|
|
+ int recv_fd;
|
|
+ int send_fd;
|
|
time_t timestamp;
|
|
enum packet_type packet_type;
|
|
union {
|
|
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
|
|
index 50fb9f1..8f8d891 100644
|
|
--- a/source3/libsmb/namequery.c
|
|
+++ b/source3/libsmb/namequery.c
|
|
@@ -301,7 +301,8 @@ NODE_STATUS_STRUCT *node_status_query(int fd,
|
|
|
|
p.ip = ((const struct sockaddr_in *)to_ss)->sin_addr;
|
|
p.port = NMB_PORT;
|
|
- p.fd = fd;
|
|
+ p.recv_fd = -1;
|
|
+ p.send_fd = fd;
|
|
p.timestamp = time(NULL);
|
|
p.packet_type = NMB_PACKET;
|
|
|
|
@@ -678,7 +679,8 @@ struct sockaddr_storage *name_query(int fd,
|
|
|
|
p.ip = ((struct sockaddr_in *)to_ss)->sin_addr;
|
|
p.port = NMB_PORT;
|
|
- p.fd = fd;
|
|
+ p.recv_fd = -1;
|
|
+ p.send_fd = fd;
|
|
p.timestamp = time(NULL);
|
|
p.packet_type = NMB_PACKET;
|
|
|
|
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
|
|
index 8230c5a..f7bcf8f 100644
|
|
--- a/source3/libsmb/nmblib.c
|
|
+++ b/source3/libsmb/nmblib.c
|
|
@@ -601,6 +601,8 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
|
|
|
|
/* Ensure this copy is not locked. */
|
|
pkt_copy->locked = False;
|
|
+ pkt_copy->recv_fd = -1;
|
|
+ pkt_copy->send_fd = -1;
|
|
|
|
/* Ensure this copy has no resource records. */
|
|
nmb = &packet->packet.nmb;
|
|
@@ -666,6 +668,8 @@ static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
|
|
|
|
/* Ensure this copy is not locked. */
|
|
pkt_copy->locked = False;
|
|
+ pkt_copy->recv_fd = -1;
|
|
+ pkt_copy->send_fd = -1;
|
|
|
|
/* There are no additional pointers in a dgram packet,
|
|
we are finished. */
|
|
@@ -791,7 +795,8 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
|
|
if (!packet)
|
|
return NULL;
|
|
|
|
- packet->fd = fd;
|
|
+ packet->recv_fd = fd;
|
|
+ packet->send_fd = -1;
|
|
|
|
DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
|
|
length, inet_ntoa(packet->ip), packet->port ) );
|
|
@@ -1075,7 +1080,7 @@ bool send_packet(struct packet_struct *p)
|
|
if (!len)
|
|
return(False);
|
|
|
|
- return(send_udp(p->fd,buf,len,p->ip,p->port));
|
|
+ return(send_udp(p->send_fd,buf,len,p->ip,p->port));
|
|
}
|
|
|
|
/****************************************************************************
|
|
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
|
|
index eefe27a..07a4b02 100644
|
|
--- a/source3/nmbd/nmbd.c
|
|
+++ b/source3/nmbd/nmbd.c
|
|
@@ -441,13 +441,14 @@ static void msg_nmbd_send_packet(struct messaging_context *msg,
|
|
local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
|
|
subrec = FIRST_SUBNET;
|
|
|
|
- p->fd = (p->packet_type == NMB_PACKET) ?
|
|
+ p->recv_fd = -1;
|
|
+ p->send_fd = (p->packet_type == NMB_PACKET) ?
|
|
subrec->nmb_sock : subrec->dgram_sock;
|
|
|
|
for (subrec = FIRST_SUBNET; subrec != NULL;
|
|
subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
|
if (ip_equal_v4(*local_ip, subrec->myip)) {
|
|
- p->fd = (p->packet_type == NMB_PACKET) ?
|
|
+ p->send_fd = (p->packet_type == NMB_PACKET) ?
|
|
subrec->nmb_sock : subrec->dgram_sock;
|
|
break;
|
|
}
|
|
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
|
|
index 855f6af..402282c 100644
|
|
--- a/source3/nmbd/nmbd_packets.c
|
|
+++ b/source3/nmbd/nmbd_packets.c
|
|
@@ -207,7 +207,8 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb
|
|
|
|
packet->ip = to_ip;
|
|
packet->port = NMB_PORT;
|
|
- packet->fd = ClientNMB;
|
|
+ packet->recv_fd = -1;
|
|
+ packet->send_fd = ClientNMB;
|
|
packet->timestamp = time(NULL);
|
|
packet->packet_type = NMB_PACKET;
|
|
packet->locked = False;
|
|
@@ -258,7 +259,8 @@ static bool create_and_init_additional_record(struct packet_struct *packet,
|
|
our standard refresh cycle for that name which copes nicely
|
|
with disconnected networks.
|
|
*/
|
|
- packet->fd = find_subnet_fd_for_address(*register_ip);
|
|
+ packet->recv_fd = -1;
|
|
+ packet->send_fd = find_subnet_fd_for_address(*register_ip);
|
|
|
|
return True;
|
|
}
|
|
@@ -743,7 +745,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
|
|
}
|
|
|
|
DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip)));
|
|
- p->fd = find_subnet_fd_for_address( *ifip );
|
|
+ p->send_fd = find_subnet_fd_for_address( *ifip );
|
|
break;
|
|
}
|
|
}
|
|
@@ -979,9 +981,14 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
|
|
}
|
|
|
|
packet.packet_type = NMB_PACKET;
|
|
+ packet.recv_fd = -1;
|
|
/* Ensure we send out on the same fd that the original
|
|
packet came in on to give the correct source IP address. */
|
|
- packet.fd = orig_packet->fd;
|
|
+ if (orig_packet->send_fd != -1) {
|
|
+ packet.send_fd = orig_packet->send_fd;
|
|
+ } else {
|
|
+ packet.send_fd = orig_packet->recv_fd;
|
|
+ }
|
|
packet.timestamp = time(NULL);
|
|
|
|
debug_nmb_packet(&packet);
|
|
@@ -1679,26 +1686,32 @@ static bool create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_n
|
|
return True;
|
|
}
|
|
|
|
+ /* The Client* sockets */
|
|
+ count++;
|
|
+
|
|
/* Check that we can add all the fd's we need. */
|
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
|
|
count++;
|
|
|
|
- if((count*2) + 2 >= FD_SETSIZE) {
|
|
+ /* each interface gets 4 sockets */
|
|
+ count *= 4;
|
|
+
|
|
+ if(count >= FD_SETSIZE) {
|
|
DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
|
|
-only use %d.\n", (count*2) + 2, FD_SETSIZE));
|
|
+only use %d.\n", count, FD_SETSIZE));
|
|
SAFE_FREE(pset);
|
|
return True;
|
|
}
|
|
|
|
- if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) {
|
|
- DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
|
|
+ if((sock_array = SMB_MALLOC_ARRAY(int, count)) == NULL) {
|
|
+ DEBUG(0,("create_listen_fdset: malloc fail for socket array. size %d\n", count));
|
|
SAFE_FREE(pset);
|
|
return True;
|
|
}
|
|
|
|
FD_ZERO(pset);
|
|
|
|
- /* Add in the broadcast socket on 137. */
|
|
+ /* Add in the lp_socket_address() interface on 137. */
|
|
if (ClientNMB < 0 || ClientNMB >= FD_SETSIZE) {
|
|
errno = EBADF;
|
|
SAFE_FREE(pset);
|
|
@@ -1709,6 +1722,9 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
|
|
sock_array[num++] = ClientNMB;
|
|
*maxfd = MAX( *maxfd, ClientNMB);
|
|
|
|
+ /* the lp_socket_address() interface has only one socket */
|
|
+ sock_array[num++] = -1;
|
|
+
|
|
/* Add in the 137 sockets on all the interfaces. */
|
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
|
if (subrec->nmb_sock < 0 || subrec->nmb_sock >= FD_SETSIZE) {
|
|
@@ -1718,9 +1734,19 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
|
|
FD_SET(subrec->nmb_sock,pset);
|
|
sock_array[num++] = subrec->nmb_sock;
|
|
*maxfd = MAX( *maxfd, subrec->nmb_sock);
|
|
+
|
|
+ sock_array[num++] = subrec->nmb_bcast;
|
|
+ if (subrec->nmb_bcast != -1) {
|
|
+ if (subrec->nmb_bcast < 0 || subrec->nmb_bcast >= FD_SETSIZE) {
|
|
+ /* We have to ignore sockets outside FD_SETSIZE. */
|
|
+ continue;
|
|
+ }
|
|
+ FD_SET(subrec->nmb_bcast,pset);
|
|
+ *maxfd = MAX( *maxfd, subrec->nmb_bcast);
|
|
+ }
|
|
}
|
|
|
|
- /* Add in the broadcast socket on 138. */
|
|
+ /* Add in the lp_socket_address() interface on 138. */
|
|
if (ClientDGRAM < 0 || ClientDGRAM >= FD_SETSIZE) {
|
|
errno = EBADF;
|
|
SAFE_FREE(pset);
|
|
@@ -1731,6 +1757,9 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
|
|
sock_array[num++] = ClientDGRAM;
|
|
*maxfd = MAX( *maxfd, ClientDGRAM);
|
|
|
|
+ /* the lp_socket_address() interface has only one socket */
|
|
+ sock_array[num++] = -1;
|
|
+
|
|
/* Add in the 138 sockets on all the interfaces. */
|
|
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
|
|
if (subrec->dgram_sock < 0 || subrec->dgram_sock >= FD_SETSIZE) {
|
|
@@ -1740,9 +1769,19 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
|
|
FD_SET(subrec->dgram_sock,pset);
|
|
sock_array[num++] = subrec->dgram_sock;
|
|
*maxfd = MAX( *maxfd, subrec->dgram_sock);
|
|
+
|
|
+ sock_array[num++] = subrec->dgram_bcast;
|
|
+ if (subrec->dgram_bcast != -1) {
|
|
+ if (subrec->dgram_bcast < 0 || subrec->dgram_bcast >= FD_SETSIZE) {
|
|
+ /* We have to ignore sockets outside FD_SETSIZE. */
|
|
+ continue;
|
|
+ }
|
|
+ FD_SET(subrec->dgram_bcast,pset);
|
|
+ *maxfd = MAX( *maxfd, subrec->dgram_bcast);
|
|
+ }
|
|
}
|
|
|
|
- *listen_number = num;
|
|
+ *listen_number = count;
|
|
|
|
SAFE_FREE(*ppset);
|
|
SAFE_FREE(*psock_array);
|
|
@@ -1831,61 +1870,90 @@ bool listen_for_packets(bool run_election)
|
|
#endif
|
|
|
|
for(i = 0; i < listen_number; i++) {
|
|
+ enum packet_type packet_type;
|
|
+ struct packet_struct *packet;
|
|
+ const char *packet_name;
|
|
+ int client_fd;
|
|
+ int client_port;
|
|
+
|
|
+ if (sock_array[i] == -1) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!FD_ISSET(sock_array[i],&r_fds)) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
if (i < (listen_number/2)) {
|
|
- /* Processing a 137 socket. */
|
|
- if (FD_ISSET(sock_array[i],&r_fds)) {
|
|
- struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
|
|
- if (packet) {
|
|
- /*
|
|
- * If we got a packet on the broadcast socket and interfaces
|
|
- * only is set then check it came from one of our local nets.
|
|
- */
|
|
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) &&
|
|
- (!is_local_net_v4(packet->ip))) {
|
|
- DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
|
|
- inet_ntoa(packet->ip),packet->port));
|
|
- free_packet(packet);
|
|
- } else if ((is_loopback_ip_v4(packet->ip) ||
|
|
- ismyip_v4(packet->ip)) && packet->port == global_nmb_port &&
|
|
- packet->packet.nmb.header.nm_flags.bcast) {
|
|
- DEBUG(7,("discarding own bcast packet from %s:%d\n",
|
|
- inet_ntoa(packet->ip),packet->port));
|
|
- free_packet(packet);
|
|
- } else {
|
|
- /* Save the file descriptor this packet came in on. */
|
|
- packet->fd = sock_array[i];
|
|
- queue_packet(packet);
|
|
- }
|
|
- }
|
|
- }
|
|
+ /* Port 137 */
|
|
+ packet_type = NMB_PACKET;
|
|
+ packet_name = "nmb";
|
|
+ client_fd = ClientNMB;
|
|
+ client_port = global_nmb_port;
|
|
} else {
|
|
- /* Processing a 138 socket. */
|
|
- if (FD_ISSET(sock_array[i],&r_fds)) {
|
|
- struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
|
|
- if (packet) {
|
|
- /*
|
|
- * If we got a packet on the broadcast socket and interfaces
|
|
- * only is set then check it came from one of our local nets.
|
|
- */
|
|
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
|
|
- (!is_local_net_v4(packet->ip))) {
|
|
- DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
|
|
- inet_ntoa(packet->ip),packet->port));
|
|
- free_packet(packet);
|
|
- } else if ((is_loopback_ip_v4(packet->ip) ||
|
|
- ismyip_v4(packet->ip)) && packet->port == DGRAM_PORT) {
|
|
- DEBUG(7,("discarding own dgram packet from %s:%d\n",
|
|
- inet_ntoa(packet->ip),packet->port));
|
|
- free_packet(packet);
|
|
- } else {
|
|
- /* Save the file descriptor this packet came in on. */
|
|
- packet->fd = sock_array[i];
|
|
- queue_packet(packet);
|
|
- }
|
|
- }
|
|
+ /* Port 137 */
|
|
+ packet_type = DGRAM_PACKET;
|
|
+ packet_name = "dgram";
|
|
+ client_fd = ClientDGRAM;
|
|
+ client_port = DGRAM_PORT;
|
|
+ }
|
|
+
|
|
+ packet = read_packet(sock_array[i], packet_type);
|
|
+ if (!packet) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * If we got a packet on the broadcast socket and interfaces
|
|
+ * only is set then check it came from one of our local nets.
|
|
+ */
|
|
+ if (lp_bind_interfaces_only() &&
|
|
+ (sock_array[i] == client_fd) &&
|
|
+ (!is_local_net_v4(packet->ip))) {
|
|
+ DEBUG(7,("discarding %s packet sent to broadcast socket from %s:%d\n",
|
|
+ packet_name, inet_ntoa(packet->ip), packet->port));
|
|
+ free_packet(packet);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if ((is_loopback_ip_v4(packet->ip) || ismyip_v4(packet->ip)) &&
|
|
+ packet->port == client_port)
|
|
+ {
|
|
+ if (client_port == DGRAM_PORT) {
|
|
+ DEBUG(7,("discarding own dgram packet from %s:%d\n",
|
|
+ inet_ntoa(packet->ip),packet->port));
|
|
+ free_packet(packet);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (packet->packet.nmb.header.nm_flags.bcast) {
|
|
+ DEBUG(7,("discarding own nmb bcast packet from %s:%d\n",
|
|
+ inet_ntoa(packet->ip),packet->port));
|
|
+ free_packet(packet);
|
|
+ continue;
|
|
}
|
|
- } /* end processing 138 socket. */
|
|
- } /* end for */
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * 0,2,4,... are unicast sockets
|
|
+ * 1,3,5,... are broadcast sockets
|
|
+ *
|
|
+ * on broadcast socket we only receive packets
|
|
+ * and send replies via the unicast socket.
|
|
+ *
|
|
+ * 0,1 and 2,3 and ... belong together.
|
|
+ */
|
|
+ if ((i % 2) != 0) {
|
|
+ /* this is a broadcast socket */
|
|
+ packet->send_fd = sock_array[i-1];
|
|
+ } else {
|
|
+ /* this is already a unicast socket */
|
|
+ packet->send_fd = sock_array[i];
|
|
+ }
|
|
+
|
|
+ queue_packet(packet);
|
|
+ }
|
|
+
|
|
return False;
|
|
}
|
|
|
|
@@ -1964,7 +2032,8 @@ bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len,
|
|
|
|
p.ip = dest_ip;
|
|
p.port = dest_port;
|
|
- p.fd = find_subnet_mailslot_fd_for_address( src_ip );
|
|
+ p.recv_fd = -1;
|
|
+ p.send_fd = find_subnet_mailslot_fd_for_address( src_ip );
|
|
p.timestamp = time(NULL);
|
|
p.packet_type = DGRAM_PACKET;
|
|
|
|
diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c
|
|
index 13bc931..96d7b32 100644
|
|
--- a/source3/nmbd/nmbd_subnetdb.c
|
|
+++ b/source3/nmbd/nmbd_subnetdb.c
|
|
@@ -76,18 +76,21 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
|
|
struct in_addr mask_ip)
|
|
{
|
|
struct subnet_record *subrec = NULL;
|
|
- int nmb_sock, dgram_sock;
|
|
+ int nmb_sock = -1;
|
|
+ int dgram_sock = -1;
|
|
+ int nmb_bcast = -1;
|
|
+ int dgram_bcast = -1;
|
|
+ bool bind_bcast = lp_parm_bool(-1, "nmbd", "bind explicit broadcast", false);
|
|
|
|
/* Check if we are creating a non broadcast subnet - if so don't create
|
|
sockets. */
|
|
|
|
- if(type != NORMAL_SUBNET) {
|
|
- nmb_sock = -1;
|
|
- dgram_sock = -1;
|
|
- } else {
|
|
+ if (type == NORMAL_SUBNET) {
|
|
struct sockaddr_storage ss;
|
|
+ struct sockaddr_storage ss_bcast;
|
|
|
|
in_addr_to_sockaddr_storage(&ss, myip);
|
|
+ in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip);
|
|
|
|
/*
|
|
* Attempt to open the sockets on port 137/138 for this interface
|
|
@@ -95,60 +98,74 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
|
|
* Fail the subnet creation if this fails.
|
|
*/
|
|
|
|
- if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, &ss,true)) == -1) {
|
|
- if( DEBUGLVL( 0 ) ) {
|
|
- Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
|
- Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
|
|
- Debug1( "for port %d. ", global_nmb_port );
|
|
- Debug1( "Error was %s\n", strerror(errno) );
|
|
+ nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,
|
|
+ 0, &ss, true);
|
|
+ if (nmb_sock == -1) {
|
|
+ DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
|
|
+ DEBUGADD(0,(" Failed to open nmb socket on interface %s ",
|
|
+ inet_ntoa(myip)));
|
|
+ DEBUGADD(0,("for port %d. ", global_nmb_port));
|
|
+ DEBUGADD(0,("Error was %s\n", strerror(errno)));
|
|
+ goto failed;
|
|
+ }
|
|
+ set_socket_options(nmb_sock,"SO_BROADCAST");
|
|
+ set_blocking(nmb_sock, false);
|
|
+
|
|
+ if (bind_bcast) {
|
|
+ nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port,
|
|
+ 0, &ss_bcast, true);
|
|
+ if (nmb_bcast == -1) {
|
|
+ DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
|
|
+ DEBUGADD(0,(" Failed to open nmb bcast socket on interface %s ",
|
|
+ inet_ntoa(bcast_ip)));
|
|
+ DEBUGADD(0,("for port %d. ", global_nmb_port));
|
|
+ DEBUGADD(0,("Error was %s\n", strerror(errno)));
|
|
+ goto failed;
|
|
}
|
|
- return NULL;
|
|
+ set_socket_options(nmb_bcast, "SO_BROADCAST");
|
|
+ set_blocking(nmb_bcast, false);
|
|
}
|
|
|
|
- if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, &ss, true)) == -1) {
|
|
- if( DEBUGLVL( 0 ) ) {
|
|
- Debug1( "nmbd_subnetdb:make_subnet()\n" );
|
|
- Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
|
|
- Debug1( "for port %d. ", DGRAM_PORT );
|
|
- Debug1( "Error was %s\n", strerror(errno) );
|
|
+ dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
|
|
+ 3, &ss, true);
|
|
+ if (dgram_sock == -1) {
|
|
+ DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
|
|
+ DEBUGADD(0,(" Failed to open dgram socket on interface %s ",
|
|
+ inet_ntoa(myip)));
|
|
+ DEBUGADD(0,("for port %d. ", DGRAM_PORT));
|
|
+ DEBUGADD(0,("Error was %s\n", strerror(errno)));
|
|
+ goto failed;
|
|
+ }
|
|
+ set_socket_options(dgram_sock, "SO_BROADCAST");
|
|
+ set_blocking(dgram_sock, false);
|
|
+
|
|
+ if (bind_bcast) {
|
|
+ dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
|
|
+ 3, &ss_bcast, true);
|
|
+ if (dgram_bcast == -1) {
|
|
+ DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
|
|
+ DEBUGADD(0,(" Failed to open dgram bcast socket on interface %s ",
|
|
+ inet_ntoa(bcast_ip)));
|
|
+ DEBUGADD(0,("for port %d. ", DGRAM_PORT));
|
|
+ DEBUGADD(0,("Error was %s\n", strerror(errno)));
|
|
+ goto failed;
|
|
}
|
|
- return NULL;
|
|
+ set_socket_options(dgram_bcast, "SO_BROADCAST");
|
|
+ set_blocking(dgram_bcast, false);
|
|
}
|
|
-
|
|
- /* Make sure we can broadcast from these sockets. */
|
|
- set_socket_options(nmb_sock,"SO_BROADCAST");
|
|
- set_socket_options(dgram_sock,"SO_BROADCAST");
|
|
-
|
|
- /* Set them non-blocking. */
|
|
- set_blocking(nmb_sock, False);
|
|
- set_blocking(dgram_sock, False);
|
|
}
|
|
|
|
subrec = SMB_MALLOC_P(struct subnet_record);
|
|
if (!subrec) {
|
|
DEBUG(0,("make_subnet: malloc fail !\n"));
|
|
- if (nmb_sock != -1) {
|
|
- close(nmb_sock);
|
|
- }
|
|
- if (dgram_sock != -1) {
|
|
- close(dgram_sock);
|
|
- }
|
|
- return(NULL);
|
|
+ goto failed;
|
|
}
|
|
|
|
ZERO_STRUCTP(subrec);
|
|
|
|
if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
|
|
DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
|
|
- if (nmb_sock != -1) {
|
|
- close(nmb_sock);
|
|
- }
|
|
- if (dgram_sock != -1) {
|
|
- close(dgram_sock);
|
|
- }
|
|
- ZERO_STRUCTP(subrec);
|
|
- SAFE_FREE(subrec);
|
|
- return(NULL);
|
|
+ goto failed;
|
|
}
|
|
|
|
DEBUG(2, ("making subnet name:%s ", name ));
|
|
@@ -163,9 +180,27 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
|
|
subrec->myip = myip;
|
|
subrec->type = type;
|
|
subrec->nmb_sock = nmb_sock;
|
|
+ subrec->nmb_bcast = nmb_bcast;
|
|
subrec->dgram_sock = dgram_sock;
|
|
-
|
|
+ subrec->dgram_bcast = dgram_bcast;
|
|
+
|
|
return subrec;
|
|
+
|
|
+failed:
|
|
+ SAFE_FREE(subrec);
|
|
+ if (nmb_sock != -1) {
|
|
+ close(nmb_sock);
|
|
+ }
|
|
+ if (nmb_bcast != -1) {
|
|
+ close(nmb_bcast);
|
|
+ }
|
|
+ if (dgram_sock != -1) {
|
|
+ close(dgram_sock);
|
|
+ }
|
|
+ if (dgram_bcast != -1) {
|
|
+ close(dgram_bcast);
|
|
+ }
|
|
+ return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
--
|
|
1.7.6
|
|
|
|
|
|
From 1d66aaf6f32a702703533d0391b77bdf047222b1 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Mon, 8 Feb 2010 12:51:29 +0100
|
|
Subject: [PATCH 2/4] s3:nmbd: change "nmbd:bind explicit broadcast" into
|
|
"nmbd bind explicit broadcast"
|
|
|
|
metze
|
|
(cherry picked from commit 0140bc389d56511c3255720856bdb64803ba8930)
|
|
---
|
|
source3/include/proto.h | 1 +
|
|
source3/nmbd/nmbd_subnetdb.c | 2 +-
|
|
source3/param/loadparm.c | 11 +++++++++++
|
|
3 files changed, 13 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/source3/include/proto.h b/source3/include/proto.h
|
|
index 46ed4ab..17ab59b 100644
|
|
--- a/source3/include/proto.h
|
|
+++ b/source3/include/proto.h
|
|
@@ -3939,6 +3939,7 @@ const char *lp_logon_drive(void);
|
|
const char *lp_logon_home(void);
|
|
char *lp_remote_announce(void);
|
|
char *lp_remote_browse_sync(void);
|
|
+bool lp_nmbd_bind_explicit_broadcast(void);
|
|
const char **lp_wins_server_list(void);
|
|
const char **lp_interfaces(void);
|
|
const char *lp_socket_address(void);
|
|
diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c
|
|
index 96d7b32..703e229 100644
|
|
--- a/source3/nmbd/nmbd_subnetdb.c
|
|
+++ b/source3/nmbd/nmbd_subnetdb.c
|
|
@@ -80,7 +80,7 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
|
|
int dgram_sock = -1;
|
|
int nmb_bcast = -1;
|
|
int dgram_bcast = -1;
|
|
- bool bind_bcast = lp_parm_bool(-1, "nmbd", "bind explicit broadcast", false);
|
|
+ bool bind_bcast = lp_nmbd_bind_explicit_broadcast();
|
|
|
|
/* Check if we are creating a non broadcast subnet - if so don't create
|
|
sockets. */
|
|
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
|
|
index 2ba2dd3..87df0d4 100644
|
|
--- a/source3/param/loadparm.c
|
|
+++ b/source3/param/loadparm.c
|
|
@@ -157,6 +157,7 @@ struct global {
|
|
char *szRemoteAnnounce;
|
|
char *szRemoteBrowseSync;
|
|
char *szSocketAddress;
|
|
+ bool bNmbdBindExplicitBroadcast;
|
|
char *szNISHomeMapName;
|
|
char *szAnnounceVersion; /* This is initialised in init_globals */
|
|
char *szWorkgroup;
|
|
@@ -3929,6 +3930,15 @@ static struct parm_struct parm_table[] = {
|
|
.flags = FLAG_ADVANCED,
|
|
},
|
|
{
|
|
+ .label = "nmbd bind explicit broadcast",
|
|
+ .type = P_BOOL,
|
|
+ .p_class = P_GLOBAL,
|
|
+ .ptr = &Globals.bNmbdBindExplicitBroadcast,
|
|
+ .special = NULL,
|
|
+ .enum_list = NULL,
|
|
+ .flags = FLAG_ADVANCED,
|
|
+ },
|
|
+ {
|
|
.label = "homedir map",
|
|
.type = P_STRING,
|
|
.p_class = P_GLOBAL,
|
|
@@ -5269,6 +5279,7 @@ FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
|
|
FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
|
|
FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
|
|
FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
|
|
+FN_GLOBAL_BOOL(lp_nmbd_bind_explicit_broadcast, &Globals.bNmbdBindExplicitBroadcast)
|
|
FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
|
|
FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
|
|
FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
|
|
--
|
|
1.7.6
|
|
|
|
|
|
From e23890c8e84e00df9770b1f6316711b9d08dd9d2 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Mon, 8 Feb 2010 12:59:13 +0100
|
|
Subject: [PATCH 3/4] s3:docs-xml: document "nmbd bind explicit broadcast"
|
|
|
|
metze
|
|
(cherry picked from commit 9887751f6fa6f7e4fd5c79c637e0576405000c01)
|
|
---
|
|
.../smbdotconf/misc/nmbdbindexplicitbroadcast.xml | 16 ++++++++++++++++
|
|
1 files changed, 16 insertions(+), 0 deletions(-)
|
|
create mode 100644 docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
|
|
|
|
diff --git a/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml b/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
|
|
new file mode 100644
|
|
index 0000000..f328594
|
|
--- /dev/null
|
|
+++ b/docs-xml/smbdotconf/misc/nmbdbindexplicitbroadcast.xml
|
|
@@ -0,0 +1,16 @@
|
|
+<samba:parameter name="nmbd bind explicit broadcast"
|
|
+ context="G"
|
|
+ advanced="1" developer="1"
|
|
+ type="boolean"
|
|
+ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
|
|
+<description>
|
|
+ <para>
|
|
+ This option allows you to setup <citerefentry><refentrytitle>nmbd</refentrytitle>
|
|
+ <manvolnum>8</manvolnum></citerefentry> to explicit bind to the
|
|
+ broadcast address of the local subnets. This is only useful in
|
|
+ combination with the <smbconfoption name="socket address"/> option.
|
|
+ </para>
|
|
+</description>
|
|
+
|
|
+<value type="default">no</value>
|
|
+</samba:parameter>
|
|
--
|
|
1.7.6
|
|
|
|
|
|
From df242559163fef493e4305b9eb54549012700565 Mon Sep 17 00:00:00 2001
|
|
From: Jeremy Allison <jra@samba.org>
|
|
Date: Wed, 10 Feb 2010 12:32:05 -0800
|
|
Subject: [PATCH 4/4] More of the fix for bug #7118 - nmbd problems with
|
|
socket address.
|
|
|
|
Add a simple "processed packet queue" cache to stop nmbd responding to
|
|
packets received on the broadcast and non-broadcast socket (which
|
|
it has opened when "nmbd bind explicit broadcast = yes").
|
|
|
|
This is a very simple packet queue - it only keeps the packets
|
|
processed during a single call to listen_for_packets() (i.e. one
|
|
select call). This means that if the delivery notification for a
|
|
packet received on both broadcast and non-broadcast addresses
|
|
is done in two different select calls, the packet will still be
|
|
processed twice. This is a very rare occurrance and we can just
|
|
live with it when it does as the protocol is stateless. If this
|
|
is ever flagged as a repeatable problem then we can add a longer
|
|
lived cache, using timeout processing to clear etc. etc. But without
|
|
storing all packets processed we can never be *sure* we've eliminated
|
|
the race condition so I'm going to go with this simple solution until
|
|
someone proves a more complex one is needed :-).
|
|
|
|
Jeremy.
|
|
(cherry picked from commit 6fe7ee1d216fcf722b3efa23fd80782ce0dd0e9f)
|
|
---
|
|
source3/nmbd/nmbd_packets.c | 89 +++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 89 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
|
|
index 402282c..567a9df 100644
|
|
--- a/source3/nmbd/nmbd_packets.c
|
|
+++ b/source3/nmbd/nmbd_packets.c
|
|
@@ -1793,6 +1793,83 @@ only use %d.\n", count, FD_SETSIZE));
|
|
}
|
|
|
|
/****************************************************************************
|
|
+ List of packets we're processing this select.
|
|
+***************************************************************************/
|
|
+
|
|
+struct processed_packet {
|
|
+ struct processed_packet *next;
|
|
+ struct processed_packet *prev;
|
|
+ enum packet_type packet_type;
|
|
+ struct in_addr ip;
|
|
+ int packet_id;
|
|
+};
|
|
+
|
|
+/****************************************************************************
|
|
+ Have we seen this before ?
|
|
+***************************************************************************/
|
|
+
|
|
+static bool is_processed_packet(struct processed_packet *processed_packet_list,
|
|
+ struct packet_struct *packet)
|
|
+{
|
|
+ struct processed_packet *p = NULL;
|
|
+
|
|
+ for (p = processed_packet_list; p; p = p->next) {
|
|
+ if (ip_equal_v4(p->ip, packet->ip) && p->packet_type == packet->packet_type) {
|
|
+ if ((p->packet_type == NMB_PACKET) &&
|
|
+ (p->packet_id ==
|
|
+ packet->packet.nmb.header.name_trn_id)) {
|
|
+ return true;
|
|
+ } else if ((p->packet_type == DGRAM_PACKET) &&
|
|
+ (p->packet_id ==
|
|
+ packet->packet.dgram.header.dgm_id)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/****************************************************************************
|
|
+ Keep a list of what we've seen before.
|
|
+***************************************************************************/
|
|
+
|
|
+static bool store_processed_packet(struct processed_packet **pp_processed_packet_list,
|
|
+ struct packet_struct *packet)
|
|
+{
|
|
+ struct processed_packet *p = SMB_MALLOC_P(struct processed_packet);
|
|
+ if (!p) {
|
|
+ return false;
|
|
+ }
|
|
+ p->packet_type = packet->packet_type;
|
|
+ p->ip = packet->ip;
|
|
+ if (packet->packet_type == NMB_PACKET) {
|
|
+ p->packet_id = packet->packet.nmb.header.name_trn_id;
|
|
+ } else if (packet->packet_type == DGRAM_PACKET) {
|
|
+ p->packet_id = packet->packet.dgram.header.dgm_id;
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ DLIST_ADD(*pp_processed_packet_list, p);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/****************************************************************************
|
|
+ Throw away what we've seen before.
|
|
+***************************************************************************/
|
|
+
|
|
+static void free_processed_packet_list(struct processed_packet **pp_processed_packet_list)
|
|
+{
|
|
+ struct processed_packet *p = NULL, *next = NULL;
|
|
+
|
|
+ for (p = *pp_processed_packet_list; p; p = next) {
|
|
+ next = p->next;
|
|
+ DLIST_REMOVE(*pp_processed_packet_list, p);
|
|
+ SAFE_FREE(p);
|
|
+ }
|
|
+}
|
|
+
|
|
+/****************************************************************************
|
|
Listens for NMB or DGRAM packets, and queues them.
|
|
return True if the socket is dead
|
|
***************************************************************************/
|
|
@@ -1812,6 +1889,7 @@ bool listen_for_packets(bool run_election)
|
|
#ifndef SYNC_DNS
|
|
int dns_fd;
|
|
#endif
|
|
+ struct processed_packet *processed_packet_list = NULL;
|
|
|
|
if(listen_set == NULL || rescan_listen_set) {
|
|
if(create_listen_fdset(&listen_set, &sock_array, &listen_number, &maxfd)) {
|
|
@@ -1934,6 +2012,16 @@ bool listen_for_packets(bool run_election)
|
|
}
|
|
}
|
|
|
|
+
|
|
+ if (is_processed_packet(processed_packet_list, packet)) {
|
|
+ DEBUG(7,("discarding duplicate packet from %s:%d\n",
|
|
+ inet_ntoa(packet->ip),packet->port));
|
|
+ free_packet(packet);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ store_processed_packet(&processed_packet_list, packet);
|
|
+
|
|
/*
|
|
* 0,2,4,... are unicast sockets
|
|
* 1,3,5,... are broadcast sockets
|
|
@@ -1954,6 +2042,7 @@ bool listen_for_packets(bool run_election)
|
|
queue_packet(packet);
|
|
}
|
|
|
|
+ free_processed_packet_list(&processed_packet_list);
|
|
return False;
|
|
}
|
|
|
|
--
|
|
1.7.6
|
|
|
|
From 179e63ae9aa93984ea3d237c1039460c5acf01a5 Mon Sep 17 00:00:00 2001
|
|
From: Michael Adam <obnox@samba.org>
|
|
Date: Thu, 14 Jan 2010 14:24:35 +0100
|
|
Subject: [PATCH] s3:auth: fix account unlock regression introduced with fix for bug #4347
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=utf-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
By an oversight, the patchset for #4347 made the unlocking of a locked
|
|
account after the lockout duration ineffective.
|
|
Thanks to Björn for finding this!
|
|
|
|
Michael
|
|
---
|
|
source3/auth/auth_sam.c | 12 +++++-------
|
|
1 files changed, 5 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
|
|
index 1dd8fc9..01b2517 100644
|
|
--- a/source3/auth/auth_sam.c
|
|
+++ b/source3/auth/auth_sam.c
|
|
@@ -369,7 +369,6 @@ 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;
|
|
@@ -399,22 +398,21 @@ 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 (acct_ctrl & ACB_NORMAL)
|
|
+ if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL)
|
|
pdb_update_autolock_flag(sampass, &updated_autolock);
|
|
/* Quit if the account was locked out. */
|
|
- if (acct_ctrl & ACB_AUTOLOCK) {
|
|
+ if (pdb_get_acct_ctrl(sampass) & 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,
|
|
- username, acct_ctrl, lm_pw, nt_pw,
|
|
+ username, pdb_get_acct_ctrl(sampass), lm_pw, nt_pw,
|
|
user_info, &user_sess_key, &lm_sess_key);
|
|
|
|
/* Notify passdb backend of login success/failure. If not
|
|
@@ -426,7 +424,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
|
|
bool increment_bad_pw_count = false;
|
|
|
|
if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) &&
|
|
- acct_ctrl & ACB_NORMAL &&
|
|
+ pdb_get_acct_ctrl(sampass) & ACB_NORMAL &&
|
|
NT_STATUS_IS_OK(update_login_attempts_status))
|
|
{
|
|
increment_bad_pw_count =
|
|
@@ -457,7 +455,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
|
|
goto done;
|
|
}
|
|
|
|
- if ((acct_ctrl & ACB_NORMAL) &&
|
|
+ if ((pdb_get_acct_ctrl(sampass) & 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);
|
|
--
|
|
1.6.3.3
|
|
|