[Freeipa-devel] [PATCH 0034] Deny LDAP binds for user accounts with expired principal

Simo Sorce simo at redhat.com
Thu Mar 27 14:35:39 UTC 2014


this need rebasing due to OTP patches, however comments inline.

On Tue, 2014-01-07 at 13:47 +0100, Tomas Babej wrote:
> diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
> b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
> index
> ef37b5e173359f9404b241c12d8a6dc6e77da128..df74a671c219f9b4aaa407f2ebd68f41669817b4 100644
> --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
> +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
> @@ -1389,13 +1389,17 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
>      Slapi_Value *value = NULL;
>      Slapi_Attr *attr = NULL;
>      struct tm expire_tm;
> +    time_t current_time;
> +    time_t expire_time;
>      char *errMesg = "Internal operations error\n"; /* error message
> */
>      char *expire = NULL; /* passwordExpirationTime attribute value */
> +    char *principal_expire = NULL; /* krbPrincipalExpiration
> attribute value */
>      char *dn = NULL; /* bind DN */
>      Slapi_Value *objectclass;
>      int method; /* authentication method */
>      int ret = 0;
>      char *principal = NULL;
> +    bool auth_failed = false;
>  
>      LOG_TRACE("=>\n");
>  
> @@ -1422,7 +1426,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
>      const char *attrs_list[] = {SLAPI_USERPWD_ATTR,
> "krbprincipalkey", "uid",
>                                  "krbprincipalname", "objectclass",
>                                  "passwordexpirationtime",
> "passwordhistory",
> -                                NULL};
> +                                "krbprincipalexpiration", NULL};
>  
>      /* retrieve user entry */
>      ret = ipapwd_getEntry(dn, &entry, (char **) attrs_list);
> @@ -1438,6 +1442,39 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
>          goto done;
>      }
>  
> +    /* check the krbPrincipalExpiration attribute is present */
> +    ret = slapi_entry_attr_find(entry, "krbPrincipalExpiration",
> &attr);
> +    if (ret == 0) {
> +        ret = slapi_attr_first_value(attr, &value);
> +
> +        if (ret == 0) {
> +            /* if it is, check whether the principal has not expired
> */
> +            principal_expire = slapi_value_get_string(value);

Why not just use a simpler condition from the start of this very nested
sequence of checks ?
Like:

    /* check the krbPrincipalExpiration attribute is present */
    principal_expire = slapi_entry_attr_get_charptr(entry, "krbPrincipalExpiration")
    if (principal_expire) {
        memset(...

I do not see the value of digging through the attr with that many calls.

> +            memset(&expire_tm, 0, sizeof (expire_tm));
> +
> +            if (strptime(principal_expire, "%Y%m%d%H%M%SZ",
> &expire_tm)) {
> +                expire_time = mktime(&expire_tm);
> +
> +                /* get current time */
> +                current_time = time(NULL);
> +
> +                /* mktime returns -1 if the tm struct cannot be
> represented as
> +                 * as calendar time (seconds since the Epoch). This
> might
> +                 * happen with tm structs that are ill-formated or on
> 32-bit
> +                 * platforms with dates that would cause overflow
> +                 * (year 2038 and later).
> +                 * In such cases, skip the expiration check. */
> +
> +                if (current_time > expire_time && expire_time > 0) {
> +                    LOG_FATAL("kerberos principal in %s is expired
> \n", dn);
> +                    errMesg = "Kerberos principal is expired.";

This message is sent back to the client, perhaps we should say: "Account
is expired", it seem to me a more understandable error for a casual
user/admin.

> +                    auth_failed = true;

Technically no auth was performed also I am not sure why we need a
boolean ?
Just set rc = LDAP_UNWILLING_TO_PERFORM ?


> +                    goto done;
> +                }
> +            }
> +        }
> +    }
> +
>      /* we aren't interested in host principals */
>      objectclass = slapi_value_new_string("ipaHost");
>      if ((slapi_entry_attr_has_syntax_value(entry,
> SLAPI_ATTR_OBJECTCLASS, objectclass)) == 1) {
> @@ -1560,6 +1597,12 @@ done:
>          slapi_entry_free(entry);
>      free_ipapwd_krbcfg(&krbcfg);
>  
> +    if (auth_failed){
> +        slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
> errMesg,

and here:
    if (rc != LDAP_SUCCESS) {
        slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);

> +                               0, NULL);
> +        return -1;
> +    }
> +
>      return 0;
>  } 

HTH,
Simo.

-- 
Simo Sorce * Red Hat, Inc * New York




More information about the Freeipa-devel mailing list