66static const char * g_etcPamdCommonPassword = "/etc/pam.d/common-password" ;
77static const char * g_etcSecurityPwQualityConf = "/etc/security/pwquality.conf" ;
88static const char * g_etcPamdSystemAuth = "/etc/pam.d/system-auth" ;
9+ static const char * g_pamUnixSo = "pam_unix.so" ;
910static const char * g_remember = "remember" ;
1011
11- int CheckEnsurePasswordReuseIsLimited (int remember , char * * reason , void * log )
12- {
13- int status = ENOENT ;
14-
15- if (0 == CheckFileExists (g_etcPamdCommonPassword , NULL , log ))
16- {
17- // On Debian-based systems '/etc/pam.d/common-password' is expected to exist
18- status = ((0 == CheckLineFoundNotCommentedOut (g_etcPamdCommonPassword , '#' , g_remember , NULL , log )) &&
19- (0 == CheckIntegerOptionFromFileLessOrEqualWith (g_etcPamdCommonPassword , g_remember , '=' , remember , reason , log ))) ? 0 : ENOENT ;
20- }
21- else if (0 == CheckFileExists (g_etcPamdSystemAuth , NULL , log ))
22- {
23- // On Red Hat-based systems '/etc/pam.d/system-auth' is expected to exist
24- status = ((0 == CheckLineFoundNotCommentedOut (g_etcPamdSystemAuth , '#' , g_remember , NULL , log )) &&
25- (0 == CheckIntegerOptionFromFileLessOrEqualWith (g_etcPamdSystemAuth , g_remember , '=' , remember , reason , log ))) ? 0 : ENOENT ;
26- }
27- else
28- {
29- OsConfigCaptureReason (reason , "Neither '%s' or '%s' found, unable to check for '%s' option being set" ,
30- g_etcPamdCommonPassword , g_etcPamdSystemAuth , g_remember );
31- }
32-
33- return status ;
34- }
35-
3612static char * FindPamModule (const char * pamModule , void * log )
3713{
38- const char * paths [] = {"/usr/lib/x86_64-linux-gnu/security/%s" , "/lib/security/%s" , "/usr/lib/security/%s" , "/lib64/security/%s" };
14+ const char * paths [] = {
15+ "/usr/lib/x86_64-linux-gnu/security/%s" ,
16+ "/usr/lib/security/%s" ,
17+ "/lib/security/%s" ,
18+ "/lib64/security/%s" ,
19+ "/lib/x86_64-linux-gnu/security/%s" };
3920 int numPaths = ARRAY_SIZE (paths );
4021 char * result = NULL ;
4122 int status = 0 , i = 0 ;
@@ -78,6 +59,36 @@ static char* FindPamModule(const char* pamModule, void* log)
7859 return result ;
7960}
8061
62+ int CheckEnsurePasswordReuseIsLimited (int remember , char * * reason , void * log )
63+ {
64+ int status = ENOENT ;
65+
66+ if (0 == CheckFileExists (g_etcPamdCommonPassword , NULL , log ))
67+ {
68+ // On Debian-based systems '/etc/pam.d/common-password' is expected to exist
69+ status = ((0 == CheckLineFoundNotCommentedOut (g_etcPamdCommonPassword , '#' , g_remember , NULL , log )) &&
70+ (0 == CheckIntegerOptionFromFileLessOrEqualWith (g_etcPamdCommonPassword , g_remember , '=' , remember , reason , log ))) ? 0 : ENOENT ;
71+ }
72+ else if (0 == CheckFileExists (g_etcPamdSystemAuth , NULL , log ))
73+ {
74+ // On Red Hat-based systems '/etc/pam.d/system-auth' is expected to exist
75+ status = ((0 == CheckLineFoundNotCommentedOut (g_etcPamdSystemAuth , '#' , g_remember , NULL , log )) &&
76+ (0 == CheckIntegerOptionFromFileLessOrEqualWith (g_etcPamdSystemAuth , g_remember , '=' , remember , reason , log ))) ? 0 : ENOENT ;
77+ }
78+ else
79+ {
80+ OsConfigCaptureReason (reason , "Neither '%s' or '%s' found, unable to check for '%s' option being set" ,
81+ g_etcPamdCommonPassword , g_etcPamdSystemAuth , g_remember );
82+ }
83+
84+ if (status && (false == FindPamModule (g_pamUnixSo , log )))
85+ {
86+ OsConfigCaptureReason (reason , "The PAM module '%s' is not available. Automatic remediation is not possible" , g_pamUnixSo );
87+ }
88+
89+ return status ;
90+ }
91+
8192static void EnsurePamModulePackagesAreInstalled (void * log )
8293{
8394 const char * pamPackages [] = {"pam" , "libpam-modules" , "pam_pwquality" , "libpam-pwquality" , "libpam-cracklib" };
@@ -112,15 +123,15 @@ int SetEnsurePasswordReuseIsLimited(int remember, void* log)
112123 // While 'required' says that if this module fails, authentication fails.
113124
114125 const char * endsHereIfFailsTemplate = "password required %s sha512 shadow %s=%d retry=3\n" ;
115- const char * pamUnixSo = "pam_unix.so" ;
116126 char * pamModulePath = NULL ;
117127 char * newline = NULL ;
118128 int status = 0 , _status = 0 ;
119129
120130 EnsurePamModulePackagesAreInstalled (log );
121131
122- if (NULL == (pamModulePath = FindPamModule (pamUnixSo , log )))
132+ if (NULL == (pamModulePath = FindPamModule (g_pamUnixSo , log )))
123133 {
134+ OsConfigLogError (log , "SetEnsurePasswordReuseIsLimited: cannot proceed without %s being present" , g_pamUnixSo );
124135 return ENOENT ;
125136 }
126137
@@ -198,8 +209,9 @@ int CheckLockoutForFailedPasswordAttempts(const char* fileName, const char* pamS
198209 {
199210 // Example of valid lines:
200211 //
201- // 'auth required pam_tally2.so onerr=fail audit silent deny=5 unlock_time=900' in /etc/pam.d/login
202- // 'auth required pam_faillock.so preauth silent audit deny=3 unlock_time=900' in /etc/pam.d/system-auth
212+ // 'auth required pam_tally2.so onerr=fail audit silent deny=5 unlock_time=900'
213+ // 'auth required pam_faillock.so preauth silent audit deny=3 unlock_time=900'
214+ // 'auth required pam_tally.so onerr=fail deny=3 unlock_time=900'
203215
204216 if ((commentCharacter == line [0 ]) || (EOL == line [0 ]))
205217 {
@@ -427,7 +439,7 @@ static int CheckRequirementsForCommonPassword(int retry, int minlen, int dcredit
427439 continue ;
428440 }
429441 else if ((NULL != strstr (line , password )) && (NULL != strstr (line , requisite )) &&
430- ((NULL != strstr (line , pamPwQualitySo )) || (NULL != strstr (line , pamCrackLibSo ))))
442+ ((NULL != strstr (line , pamPwQualitySo )) || (NULL != strstr (line , pamCrackLibSo )) || ( NULL != strstr ( line , g_pamUnixSo )) ))
431443 {
432444 found = true;
433445
@@ -745,8 +757,10 @@ int SetPasswordCreationRequirements(int retry, int minlen, int minclass, int dcr
745757 int numEntries = ARRAY_SIZE (entries );
746758 bool pamPwQualitySoExists = false;
747759 bool pamCrackLibSoExists = false;
760+ bool pamUnixSoExists = false;
748761 char * pamModulePath = NULL ;
749762 char * pamModulePath2 = NULL ;
763+ char * pamModulePath3 = NULL ;
750764 int i = 0 , status = 0 , _status = 0 ;
751765 char * line = NULL ;
752766
@@ -756,13 +770,15 @@ int SetPasswordCreationRequirements(int retry, int minlen, int minclass, int dcr
756770
757771 pamPwQualitySoExists = (NULL != (pamModulePath = FindPamModule (pamPwQualitySo , log ))) ? true : false;
758772 pamCrackLibSoExists = (NULL != (pamModulePath2 = FindPamModule (pamCrackLibSo , log ))) ? true : false;
773+ pamUnixSoExists = (NULL != (pamModulePath3 = FindPamModule (g_pamUnixSo , log ))) ? true : false;
759774
760- if (pamPwQualitySoExists || pamCrackLibSoExists )
775+ if (pamPwQualitySoExists || pamCrackLibSoExists || pamUnixSoExists )
761776 {
762- if (NULL != (line = FormatAllocateString (etcPamdCommonPasswordLineTemplate , pamPwQualitySoExists ? pamModulePath : pamModulePath2 ,
777+ if (NULL != (line = FormatAllocateString (etcPamdCommonPasswordLineTemplate ,
778+ pamPwQualitySoExists ? pamModulePath : (pamCrackLibSoExists ? pamModulePath2 : pamModulePath3 ),
763779 retry , minlen , lcredit , ucredit , ocredit , dcredit )))
764780 {
765- status = ReplaceMarkedLinesInFile (g_etcPamdCommonPassword , pamPwQualitySoExists ? pamPwQualitySo : pamCrackLibSo , line , '#' , true, log );
781+ status = ReplaceMarkedLinesInFile (g_etcPamdCommonPassword , pamPwQualitySoExists ? pamPwQualitySo : ( pamCrackLibSoExists ? pamCrackLibSo : g_pamUnixSo ) , line , '#' , true, log );
766782 FREE_MEMORY (line );
767783 }
768784 else
0 commit comments