Skip to content

Commit

Permalink
libpam: Block sshd's INCORRECT password to AAA server (#10029)
Browse files Browse the repository at this point in the history
Why I did it
sshd overrides user password with a bad one, when pre-auth fails.
Refer PR #9123 for more details

How I did it
Manual cherry pick of PR #9123

How to verify it
Pick a user alias that has not logged into the switch yet
Add this alias to /etc/tacplus_user
Attempt to login as that user
Look for the error message in /var/log/syslog
e.g. "Feb 18 19:16:41.592191 sonic ERR sshd[5233]: auth fail: Password incorrect. user: user_xyz"
  • Loading branch information
renukamanavalan authored Feb 19, 2022
1 parent 7910108 commit ca7d730
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
115 changes: 115 additions & 0 deletions src/tacacs/pam/0006-handle-bad-password-set-by-sshd.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
From 854d3f9cae530cea6b4c12481759bd5cb139259f Mon Sep 17 00:00:00 2001
From: Renuka Manavalan <[email protected]>
Date: Fri, 18 Feb 2022 18:34:03 +0000
Subject: [PATCH] handle bad password set by sshd

---
pam_tacplus.c | 7 +++++++
support.c | 37 +++++++++++++++++++++++++++++++++++++
support.h | 1 +
tacc.c | 4 ++--
4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/pam_tacplus.c b/pam_tacplus.c
index 38e2a70..bf06519 100644
--- a/pam_tacplus.c
+++ b/pam_tacplus.c
@@ -251,6 +251,13 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags,
return PAM_CRED_INSUFFICIENT;
}

+ if (validate_not_sshd_bad_pass(pass) != PAM_SUCCESS) {
+ syslog(LOG_LOCAL0|LOG_ERR, "auth fail: Password incorrect. user: %s", user);
+ memset(pass, 0, strlen (pass));
+ free(pass);
+ return PAM_AUTH_ERR;
+ }
+
retval = pam_set_item (pamh, PAM_AUTHTOK, pass);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_ERR, "unable to set password");
diff --git a/support.c b/support.c
index 7c00618..a34d061 100644
--- a/support.c
+++ b/support.c
@@ -106,6 +106,43 @@ int converse(pam_handle_t * pamh, int nargs, const struct pam_message *message,
return retval;
}

+/*
+ * Ref: From <https://groups.google.com/g/mailing.unix.openssh-dev/c/ViHvtciKYh0>
+ * For future archive searchers:
+ * > Why does OpenSSH replaces the password entered by the user with the
+ * > bad password - "\b\n\r\177INCORRECT
+ *
+ * There are some situations where sshd determines a user can't log in.
+ * Typical samples of that are DenyUsers or PermitRootLogin.
+ * In those cases sshd *still* calls PAM, so that delays set by it are
+ * still performed to the user (without leaking info about accounts
+ * existing, disabled, etc.). But in order to ensure it can't succeed,
+ * replaces the password with that impossible one.
+ *
+ */
+int validate_not_sshd_bad_pass(const char *pass)
+{
+ const char *SSHD_BAD_PASS = "\010\012\015\177INCORRECT";
+ const int SSHD_BAD_PASS_LEN = strlen(SSHD_BAD_PASS);
+
+ int len = strlen(pass);
+ const char *p = pass;
+
+ if (len == 0)
+ return PAM_SUCCESS;
+
+ while (len > 0) {
+ int l = len < SSHD_BAD_PASS_LEN ? len : SSHD_BAD_PASS_LEN;
+
+ if (strncmp(p, SSHD_BAD_PASS, l) != 0)
+ return PAM_SUCCESS;
+
+ len -= l;
+ p += l;
+ }
+ return PAM_AUTH_ERR;
+}
+
/* stolen from pam_stress */
int tacacs_get_password (pam_handle_t * pamh, int flags
,int ctrl, char **password) {
diff --git a/support.h b/support.h
index 9cbd040..d7845d3 100644
--- a/support.h
+++ b/support.h
@@ -41,6 +41,7 @@ extern char tac_prompt[64];
int _pam_parse (int, const char **);
unsigned long _resolve_name (char *);
unsigned long _getserveraddr (char *serv);
+int validate_not_sshd_bad_pass(const char *pass);
int tacacs_get_password (pam_handle_t *, int, int, char **);
int converse (pam_handle_t *, int, const struct pam_message *, struct pam_response **);
void _pam_log (int, const char *, ...);
diff --git a/tacc.c b/tacc.c
index fcc7d8c..bf0f2a3 100644
--- a/tacc.c
+++ b/tacc.c
@@ -181,7 +181,7 @@ int main(int argc, char **argv) {
break;
case 'L':
// tac_login is a global variable initialized in libtac
- bzero(tac_login, sizeof(tac_login));
+ memset(tac_login, 0, sizeof(tac_login));
strncpy(tac_login, optarg, sizeof(tac_login) - 1);
break;
case 'p':
@@ -312,7 +312,7 @@ int main(int argc, char **argv) {
}

/* we no longer need the password in our address space */
- bzero(pass, strlen(pass));
+ memset(pass, 0, strlen(pass));
pass = NULL;

if (do_account) {
--
2.17.1

1 change: 1 addition & 0 deletions src/tacacs/pam/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
git apply ../0003-Obfuscate-key-before-printing-to-syslog.patch
git apply ../0004-management-vrf-support.patch
git apply ../0005-pam-Modify-parsing-of-IP-address-and-port-number-to-.patch
git apply ../0006-handle-bad-password-set-by-sshd.patch

dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR)
popd
Expand Down

0 comments on commit ca7d730

Please sign in to comment.