andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From cb1ef86c225632f7ac2d267a5e3687b156ffc3bf Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Fri, 21 Mar 2014 14:21:13 -0700
dc8c34
Subject: [PATCH 190/225] Ticket #47748 - Simultaneous adding a user and
dc8c34
 binding as the user could fail in the password policy check
dc8c34
dc8c34
Bug description: In do_bind, bind_target_entry is retrieved from the
dc8c34
DB or the entry cache.  There was a small window that the entry failed
dc8c34
to retrieve from there but the bind procedure in the backend (be_bind)
dc8c34
succeeds.  In the case, NULL bind_target_entry is passed to the Pass-
dc8c34
word Policy check and it fails.
dc8c34
dc8c34
Fix description: If be_bind returns SUCCESS and bind_target_entry is
dc8c34
NULL, retrieve bind_target_entry agian, which is guaranteed since the
dc8c34
entry was retrieved in the backend and placed in the entry cache.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/47748
dc8c34
dc8c34
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
dc8c34
(cherry picked from commit 4fc53e1a63222d0ff67c30a59f2cff4b535f90a8)
dc8c34
(cherry picked from commit f8f063c3fb2c7642506cbad923c71972f78edac2)
dc8c34
(cherry picked from commit feed9ba773766ade744ca4d45aca46c91d4b7f4f)
dc8c34
(cherry picked from commit f9b2bec732645bf0d219e790448b191c4652858e)
dc8c34
---
dc8c34
 ldap/servers/slapd/bind.c    | 105 ++++++++++++++++++++++++++-----------------
dc8c34
 ldap/servers/slapd/entry.c   |  18 ++++----
dc8c34
 ldap/servers/slapd/pw_mgmt.c |   3 ++
dc8c34
 3 files changed, 75 insertions(+), 51 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
dc8c34
index ec874cc..97b236e 100644
dc8c34
--- a/ldap/servers/slapd/bind.c
dc8c34
+++ b/ldap/servers/slapd/bind.c
dc8c34
@@ -429,6 +429,7 @@ do_bind( Slapi_PBlock *pb )
dc8c34
         if (!strcasecmp (saslmech, LDAP_SASL_EXTERNAL)) {
dc8c34
             /* call preop plugins */
dc8c34
             if (plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_BIND_FN ) != 0){
dc8c34
+                send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "", 0, NULL);
dc8c34
                 goto free_and_return;
dc8c34
             }
dc8c34
 
dc8c34
@@ -474,10 +475,10 @@ do_bind( Slapi_PBlock *pb )
dc8c34
                 goto free_and_return;
dc8c34
             }
dc8c34
 
dc8c34
-            if (!isroot ) {
dc8c34
+            if (!isroot) {
dc8c34
                 /* check if the account is locked */
dc8c34
                 bind_target_entry = get_entry(pb, pb->pb_conn->c_external_dn);
dc8c34
-                if ( bind_target_entry != NULL && slapi_check_account_lock(pb, bind_target_entry,
dc8c34
+                if ( bind_target_entry && slapi_check_account_lock(pb, bind_target_entry,
dc8c34
                      pw_response_requested, 1 /*check password policy*/, 1 /*send ldap result*/) == 1) {
dc8c34
                     /* call postop plugins */
dc8c34
                     plugin_call_plugins( pb, SLAPI_PLUGIN_POST_BIND_FN );
dc8c34
@@ -553,6 +554,8 @@ do_bind( Slapi_PBlock *pb )
dc8c34
 
dc8c34
                 /* call postop plugins */
dc8c34
                 plugin_call_plugins( pb, SLAPI_PLUGIN_POST_BIND_FN );
dc8c34
+            } else {
dc8c34
+                send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "", 0, NULL);
dc8c34
             }
dc8c34
             goto free_and_return;
dc8c34
         /* Check if unauthenticated binds are allowed. */
dc8c34
@@ -651,7 +654,7 @@ do_bind( Slapi_PBlock *pb )
dc8c34
                 bind_credentials_set( pb->pb_conn, SLAPD_AUTH_SIMPLE, slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
dc8c34
                                       NULL, NULL, NULL , NULL);
dc8c34
             } else {
dc8c34
-            	/*
dc8c34
+                /*
dc8c34
                  *  right dn, wrong passwd - reject with invalid credentials
dc8c34
                  */
dc8c34
                 send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
dc8c34
@@ -675,6 +678,8 @@ do_bind( Slapi_PBlock *pb )
dc8c34
 
dc8c34
             /* call postop plugins */
dc8c34
             plugin_call_plugins( pb, SLAPI_PLUGIN_POST_BIND_FN );
dc8c34
+        } else {
dc8c34
+            send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "", 0, NULL);
dc8c34
         }
dc8c34
         goto free_and_return;
dc8c34
     }
