Parcourir la source

Fix gh-2549 Add pwd expiry column to ECLWatch users screen

In ECLWatch 'users' screen, only visible to an admin, add a
"Password Expiration" column that shows the user's password expiration
date, or "Expired" or "Never"

Signed-off-by: William Whitehead <william.whitehead@lexisnexis.com>
William Whitehead il y a 13 ans
Parent
commit
5c4ac319c4

+ 7 - 2
esp/eclwatch/ws_XSLT/access_users.xslt

@@ -131,8 +131,9 @@
                 <colgroup>
                     <col width="5"/>
                     <col width="150"/>
-                    <col width="200"/>
-                    <col width="250"/>
+                    <col width="175"/>
+                    <col width="100"/>
+                    <col width="300"/>
                 </colgroup>
                 <thead>
                 <tr class="grey">
@@ -144,6 +145,7 @@
                 </th>
                 <th align="left">User ID</th>
                 <th>Full Name</th>
+                <th>Password Expires</th>
                 <th>Operation</th>
                 </tr>
                 </thead>
@@ -213,6 +215,9 @@
         <xsl:value-of select="fullname"/>
         </td>
         <td>
+        <xsl:value-of select="passwordexpiration"/>
+        </td>
+        <td>
             <a href="javascript:go('/ws_access/UserInfoEditInput?username={username}')">Edit</a>
             <xsl:text disable-output-escaping="yes"> </xsl:text>
             <a href="javascript:go('/ws_access/UserEdit?username={username}')">MemberOf</a>

+ 2 - 1
esp/scm/ws_access.ecm

@@ -20,6 +20,7 @@ ESPstruct UserInfo
 {
     string username;
     string fullname;
+    [min_ver("1.07")] string passwordexpiration;
 };
 
 ESPstruct GroupInfo
@@ -647,7 +648,7 @@ ESPresponse [nil_remove] UserAccountExportResponse
 };
 
 
