X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fcontrols.c;h=88bfc9427986f2983d96c61f2390dbba7fc04dad;hb=17f95a3fd30247a0735a3526d85b46178304748d;hp=b8a2011112a7da97830faf069fd0e35f19862207;hpb=c354bb23bf78f414e1ffdfbb0173a042c112ec3e;p=openldap diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index b8a2011112..88bfc94279 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1999-2002 The OpenLDAP Foundation. + * Copyright 1999-2003 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms are permitted only @@ -44,18 +44,27 @@ typedef int (SLAP_CTRL_PARSE_FN) LDAP_P(( LDAPControl *ctrl, const char **text )); +static SLAP_CTRL_PARSE_FN parseProxyAuthz; static SLAP_CTRL_PARSE_FN parseManageDSAit; -static SLAP_CTRL_PARSE_FN parseSubentries; static SLAP_CTRL_PARSE_FN parseNoOp; static SLAP_CTRL_PARSE_FN parsePagedResults; static SLAP_CTRL_PARSE_FN parseValuesReturnFilter; +#ifdef LDAP_CONTROL_SUBENTRIES +static SLAP_CTRL_PARSE_FN parseSubentries; +#endif #ifdef LDAP_CLIENT_UPDATE static SLAP_CTRL_PARSE_FN parseClientUpdate; -#endif /* LDAP_CLIENT_UPDATE */ +#endif #undef sc_mask /* avoid conflict with Irix 6.5 */ +static char *proxy_authz_extops[] = { + LDAP_EXOP_MODIFY_PASSWD, + LDAP_EXOP_X_WHO_AM_I, + NULL +}; + static struct slap_control { char *sc_oid; slap_mask_t sc_mask; @@ -63,35 +72,32 @@ static struct slap_control { SLAP_CTRL_PARSE_FN *sc_parse; } supportedControls[] = { + { LDAP_CONTROL_PROXY_AUTHZ, + SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops, + parseProxyAuthz }, { LDAP_CONTROL_MANAGEDSAIT, SLAP_CTRL_ACCESS, NULL, parseManageDSAit }, -#ifdef LDAP_CONTROL_SUBENTRIES - { LDAP_CONTROL_SUBENTRIES, - SLAP_CTRL_SEARCH, NULL, - parseSubentries }, -#endif -#ifdef LDAP_CONTROL_NOOP { LDAP_CONTROL_NOOP, SLAP_CTRL_ACCESS, NULL, parseNoOp }, -#endif -#ifdef LDAP_CONTROL_PAGEDRESULTS { LDAP_CONTROL_PAGEDRESULTS, SLAP_CTRL_SEARCH, NULL, parsePagedResults }, -#endif /* LDAP_CONTROL_PAGEDRESULTS */ -#ifdef LDAP_CONTROL_VALUESRETURNFILTER { LDAP_CONTROL_VALUESRETURNFILTER, SLAP_CTRL_SEARCH, NULL, - parseValuesReturnFilter }, + parseValuesReturnFilter }, +#ifdef LDAP_CONTROL_SUBENTRIES + { LDAP_CONTROL_SUBENTRIES, + SLAP_CTRL_SEARCH, NULL, + parseSubentries }, #endif #ifdef LDAP_CLIENT_UPDATE { LDAP_CONTROL_CLIENT_UPDATE, SLAP_CTRL_SEARCH, NULL, parseClientUpdate }, #endif /* LDAP_CLIENT_UPDATE */ - { NULL } + { NULL, 0, NULL, 0 } }; char * @@ -100,6 +106,12 @@ get_supported_ctrl(int index) return supportedControls[index].sc_oid; } +slap_mask_t +get_supported_ctrl_mask(int index) +{ + return supportedControls[index].sc_mask; +} + static struct slap_control * find_ctrl( const char *oid ) { @@ -144,10 +156,13 @@ int get_ctrls( } #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ENTRY, "get_ctrls: conn %lu\n", conn->c_connid, 0, 0 ); + LDAP_LOG( OPERATION, ENTRY, + "get_ctrls: conn %lu\n", conn->c_connid, 0, 0 ); #else - Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + "=> get_ctrls\n", 0, 0, 0 ); #endif + if( op->o_protocol < LDAP_VERSION3 ) { rc = SLAPD_DISCONNECT; errmsg = "controls require LDAPv3"; @@ -155,12 +170,7 @@ int get_ctrls( } /* one for first control, one for termination */ -#ifndef LDAP_CONTROL_PAGEDRESULTS op->o_ctrls = ch_malloc( 2 * sizeof(LDAPControl *) ); -#else /* LDAP_CONTROL_PAGEDRESULTS */ - /* FIXME: are we sure we need this? */ - op->o_ctrls = ch_malloc( 3 * sizeof(LDAPControl *) ); -#endif /* LDAP_CONTROL_PAGEDRESULTS */ #if 0 if( op->ctrls == NULL ) { @@ -225,11 +235,29 @@ int get_ctrls( Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n", 0, 0, 0 ); #endif + ldap_controls_free( op->o_ctrls ); op->o_ctrls = NULL; rc = SLAPD_DISCONNECT; errmsg = "decoding controls error"; goto return_results; + + } else if( c->ldctl_oid == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, INFO, + "get_ctrls: conn %lu got emtpy OID.\n", + conn->c_connid, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "get_ctrls: conn %lu got emtpy OID.\n", + conn->c_connid, 0, 0 ); +#endif + + ldap_controls_free( op->o_ctrls ); + op->o_ctrls = NULL; + rc = LDAP_PROTOCOL_ERROR; + errmsg = "OID field is empty"; + goto return_results; } tag = ber_peek_tag( ber, &len ); @@ -265,13 +293,12 @@ int get_ctrls( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu: " "%s (%scritical): get value failed.\n", - conn->c_connid, c->ldctl_oid ? c->ldctl_oid : "(NULL)", + conn->c_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: " "%s (%scritical): get value failed.\n", - conn->c_connid, - c->ldctl_oid ? c->ldctl_oid : "(NULL)", + conn->c_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #endif ldap_controls_free( op->o_ctrls ); @@ -285,13 +312,11 @@ int get_ctrls( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu oid=\"%s\" (%scritical)\n", - conn->c_connid, c->ldctl_oid ? c->ldctl_oid : "(NULL)", - c->ldctl_iscritical ? "" : "non" ); + conn->c_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #else - Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n", - c->ldctl_oid ? c->ldctl_oid : "(NULL)", - c->ldctl_iscritical ? "" : "non", - 0 ); + Debug( LDAP_DEBUG_TRACE, + "=> get_ctrls: oid=\"%s\" (%scritical)\n", + c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 ); #endif sc = find_ctrl( c->ldctl_oid ); @@ -327,8 +352,19 @@ int get_ctrls( tagmask = SLAP_CTRL_ABANDON; break; case LDAP_REQ_EXTENDED: - /* FIXME: check list of extended operations */ - tagmask = ~0U; + tagmask=~0L; + assert( op->o_extendedop != NULL ); + if( sc->sc_extendedops != NULL ) { + int i; + for( i=0; sc->sc_extendedops[i] != NULL; i++ ) { + if( strcmp( op->o_extendedop, sc->sc_extendedops[i] ) + == 0 ) + { + tagmask=0L; + break; + } + } + } break; default: rc = LDAP_OTHER; @@ -378,9 +414,11 @@ int get_ctrls( return_results: #ifdef NEW_LOGGING LDAP_LOG( OPERATION, RESULTS, - "get_ctrls: n=%d rc=%d err=%s\n", nctrls, rc, errmsg ? errmsg : "" ); + "get_ctrls: n=%d rc=%d err=\"%s\"\n", + nctrls, rc, errmsg ? errmsg : "" ); #else - Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: n=%d rc=%d err=%s\n", + Debug( LDAP_DEBUG_TRACE, + "<= get_ctrls: n=%d rc=%d err=\"%s\"\n", nctrls, rc, errmsg ? errmsg : ""); #endif @@ -419,38 +457,100 @@ static int parseManageDSAit ( return LDAP_SUCCESS; } -#ifdef LDAP_CONTROL_SUBENTRIES -static int parseSubentries ( +static int parseProxyAuthz ( Connection *conn, Operation *op, LDAPControl *ctrl, const char **text ) { - if ( op->o_subentries != SLAP_NO_CONTROL ) { - *text = "subentries control specified multiple times"; - return LDAP_PROTOCOL_ERROR; - } + int rc; + struct berval dn; - /* FIXME: should use BER library */ - if( ( ctrl->ldctl_value.bv_len != 3 ) - && ( ctrl->ldctl_value.bv_val[0] != 0x01 ) - && ( ctrl->ldctl_value.bv_val[1] != 0x01 )) - { - *text = "subentries control value encoding is bogus"; + if ( op->o_proxy_authz != SLAP_NO_CONTROL ) { + *text = "proxy authorization control specified multiple times"; return LDAP_PROTOCOL_ERROR; } - op->o_subentries = ctrl->ldctl_iscritical + op->o_proxy_authz = ctrl->ldctl_iscritical ? SLAP_CRITICAL_CONTROL : SLAP_NONCRITICAL_CONTROL; - op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00); +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ARGS, + "parseProxyAuthz: conn %lu authzid=\"%s\"\n", + conn->c_connid, + ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous", + 0 ); +#else + Debug( LDAP_DEBUG_ARGS, + "parseProxyAuthz: conn %lu authzid=\"%s\"\n", + conn->c_connid, + ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous", + 0 ); +#endif + + if( ctrl->ldctl_value.bv_len == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, RESULTS, + "parseProxyAuthz: conn=%lu anonymous\n", + conn->c_connid, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "parseProxyAuthz: conn=%lu anonymous\n", + conn->c_connid, 0, 0 ); +#endif + + /* anonymous */ + free( op->o_dn.bv_val ); + op->o_dn.bv_len = 0; + op->o_dn.bv_val = ch_strdup( "" ); + + free( op->o_ndn.bv_val ); + op->o_ndn.bv_len = 0; + op->o_ndn.bv_val = ch_strdup( "" ); + + return LDAP_SUCCESS; + } + + rc = slap_sasl_getdn( conn, + ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len, + NULL, &dn, SLAP_GETDN_AUTHZID ); + + if( rc != LDAP_SUCCESS || !dn.bv_len ) { + *text = "authzId mapping failed"; + return LDAP_PROXY_AUTHZ_FAILURE; + } + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, RESULTS, + "parseProxyAuthz: conn=%lu \"%s\"\n", + conn->c_connid, + dn.bv_len ? dn.bv_val : "(NULL)", 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "parseProxyAuthz: conn=%lu \"%s\"\n", + conn->c_connid, + dn.bv_len ? dn.bv_val : "(NULL)", 0 ); +#endif + + rc = slap_sasl_authorized( conn, &op->o_ndn, &dn ); + + if( rc ) { + ch_free( dn.bv_val ); + *text = "not authorized to assume identity"; + return LDAP_PROXY_AUTHZ_FAILURE; + } + + ch_free( op->o_dn.bv_val ); + ch_free( op->o_ndn.bv_val ); + + op->o_dn.bv_val = NULL; + op->o_ndn = dn; + ber_dupbv( &op->o_dn, &dn ); return LDAP_SUCCESS; } -#endif -#ifdef LDAP_CONTROL_NOOP static int parseNoOp ( Connection *conn, Operation *op, @@ -473,9 +573,7 @@ static int parseNoOp ( return LDAP_SUCCESS; } -#endif -#ifdef LDAP_CONTROL_PAGEDRESULTS static int parsePagedResults ( Connection *conn, Operation *op, @@ -493,7 +591,7 @@ static int parsePagedResults ( } if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "paged results control value is empty"; + *text = "paged results control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } @@ -518,7 +616,7 @@ static int parsePagedResults ( return LDAP_PROTOCOL_ERROR; } - if( size <= 0 ) { + if( size < 0 ) { *text = "paged results control size invalid"; return LDAP_PROTOCOL_ERROR; } @@ -556,9 +654,7 @@ static int parsePagedResults ( return LDAP_SUCCESS; } -#endif /* LDAP_CONTROL_PAGEDRESULTS */ -#ifdef LDAP_CONTROL_VALUESRETURNFILTER int parseValuesReturnFilter ( Connection *conn, Operation *op, @@ -571,7 +667,12 @@ int parseValuesReturnFilter ( const char *err_msg = ""; if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) { - *text = "valuesreturnfilter control specified multiple times"; + *text = "valuesReturnFilter control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } + + if ( ctrl->ldctl_value.bv_len == 0 ) { + *text = "valuesReturnFilter control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } @@ -614,6 +715,36 @@ int parseValuesReturnFilter ( return LDAP_SUCCESS; } + +#ifdef LDAP_CONTROL_SUBENTRIES +static int parseSubentries ( + Connection *conn, + Operation *op, + LDAPControl *ctrl, + const char **text ) +{ + if ( op->o_subentries != SLAP_NO_CONTROL ) { + *text = "subentries control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } + + /* FIXME: should use BER library */ + if( ( ctrl->ldctl_value.bv_len != 3 ) + && ( ctrl->ldctl_value.bv_val[0] != 0x01 ) + && ( ctrl->ldctl_value.bv_val[1] != 0x01 )) + { + *text = "subentries control value encoding is bogus"; + return LDAP_PROTOCOL_ERROR; + } + + op->o_subentries = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; + + op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00); + + return LDAP_SUCCESS; +} #endif #ifdef LDAP_CLIENT_UPDATE @@ -637,7 +768,7 @@ static int parseClientUpdate ( } if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "LCUP client update control value is empty"; + *text = "LCUP client update control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; }