dc8c34
@@ -733,9 +738,10 @@ do_bind( Slapi_PBlock *pb )
dc8c34
                    (rc == SLAPI_BIND_ANONYMOUS))) ) {
dc8c34
                 long t;
dc8c34
                 char* authtype = NULL;
dc8c34
-
dc8c34
-                if(auto_bind)
dc8c34
+                /* rc is SLAPI_BIND_SUCCESS or SLAPI_BIND_ANONYMOUS */
dc8c34
+                if(auto_bind) {
dc8c34
                     rc = SLAPI_BIND_SUCCESS;
dc8c34
+                }
dc8c34
 
dc8c34
                 switch ( method ) {
dc8c34
                 case LDAP_AUTH_SIMPLE:
dc8c34
@@ -755,53 +761,68 @@ do_bind( Slapi_PBlock *pb )
dc8c34
                     /* authtype = SLAPD_AUTH_SASL && saslmech: */
dc8c34
                     PR_snprintf(authtypebuf, sizeof(authtypebuf), "%s%s", SLAPD_AUTH_SASL, saslmech);
dc8c34
                     authtype = authtypebuf;
dc8c34
-                break;
dc8c34
-                default: /* ??? */
dc8c34
+                    break;
dc8c34
+                default:
dc8c34
                     break;
dc8c34
                 }
dc8c34
 
dc8c34
                 if ( rc == SLAPI_BIND_SUCCESS ) {
dc8c34
-                    if(!auto_bind)
dc8c34
-                        bind_credentials_set( pb->pb_conn,
dc8c34
-                                          authtype, slapi_ch_strdup(
dc8c34
-                                              slapi_sdn_get_ndn(sdn)),
dc8c34
-                                          NULL, NULL, NULL, bind_target_entry );
dc8c34
-                    if ( auth_response_requested ) {
dc8c34
-                        slapi_add_auth_response_control( pb,
dc8c34
-                                                   slapi_sdn_get_ndn(sdn));
dc8c34
+                    if (!auto_bind) {
dc8c34
+                        /* 
dc8c34
+                         * There could be a race that bind_target_entry was not added 
dc8c34
+                         * when bind_target_entry was retrieved before be_bind, but it
dc8c34
+                         * was in be_bind.  Since be_bind returned SLAPI_BIND_SUCCESS,
dc8c34
+                         * the entry is in the DS.  So, we need to retrieve it once more.
dc8c34
+                         */
dc8c34
+                        if (!bind_target_entry) {
dc8c34
+                            bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(sdn));
dc8c34
+                            if (bind_target_entry) {
dc8c34
+                                rc = slapi_check_account_lock(pb, bind_target_entry,
dc8c34
+                                                              pw_response_requested, 1, 1);
dc8c34
+                                if (1 == rc) { /* account is locked */
dc8c34
+                                    goto account_locked;
dc8c34
+                                }
dc8c34
+                            } else {
dc8c34
+                                send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, "", 0, NULL);
dc8c34
+                                goto free_and_return;
dc8c34
+                            }
dc8c34
+                        }
dc8c34
+                        bind_credentials_set(pb->pb_conn, authtype,
dc8c34
+                                             slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
dc8c34
+                                             NULL, NULL, NULL, bind_target_entry);
dc8c34
+                        if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
dc8c34
+                            /* check if need new password before sending 
dc8c34
+                               the bind success result */
dc8c34
+                            rc = need_new_pw(pb, &t, bind_target_entry, pw_response_requested);
dc8c34
+                            switch (rc) {
dc8c34
+                            case 1:
dc8c34
+                                (void)slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
dc8c34
+                                break;
dc8c34
+                            case 2:
dc8c34
+                                (void)slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRING, t);
dc8c34
+                                break;
dc8c34
+                            default:
dc8c34
+                                break;
dc8c34
+                            }
dc8c34
+                        }
dc8c34
                     }
dc8c34
+                    if (auth_response_requested) {
dc8c34
+                        slapi_add_auth_response_control(pb, slapi_sdn_get_ndn(sdn));
dc8c34
+                    }
dc8c34
+                    if (-1 == rc) {
dc8c34
+                        /* neeed_new_pw failed; need_new_pw already send_ldap_result in it. */
dc8c34
+                        goto free_and_return;
dc8c34
+                    } 
dc8c34
                 } else {	/* anonymous */
dc8c34
                     /* set bind creds here so anonymous limits are set */
dc8c34
-                    bind_credentials_set( pb->pb_conn, authtype, NULL,
dc8c34
-                                          NULL, NULL, NULL, NULL );
dc8c34
+                    bind_credentials_set(pb->pb_conn, authtype, NULL, NULL, NULL, NULL, NULL);
dc8c34
 
dc8c34
                     if ( auth_response_requested ) {
dc8c34
-                        slapi_add_auth_response_control( pb,
dc8c34
-                                                   "" );
dc8c34
+                        slapi_add_auth_response_control(pb, "");
dc8c34
                     }
dc8c34
                 }