-ESPservice [version("1.06"), default_client_version("1.06"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
+ESPservice [version("1.07"), default_client_version("1.07"), exceptions_inline("./smc_xslt/exceptions.xslt")] ws_access
 {
     ESPmethod [client_xslt("/esp/xslt/access_users.xslt")] Users(UserRequest, UserResponse);
     ESPmethod [client_xslt("/esp/xslt/access_useredit.xslt")] UserEdit(UserEditRequest, UserEditResponse);

+ 23 - 0
esp/services/ws_access/ws_accessService.cpp

@@ -414,6 +414,29 @@ bool Cws_accessEx::onUsers(IEspContext &context, IEspUserRequest &req, IEspUserR
                 Owned<IEspUserInfo> oneusr = createUserInfo();
                 oneusr->setUsername(usr->getName());
                 oneusr->setFullname(usr->getFullName());
+
+                double version = context.getClientVersion();
+                if (version >= 1.07)
+                {
+                    StringBuffer sb;
+                    switch (usr->getPasswordDaysRemaining())//-1 if expired, -2 if never expires
+                    {
+                    case -1:
+                        sb.set("Expired");
+                        break;
+                    case -2:
+                        sb.set("Never");
+                        break;
+                    default:
+                        {
+                            CDateTime dt;
+                            usr->getPasswordExpiration(dt);
+                            dt.getDateString(sb);
+                            break;
+                        }
+                    }
+                    oneusr->setPasswordexpiration(sb.str());
+                }
                 espusers.append(*oneusr.getLink());
             }
         }

+ 1 - 1
esp/services/ws_account/ws_accountService.cpp

@@ -165,7 +165,7 @@ bool Cws_accountEx::onMyAccount(IEspContext &context, IEspMyAccountRequest &req,
             else
             {
                 dt.getString(sb);
-                sb.replace('T', (char)' ');
+                sb.replace('T', (char)0);//chop off timestring
             }
             resp.setPasswordExpiration(sb.str());
             resp.setPasswordDaysRemaining(user->getPasswordDaysRemaining());

+ 56 - 33
system/security/LdapSecurity/ldapconnection.cpp

@@ -887,7 +887,9 @@ private:
     //int                  m_defaultWorkunitScopePermission;
     Owned<CLdapConfig>   m_ldapconfig;
     StringBuffer         m_pwscheme;
-    bool                 m_passwordNeverExpires;
+    bool                 m_domainPwdsNeverExpire;//no domain policy for password expiration
+    __int64              m_maxPwdAge;
+
     class CLDAPMessage
     {
     public:
@@ -992,6 +994,16 @@ public:
         return maxAge;
     }
 
+    void calcPWExpiry(CDateTime &dt, unsigned len, char * val)
+    {
+        __int64 time = 0;
+        for (unsigned x=0; x < len; x++)
+            time = time * 10 + ( (int)val[x] - '0');
+        time += m_maxPwdAge;
+        dt.setFromFILETIME(time);
+        dt.adjustTime(dt.queryUtcToLocalDelta());
+    }
+
     virtual bool authenticate(ISecUser& user)
     {
         {
@@ -1005,11 +1017,11 @@ public:
             if(!username || !*username || !password || !*password)
                 return false;
 
-            __int64 maxPWAge = getMaxPwdAge();
-            if (maxPWAge != (__int64)0x8000000000000000)
-                m_passwordNeverExpires = false;
+            m_maxPwdAge = getMaxPwdAge();
+            if (m_maxPwdAge != (__int64)0x8000000000000000)
+                m_domainPwdsNeverExpire = false;
             else
-                m_passwordNeverExpires = true;
+                m_domainPwdsNeverExpire = true;
 
             const char* sysuser = m_ldapconfig->getSysUser();
             if(sysuser && *sysuser && (strcmp(username, sysuser) == 0))
@@ -1087,7 +1099,7 @@ public:
                 DBGLOG("LDAP: Can't find entry for user %s", username);
                 return false;
             }
-
+            bool accountPwdNeverExpires = false;
             for ( attribute = ldap_first_attribute(sys_ld, searchResult, &ber ); attribute != NULL; attribute = ldap_next_attribute(sys_ld, searchResult, ber))
             {
                 if((stricmp(attribute, "cn") == 0) && (values = ldap_get_values(sys_ld, entry, attribute)) != NULL )
@@ -1112,7 +1124,7 @@ public:
                 {
                     //UF_DONT_EXPIRE_PASSWD 0x10000
                     if (atoi((char*)values[0]) & 0x10000)//this can be true at the account level, even if domain policy requires password
-                        m_passwordNeverExpires = true;
+                        accountPwdNeverExpires = true;
                     ldap_value_free( values );
                 }
                 else if((stricmp(attribute, "pwdLastSet") == 0) && (bvalues = ldap_get_values_len(sys_ld, entry, attribute)) != NULL )
@@ -1123,36 +1135,19 @@ public:
                       to 0 and the User-Account-Control attribute does not contain the UF_DONT_EXPIRE_PASSWD
                       flag, then the user must set the password at the next logon.
                       */
-                    if (!m_passwordNeverExpires)
+                    CDateTime expiry;
+                    if (!m_domainPwdsNeverExpire && !accountPwdNeverExpires)
                     {
-                        CDateTime expiry;
                         struct berval* val = bvalues[0];
-                        if(val != NULL)
-                        {
-                            __int64 time = 0;
-                            for (int x=0; x < (int)val->bv_len; x++)
-                                time = time * 10 + ( (int)val->bv_val[x] - '0');
-                            ldap_value_free_len(bvalues);
-
-                            time += maxPWAge;
-                            expiry.setFromFILETIME(time);
-                            expiry.adjustTime(expiry.queryUtcToLocalDelta());
-                            user.setPasswordExpiration(expiry);
-                        }
-                        else
-                        {
-                            DBGLOG("LDAP: Can't find entry for %s pwdLastSet", username);
-                            return false;
-                        }
+                        calcPWExpiry(expiry, (unsigned)val->bv_len, val->bv_val);
+                        ldap_value_free_len(bvalues);
                     }
                     else
                     {
-                        CDateTime never;
-                        never.clear();
-                        assertex(never.isNull());
-                        user.setPasswordExpiration(never);
+                        expiry.clear();
                         DBGLOG("LDAP: Password never expires for user %s", username);
                     }
+                    user.setPasswordExpiration(expiry);
                 }
             }
             ber_free(ber, 0);
@@ -1983,10 +1978,9 @@ public:
             filter.appendf(")(|(%s=*%s*)(%s=*%s*)(%s=*%s*)))", act_fieldname, searchstr, "givenName", searchstr, "sn", searchstr);
         }
 
-        char        *attrs[] = {act_fieldname, sid_fieldname, "cn", NULL};
+        char *attrs[] = {act_fieldname, sid_fieldname, "cn", "userAccountControl", "pwdLastSet", NULL};
         CLDAPMessage searchResult;
         int rc = ldap_search_ext_s(ld, (char*)m_ldapconfig->getUserBasedn(), LDAP_SCOPE_SUBTREE, (char*)filter.str(), attrs, 0, NULL, NULL, &timeOut, LDAP_NO_LIMIT,    &searchResult.msg );
-
         if ( rc != LDAP_SUCCESS )
         {
             DBGLOG("ldap_search_ext_s error: %s, when searching %s under %s", ldap_err2string( rc ), filter.str(), m_ldapconfig->getUserBasedn());
@@ -1997,6 +1991,7 @@ public:
         // Go through the search results by checking message types
         for(message = LdapFirstEntry( ld, searchResult); message != NULL; message = ldap_next_entry(ld, message))
         {
+            bool accountPwdNeverExpires = false;
             Owned<ISecUser> user = new CLdapSecUser("", "");
             for ( attribute = ldap_first_attribute( ld,searchResult,&ber );
                 attribute != NULL; 
@@ -2013,6 +2008,34 @@ public:
                         ldap_value_free( values );
                     }
                 }
+                else if (stricmp(attribute, "userAccountControl") == 0)
+                {
+                    if ((values = ldap_get_values( ld, message, attribute))
+                        != NULL )
+                    {
+                        //UF_DONT_EXPIRE_PASSWD 0x10000
+                        if (atoi((char*)values[0]) & 0x10000)//this can be true at the account level, even if domain policy requires password
+                            accountPwdNeverExpires = true;
+                        ldap_value_free( values );
+                    }
+                }
+                else if(stricmp(attribute, "pwdLastSet") == 0)
+                {
+                    CDateTime expiry;
+                    if (!m_domainPwdsNeverExpire && !accountPwdNeverExpires)
+                    {
+                        if ((bvalues = ldap_get_values_len(ld, message, attribute))
+                            != NULL )
+                        {
+                            struct berval* val = bvalues[0];
+                            calcPWExpiry(expiry, (unsigned)val->bv_len, val->bv_val);
+                            ldap_value_free_len(bvalues);
+                        }
+                    }
+                    else
+                        expiry.clear();
+                    user->setPasswordExpiration(expiry);
+                }
                 else if(stricmp(attribute, act_fieldname) == 0)
                 {
                     if (( values = ldap_get_values( ld, message, attribute)) 
@@ -4822,7 +4845,7 @@ private:
         act_ctrl_val &= 0xFFFFFFFD;
 #ifdef _DONT_EXPIRE_PASSWORD
         // UF_DONT_EXPIRE_PASSWD 0x10000
-        if (m_passwordNeverExpires)
+        if (m_domainPwdsNeverExpire)
             act_ctrl_val |= 0x10000;
 #endif