From e1ce45ac3de941ba79b8305b118d260a6dd29e62 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 2 Jan 2006 17:57:27 +0000 Subject: [PATCH] ITS#4292,94,95 fixes from HEAD --- CHANGES | 3 + include/ac/string.h | 8 +- servers/slapd/back-ldap/extended.c | 205 ++++++++++++++++++++++------- servers/slapd/passwd.c | 22 +++- servers/slapd/slap.h | 8 +- 5 files changed, 186 insertions(+), 60 deletions(-) diff --git a/CHANGES b/CHANGES index 2628d14170..dea2649ee1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ OpenLDAP 2.3 Change Log OpenLDAP 2.3.15 Engineering + Fixed slapd strerror logging bug (ITS#4292) + Fixed slapd-ldap password modify exop password return (ITS#4294) + Fixed slapd ACL add/delete fraction issue (ITS#4295) OpenLDAP 2.3.14 Release Fixed slapd assertion control restrictions diff --git a/include/ac/string.h b/include/ac/string.h index f91f04035c..49075a2782 100644 --- a/include/ac/string.h +++ b/include/ac/string.h @@ -106,14 +106,14 @@ void * memrchr(const void *b, int c, size_t len); #if defined( HAVE_NONPOSIX_STRERROR_R ) # define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l))) #elif defined( HAVE_STRERROR_R ) -# define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l)) ? (b) : "") +# define AC_STRERROR_R(e,b,l) (strerror_r((e), (b), (l)) == 0 ? (b) : "Unknown error") #elif defined( HAVE_SYS_ERRLIST ) # define AC_STRERROR_R(e,b,l) ((e) > -1 && (e) < sys_nerr \ - ? sys_errlist[(e)] : "" ) + ? sys_errlist[(e)] : "Unknown error" ) #elif defined( HAVE_STRERROR ) -# define AC_STRERROR_R(e,b,l) (strerror(e)) +# define AC_STRERROR_R(e,b,l) (strerror(e)) /* NOTE: may be NULL */ #else -# define AC_STRERROR_R(e,b,l) ("") +# define AC_STRERROR_R(e,b,l) ("Unknown error") #endif #endif /* _AC_STRING_H */ diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index 5c631ba4a1..21a4bd17f2 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -28,16 +28,59 @@ #include "back-ldap.h" #include "lber_pvt.h" -BI_op_extended ldap_back_exop_passwd; +static BI_op_extended ldap_back_exop_passwd; +static BI_op_extended ldap_back_exop_generic; static struct exop { struct berval oid; BI_op_extended *extended; } exop_table[] = { - { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), ldap_back_exop_passwd }, + { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), ldap_back_exop_passwd }, { BER_BVNULL, NULL } }; +static int +ldap_back_extended_one( Operation *op, SlapReply *rs, BI_op_extended exop ) +{ + ldapconn_t *lc; + LDAPControl **oldctrls = NULL; + int rc; + + /* FIXME: this needs to be called here, so it is + * called twice; maybe we could avoid the + * ldap_back_dobind() call inside each extended() + * call ... */ + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { + return -1; + } + + oldctrls = op->o_ctrls; + if ( ldap_back_proxy_authz_ctrl( lc, op, rs, &op->o_ctrls ) ) { + op->o_ctrls = oldctrls; + send_ldap_extended( op, rs ); + rs->sr_text = NULL; + /* otherwise frontend resends result */ + rc = rs->sr_err = SLAPD_ABANDON; + goto done; + } + + rc = exop( op, rs ); + + if ( op->o_ctrls && op->o_ctrls != oldctrls ) { + free( op->o_ctrls[ 0 ] ); + free( op->o_ctrls ); + } + op->o_ctrls = oldctrls; + +done:; + if ( lc != NULL ) { + ldap_back_release_conn( op, rs, lc ); + } + + return rc; +} + int ldap_back_extended( Operation *op, @@ -48,52 +91,17 @@ ldap_back_extended( for ( i = 0; exop_table[i].extended != NULL; i++ ) { if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) ) { - ldapconn_t *lc; - LDAPControl **oldctrls = NULL; - int rc; - - /* FIXME: this needs to be called here, so it is - * called twice; maybe we could avoid the - * ldap_back_dobind() call inside each extended() - * call ... */ - lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); - if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { - return -1; - } - - oldctrls = op->o_ctrls; - if ( ldap_back_proxy_authz_ctrl( lc, op, rs, - &op->o_ctrls ) ) - { - op->o_ctrls = oldctrls; - send_ldap_result( op, rs ); - rs->sr_text = NULL; - rc = rs->sr_err; - goto done; - } - - rc = ( *exop_table[i].extended )( op, rs ); - - if ( op->o_ctrls && op->o_ctrls != oldctrls ) { - free( op->o_ctrls[ 0 ] ); - free( op->o_ctrls ); - } - op->o_ctrls = oldctrls; - -done:; - if ( lc != NULL ) { - ldap_back_release_conn( op, rs, lc ); - } - - return rc; + return ldap_back_extended_one( op, rs, exop_table[i].extended ); } } - rs->sr_text = "not supported within naming context"; - return LDAP_UNWILLING_TO_PERFORM; + /* if we get here, the exop is known; the best that we can do + * is pass it thru as is */ + /* FIXME: maybe a list of OIDs to pass thru would be safer */ + return ldap_back_extended_one( op, rs, ldap_back_exop_generic ); } -int +static int ldap_back_exop_passwd( Operation *op, SlapReply *rs ) @@ -145,12 +153,20 @@ retry: rs->sr_text = NULL; } #endif /* LDAP_NULL_IS_NULL */ + if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { struct berval newpw; - + + /* this never happens because + * the frontend is generating + * the new password, so when + * the passwd exop is proxied, + * it never delegates password + * generation to the remote server + */ rc = ldap_parse_passwd( lc->lc_ld, res, - &newpw); + &newpw ); if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &newpw ) ) { @@ -174,8 +190,9 @@ retry: goto retry; } } - send_ldap_result( op, rs ); - rc = -1; + send_ldap_extended( op, rs ); + /* otherwise frontend resends result */ + rc = rs->sr_err = SLAPD_ABANDON; } /* these have to be freed anyway... */ @@ -194,3 +211,97 @@ retry: return rc; } + +static int +ldap_back_exop_generic( + Operation *op, + SlapReply *rs ) +{ + ldapconn_t *lc; + LDAPMessage *res; + ber_int_t msgid; + int rc; + int do_retry = 1; + + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { + return -1; + } + + Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n", + op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 ); + +retry: + rc = ldap_extended_operation( lc->lc_ld, + op->ore_reqoid.bv_val, op->ore_reqdata, + op->o_ctrls, NULL, &msgid ); + + if ( rc == LDAP_SUCCESS ) { + if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) { + ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); + ldap_back_freeconn( op, lc, 0 ); + lc = NULL; + + } else { + /* sigh. parse twice, because parse_passwd + * doesn't give us the err / match / msg info. + */ + rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, + (char **)&rs->sr_matched, + (char **)&rs->sr_text, + NULL, NULL, 0 ); +#ifndef LDAP_NULL_IS_NULL + if ( rs->sr_matched && rs->sr_matched[ 0 ] == '\0' ) { + free( (char *)rs->sr_matched ); + rs->sr_matched = NULL; + } + if ( rs->sr_text && rs->sr_text[ 0 ] == '\0' ) { + free( (char *)rs->sr_text ); + rs->sr_text = NULL; + } +#endif /* LDAP_NULL_IS_NULL */ + if ( rc == LDAP_SUCCESS ) { + if ( rs->sr_err == LDAP_SUCCESS ) { + rc = ldap_parse_extended_result( lc->lc_ld, res, + (char **)&rs->sr_rspoid, &rs->sr_rspdata, 0 ); + if ( rc == LDAP_SUCCESS ) { + rs->sr_type = REP_EXTENDED; + } + + } else { + rc = rs->sr_err; + } + } + ldap_msgfree( res ); + } + } + if ( rc != LDAP_SUCCESS ) { + rs->sr_err = slap_map_api2result( rs ); + if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + do_retry = 0; + if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { + goto retry; + } + } + send_ldap_extended( op, rs ); + /* otherwise frontend resends result */ + rc = rs->sr_err = SLAPD_ABANDON; + } + + /* these have to be freed anyway... */ + if ( rs->sr_matched ) { + free( (char *)rs->sr_matched ); + rs->sr_matched = NULL; + } + if ( rs->sr_text ) { + free( (char *)rs->sr_text ); + rs->sr_text = NULL; + } + + if ( lc != NULL ) { + ldap_back_release_conn( op, rs, lc ); + } + + return rc; +} + diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index af39674c1c..b79f26127e 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -54,8 +54,9 @@ int passwd_extop( slap_callback cb2 = { NULL, slap_replog_cb, NULL, NULL }; int i, nhash; char **hashes; - int rc; + int rc; BackendDB *op_be; + int freenewpw = 0; cb2.sc_next = &cb; @@ -183,6 +184,7 @@ int passwd_extop( slap_passwd_generate( &qpw->rs_new ); if ( qpw->rs_new.bv_len ) { rsp = slap_passwd_return( &qpw->rs_new ); + freenewpw = 1; } } if ( qpw->rs_new.bv_len == 0 ) { @@ -197,8 +199,13 @@ int passwd_extop( if ( op->o_bd->be_extended ) { rs->sr_err = op->o_bd->be_extended( op, rs ); if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM && - rs->sr_err != SLAP_CB_CONTINUE ) { + rs->sr_err != SLAP_CB_CONTINUE ) + { rc = rs->sr_err; + if ( rsp ) { + rs->sr_rspdata = rsp; + rsp = NULL; + } goto error_return; } } @@ -279,19 +286,22 @@ old_good: rs->sr_rspdata = rsp; } else if ( rsp ) { ber_bvfree( rsp ); + rsp = NULL; } op->o_tag = LDAP_REQ_EXTENDED; op->o_callback = sc; } - slap_mods_free( qpw->rs_mods, 1 ); - if ( rsp ) { - free( qpw->rs_new.bv_val ); - } rc = rs->sr_err; op->oq_extended = qext; error_return:; + if ( qpw->rs_mods ) { + slap_mods_free( qpw->rs_mods, 1 ); + } + if ( freenewpw ) { + free( qpw->rs_new.bv_val ); + } if ( !BER_BVISNULL( &op->o_req_dn ) ) { op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 9564bdbfa6..53ecc0b668 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1215,7 +1215,7 @@ typedef enum slap_access_e { ACL_COMPARE, ACL_SEARCH, ACL_READ, - ACL_WRITE, + ACL_WRITE_, ACL_MANAGE, /* always leave at end of levels but not greater than ACL_LEVEL_MASK */ @@ -1230,8 +1230,10 @@ typedef enum slap_access_e { ACL_QUALIFIER_MASK = 0x0f00, /* write granularity */ - ACL_WADD = ACL_WRITE|ACL_QUALIFIER1, - ACL_WDEL = ACL_WRITE|ACL_QUALIFIER2 + ACL_WADD = ACL_WRITE_|ACL_QUALIFIER1, + ACL_WDEL = ACL_WRITE_|ACL_QUALIFIER2, + + ACL_WRITE = ACL_WADD|ACL_WDEL } slap_access_t; typedef enum slap_control_e { -- 2.39.5