X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fcontrols.c;h=33d71d1f01471c177f83b5b6c49784a0b7b260df;hb=4361a942abb69d6b3dbae637cddb4055080fe6fa;hp=1931dd14aed43e099d52e15c1660e5a925abfbf6;hpb=9bcb37b5c19bddb488560c9cc74232634871c41b;p=openldap diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 1931dd14ae..33d71d1f01 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -194,24 +194,32 @@ static struct slap_control control_defs[] = { SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS, proxy_authz_extops, NULL, parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) }, - { NULL, 0, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) } + { NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) } }; +static struct slap_control * +find_ctrl( const char *oid ); + /* * Register a supported control. * * This can be called by an OpenLDAP plugin or, indirectly, by a * SLAPI plugin calling slapi_register_supported_control(). + * + * NOTE: if flags == 1 the control is replaced if already registered; + * otherwise registering an already registered control is not allowed. */ int -register_supported_control(const char *controloid, +register_supported_control2(const char *controloid, slap_mask_t controlmask, char **controlexops, SLAP_CTRL_PARSE_FN *controlparsefn, + unsigned flags, int *controlcid) { - struct slap_control *sc; + struct slap_control *sc = NULL; int i; + BerVarray extendedopsbv = NULL; if ( num_known_controls >= SLAP_MAX_CIDS ) { Debug( LDAP_DEBUG_ANY, "Too many controls registered." @@ -220,11 +228,23 @@ register_supported_control(const char *controloid, return LDAP_OTHER; } - if ( controloid == NULL ) return LDAP_PARAM_ERROR; + if ( controloid == NULL ) { + return LDAP_PARAM_ERROR; + } - /* sanity check - should never happen */ + /* check if already registered */ for ( i = 0; slap_known_controls[ i ]; i++ ) { if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) { + if ( flags == 1 ) { + Debug( LDAP_DEBUG_TRACE, + "Control %s already registered; replacing.\n", + controloid, 0, 0 ); + /* (find and) replace existing handler */ + sc = find_ctrl( controloid ); + assert( sc != NULL ); + break; + } + Debug( LDAP_DEBUG_ANY, "Control %s already registered.\n", controloid, 0, 0 ); @@ -232,41 +252,62 @@ register_supported_control(const char *controloid, } } - sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) ); - if ( sc == NULL ) return LDAP_NO_MEMORY; - - sc->sc_oid = ch_strdup( controloid ); - sc->sc_mask = controlmask; + /* turn compatible extended operations into bervals */ if ( controlexops != NULL ) { int i; for ( i = 0; controlexops[ i ]; i++ ); - sc->sc_extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) ); - if ( sc->sc_extendedopsbv == NULL ) { - ch_free( sc ); + extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) ); + if ( extendedopsbv == NULL ) { return LDAP_NO_MEMORY; } for ( i = 0; controlexops[ i ]; i++ ) { - ber_str2bv( controlexops[ i ], 0, 1, &sc->sc_extendedopsbv[ i ] ); + ber_str2bv( controlexops[ i ], 0, 1, &extendedopsbv[ i ] ); } + } + + if ( sc == NULL ) { + sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) ); + if ( sc == NULL ) { + return LDAP_NO_MEMORY; + } + + sc->sc_oid = ch_strdup( controloid ); + sc->sc_cid = num_known_controls; + + /* Update slap_known_controls, too. */ + slap_known_controls[num_known_controls - 1] = sc->sc_oid; + slap_known_controls[num_known_controls++] = NULL; + + LDAP_SLIST_NEXT( sc, sc_next ) = NULL; + LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next ); } else { - sc->sc_extendedopsbv = NULL; + if ( sc->sc_extendedopsbv ) { + /* FIXME: in principle, we should rather merge + * existing extops with those supported by the + * new control handling implementation. + * In fact, whether a control is compatible with + * an extop should not be a matter of implementation. + * We likely also need a means for a newly + * registered extop to declare that it is + * comptible with an already registered control. + */ + ber_bvarray_free( sc->sc_extendedopsbv ); + sc->sc_extendedopsbv = NULL; + sc->sc_extendedops = NULL; + } } - sc->sc_extendedops = NULL; - sc->sc_parse = controlparsefn; - - if ( controlcid ) *controlcid = num_known_controls; - sc->sc_cid = num_known_controls; - /* Update slap_known_controls, too. */ - slap_known_controls[num_known_controls-1] = sc->sc_oid; - slap_known_controls[num_known_controls++] = NULL; + sc->sc_extendedopsbv = extendedopsbv; + sc->sc_mask = controlmask; + sc->sc_parse = controlparsefn; + if ( controlcid ) { + *controlcid = sc->sc_cid; + } - LDAP_SLIST_NEXT( sc, sc_next ) = NULL; - LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next ); return LDAP_SUCCESS; } @@ -880,8 +921,8 @@ static int parseProxyAuthz ( if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON ) && BER_BVISEMPTY( &op->o_ndn ) ) { - rs->sr_text = "anonymous proxyAuthz not allowed"; - return LDAP_PROXY_AUTHZ_FAILURE; + rs->sr_text = "anonymous proxied authorization not allowed"; + return LDAP_PROXIED_AUTHORIZATION_DENIED; } op->o_proxy_authz = ctrl->ldctl_iscritical @@ -900,8 +941,6 @@ static int parseProxyAuthz ( op->o_connid, 0, 0 ); /* anonymous */ - /* FIXME: do we let anonymous authz as anonymous? - * should we disallow authz at all for anonymous? */ if ( !BER_BVISNULL( &op->o_ndn ) ) { op->o_ndn.bv_val[ 0 ] = '\0'; } @@ -924,7 +963,7 @@ static int parseProxyAuthz ( ch_free( dn.bv_val ); } rs->sr_text = "authzId mapping failed"; - return LDAP_PROXY_AUTHZ_FAILURE; + return LDAP_PROXIED_AUTHORIZATION_DENIED; } Debug( LDAP_DEBUG_TRACE, @@ -937,7 +976,7 @@ static int parseProxyAuthz ( if ( rc ) { ch_free( dn.bv_val ); rs->sr_text = "not authorized to assume identity"; - return LDAP_PROXY_AUTHZ_FAILURE; + return LDAP_PROXIED_AUTHORIZATION_DENIED; } ch_free( op->o_ndn.bv_val );