dc8c34
-
dc8c34
-                if ( 0 == auto_bind && (rc != SLAPI_BIND_ANONYMOUS) &&
dc8c34
-                     ! slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
dc8c34
-                    /* check if need new password before sending 
dc8c34
-                       the bind success result */
dc8c34
-                    switch ( need_new_pw (pb, &t, bind_target_entry, pw_response_requested )) {
dc8c34
-                    case 1:
dc8c34
-                        (void)slapi_add_pwd_control ( pb, 
dc8c34
-                                                LDAP_CONTROL_PWEXPIRED, 0);
dc8c34
-                        break;
dc8c34
-                    case 2:
dc8c34
-                        (void)slapi_add_pwd_control ( pb, 
dc8c34
-                                                LDAP_CONTROL_PWEXPIRING, t);
dc8c34
-                        break;
dc8c34
-                    case -1: 
dc8c34
-                        goto free_and_return;
dc8c34
-                    default:
dc8c34
-                        break;
dc8c34
-                    } 
dc8c34
-                } /* end if */
dc8c34
-            }else{
dc8c34
-                
dc8c34
+            } else {
dc8c34
+account_locked:                
dc8c34
                 if(cred.bv_len == 0) {
dc8c34
                     /* its an UnAuthenticated Bind, DN specified but no pw */
dc8c34
                     slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
dc8c34
@@ -837,7 +858,7 @@ do_bind( Slapi_PBlock *pb )
dc8c34
                           "Function not implemented", 0, NULL );
dc8c34
     }
dc8c34
 
dc8c34
- free_and_return:;
dc8c34
+free_and_return:;
dc8c34
     if (be)
dc8c34
         slapi_be_Unlock(be);
dc8c34
     slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &sdn;;
dc8c34
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
dc8c34
index 04bac0d..d9226af 100644
dc8c34
--- a/ldap/servers/slapd/entry.c
dc8c34
+++ b/ldap/servers/slapd/entry.c
dc8c34
@@ -2654,8 +2654,8 @@ slapi_entry_attr_get_charray( const Slapi_Entry* e, const char *type)
dc8c34
 char *
dc8c34
 slapi_entry_attr_get_charptr( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
-    char *p= NULL;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+	char *p= NULL;
dc8c34
+	Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
 	if(attr!=NULL)
dc8c34
 	{
dc8c34
@@ -2674,7 +2674,7 @@ int
dc8c34
 slapi_entry_attr_get_int( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     int r= 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2689,7 +2689,7 @@ unsigned int
dc8c34
 slapi_entry_attr_get_uint( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     unsigned int r= 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2704,7 +2704,7 @@ long
dc8c34
 slapi_entry_attr_get_long( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     long r = 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2719,7 +2719,7 @@ unsigned long
dc8c34
 slapi_entry_attr_get_ulong( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     unsigned long r = 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2734,7 +2734,7 @@ long long
dc8c34
 slapi_entry_attr_get_longlong( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     long long r = 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
     slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2749,7 +2749,7 @@ unsigned long long
dc8c34
 slapi_entry_attr_get_ulonglong( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     unsigned long long r = 0;
dc8c34
-    Slapi_Attr* attr;
dc8c34
+    Slapi_Attr* attr = NULL;
dc8c34
     slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
@@ -2764,7 +2764,7 @@ PRBool
dc8c34
 slapi_entry_attr_get_bool( const Slapi_Entry* e, const char *type)
dc8c34
 {
dc8c34
     PRBool r = PR_FALSE; /* default if no attr */
dc8c34
-    Slapi_Attr* attr;
dc8c34
+	Slapi_Attr* attr = NULL;
dc8c34
 	slapi_entry_attr_find(e, type, &attr);
dc8c34
     if (attr!=NULL)
dc8c34
     {
dc8c34
diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c
dc8c34
index f173128..7a8d390 100644
dc8c34
--- a/ldap/servers/slapd/pw_mgmt.c
dc8c34
+++ b/ldap/servers/slapd/pw_mgmt.c
dc8c34
@@ -68,6 +68,9 @@ need_new_pw( Slapi_PBlock *pb, long *t, Slapi_Entry *e, int pwresponse_req )
dc8c34
 	int	pwdGraceUserTime = 0;
dc8c34
 	char graceUserTime[8];
dc8c34
 
dc8c34
+	if (NULL == e) {
dc8c34
+		return (-1);
dc8c34
+	}
dc8c34
 	slapi_mods_init (&smods, 0);
dc8c34
 	sdn = slapi_entry_get_sdn_const( e );
dc8c34
 	dn = slapi_entry_get_ndn( e );
dc8c34
-- 
dc8c34
1.8.1.4
dc8c34