On 01/07/2014 01:47 PM, Tomas Babej wrote: > > On 01/07/2014 07:23 AM, Alexander Bokovoy wrote: >> On Mon, 06 Jan 2014, Tomas Babej wrote: >>> >>> On 01/06/2014 12:16 PM, Tomas Babej wrote: >>>> On 04/15/2013 12:43 PM, Tomas Babej wrote: >>>>> On 04/08/2013 03:55 PM, Martin Kosek wrote: >>>>>> On 04/01/2013 09:52 PM, Rob Crittenden wrote: >>>>>>> Tomas Babej wrote: >>>>>>>> On 02/12/2013 06:23 PM, Simo Sorce wrote: >>>>>>>>> On Tue, 2013-02-12 at 18:03 +0100, Tomas Babej wrote: >>>>>>>>>> On 02/12/2013 05:50 PM, Tomas Babej wrote: >>>>>>>>>>> Hi, >>>>>>>>>>> >>>>>>>>>>> This patch adds a check for krbprincipalexpiration attribute to >>>>>>>>>>> pre_bind operation >>>>>>>>>>> in ipa-pwd-extop dirsrv plugin. If the principal is expired, >>>>>>>>>>> auth is >>>>>>>>>>> denied and LDAP_INVALID_CREDENTIALS along with the error >>>>>>>>>>> message is >>>>>>>>>>> sent back to the client. Since krbprincipalexpiration >>>>>>>>>>> attribute is >>>>>>>>>> not >>>>>>>>>>> mandatory, if there is no value set, the check is passed. >>>>>>>>>>> >>>>>>>>>>> https://fedorahosted.org/freeipa/ticket/3305 >>>>>>>>> Comments inline. >>>>>>>>>> @@ -1166,6 +1173,29 @@ 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) { >>>>>>>>> ret is not a boolean so probably better ti use (ret != 0) >>>>>>>>> >>>>>>>>>> + /* if it is, check whether the principal has not >>>>>>>>>> expired */ >>>>>>>>>> + >>>>>>>>>> + principal_expire = slapi_entry_attr_get_charptr(entry, >>>>>>>>>> + "krbprincipalexpiration"); >>>>>>>>>> + memset(&expire_tm, 0, sizeof (expire_tm)); >>>>>>>>>> + >>>>>>>>>> + if (strptime(principal_expire, "%Y%m%d%H%M%SZ", >>>>>>>>>> &expire_tm)){ >>>>>>>>> style issue missing space between ) and { >>>>>>>>> >>>>>>>>>> + expire_time = mktime(&expire_tm); >>>>>>>>>> + /* this might have overflown on 32-bit system */ >>>>>>>>> This comment does not help to point out what you want to put in >>>>>>>>> evidence. >>>>>>>>> if there is an overflow what is the consequence ? Or does it >>>>>>>>> mean the >>>>>>>>> next condition is taking that into account ? >>>>>>>> Yeah, this was rather ill-worded. Replaced by a rather verbose >>>>>>>> comment that hopefully clears things out. >>>>>>>>>> + if (current_time > expire_time && expire_time > 0){ >>>>>>>>> style issue missing space between ) and { >>>>>>>>> >>>>>>>>>> + LOG_FATAL("kerberos principal has expired in >>>>>>>>>> user >>>>>>>>>> entry: %s\n", >>>>>>>>>> + dn); >>>>>>>>> I think a better phrasing would be: "The kerberos principal on >>>>>>>>> %s is >>>>>>>>> expired\n" >>>>>>>>> >>>>>>>>>> + errMesg = "Kerberos principal has expired."; >>>>>>>>> s/has/is/ >>>>>>>>> >>>>>>>>> The rest looks good to me. >>>>>>>>> >>>>>>>>> Simo. >>>>>>>> Styling issues fixed and updated patch attached :) >>>>>>> Small nit, the expiration error should probably use 'in' not 'on'. >>>>>>> >>>>>>> I'm not sure LDAP_INVALID_CREDENTIALS is the right return code. This >>>>>>> implies >>>>>>> that the password is wrong. I think that LDAP_UNWILLING_TO_PERFORM >>>>>>> is probably >>>>>>> more correct here. It is what we return on other policy failures. >>>>>>> >>>>>>> rob >>>>>>> >>>>>> Additional findings: >>>>>> >>>>>> 1) Lets not try to get current_time every time, but only when its >>>>>> needed (i.e. >>>>>> krbPrincipalExpiration is set) - AFAIK, it is not so cheap operation: >>>>>> >>>>>> + /* get current time*/ >>>>>> + current_time = time(NULL); >>>>>> >>>>>> 2) Why using slapi_entry_attr_get_charptr and thus let 389-ds find >>>>>> the >>>>>> attribute again when we already have a pointer for the attribute? >>>>>> Would >>>>>> slapi_attr_first_value following slapi_entry_attr_find be faster >>>>>> approach? >>>>>> >>>>>> + ret = slapi_entry_attr_find(entry, "krbPrincipalExpiration", >>>>>> &attr); >>>>>> + if (ret != 0) { >>>>>> + /* if it is, check whether the principal has not expired */ >>>>>> + >>>>>> + principal_expire = slapi_entry_attr_get_charptr(entry, >>>>>> + "krbprincipalexpiration"); >>>>>> >>>>>> This way, we would not create a copy of this attribute value - we do >>>>>> not need a >>>>>> copy, we just do check against it. >>>>>> >>>>>> >>>>>> 3) Shouldn't we return -1 in the end when the auth fails? We do that >>>>>> in other >>>>>> pre_callbacks. Otherwise we just return 0 (success): >>>>>> >>>>>> + if (auth_failed){ >>>>>> + slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, >>>>>> errMesg, >>>>>> + 0, NULL); >>>>>> + } >>>>>> + >>>>>> return 0; >>>>>> >>>>>> Martin >>>>> Thank you both for the review. I updated and retested the patch, with >>>>> your suggestions incorporated. >>>>> >>>>> Tomas >>>>> >>>> I rebased the patch on top of current master. >>>> >>>> Bumping, since this is planned as part of 3.4 (and there were some >>>> requests for this feature). >>>> >>>> Tomas >>>> >>> >>> I updated the commit message to reflect better what the current version >>> of the patch implements. >>> >>> Tomas >> >>>> From a93d1ec3ca8c7b6e8e754b474257695ba9018e07 Mon Sep 17 00:00:00 2001 >>> From: Tomas Babej <tba...@redhat.com> >>> Date: Mon, 6 Jan 2014 12:11:24 +0100 >>> Subject: [PATCH] ipa-pwd-extop: Deny LDAP binds for user accounts >>> with expired >>> principal >>> >>> Adds a check for krbprincipalexpiration attribute to pre_bind operation >>> in ipa-pwd-extop dirsrv plugin. If the principal is expired, auth is >>> denied and LDAP_UNWILLING_TO_PERFORM along with the error message is >>> sent back to the client. Since krbprincipalexpiration attribute is not >>> mandatory, if there is no value set, the check is passed. >>> >>> https://fedorahosted.org/freeipa/ticket/3305 >>> --- >>> daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 45 >>> ++++++++++++++++++++++- >>> 1 file changed, 44 insertions(+), 1 deletion(-) >>> >>> diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c >>> b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c >>> index >>> ef37b5e173359f9404b241c12d8a6dc6e77da128..568cba7189d1575d030b043daee61f713e9bac5f >>> 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); >>> + 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."; >>> + auth_failed = true; >>> + goto done; >>> + } >>> + } >> I think indenting is broken for these two brackets. >> >> > > Thanks Alexander, fixed. > > Updated version attached. > > Tomas >
Simo, Alexander - are you know OK with Tomas' patch? The patch review is now taking more than a year, so I think it would be great to finish it :) Martin _______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel