X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fcontrols.c;h=88bfc9427986f2983d96c61f2390dbba7fc04dad;hb=17f95a3fd30247a0735a3526d85b46178304748d;hp=7489fb66a457540f162b7640b574ca61c9bf2f33;hpb=1509e321de84cdb40053a4ec4c5423f8e6ac373b;p=openldap diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 7489fb66a4..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_REQUEST - { LDAP_CONTROL_PAGEDRESULTS_REQUEST, + { LDAP_CONTROL_PAGEDRESULTS, SLAP_CTRL_SEARCH, NULL, parsePagedResults }, -#endif -#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"; @@ -220,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 ); @@ -260,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 ); @@ -280,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 ); @@ -318,9 +348,23 @@ int get_ctrls( case LDAP_REQ_UNBIND: tagmask = SLAP_CTRL_UNBIND; break; + case LDAP_REQ_ABANDON: + 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; @@ -370,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 @@ -411,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, @@ -465,9 +573,7 @@ static int parseNoOp ( return LDAP_SUCCESS; } -#endif -#ifdef LDAP_CONTROL_PAGEDRESULTS_REQUEST static int parsePagedResults ( Connection *conn, Operation *op, @@ -485,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; } @@ -510,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; } @@ -534,9 +640,12 @@ static int parsePagedResults ( *text = "paged results cookie is invalid or old"; return LDAP_UNWILLING_TO_PERFORM; } + } else { + /* Initial request. Initialize state. */ + op->o_pagedresults_state.ps_cookie = 0; + op->o_pagedresults_state.ps_id = NOID; } - op->o_pagedresults_state.ps_cookie = op->o_opid; op->o_pagedresults_size = size; op->o_pagedresults = ctrl->ldctl_iscritical @@ -545,9 +654,7 @@ static int parsePagedResults ( return LDAP_SUCCESS; } -#endif -#ifdef LDAP_CONTROL_VALUESRETURNFILTER int parseValuesReturnFilter ( Connection *conn, Operation *op, @@ -560,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; } @@ -603,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 @@ -626,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; } @@ -703,15 +845,15 @@ static int parseClientUpdate ( /* TODO : Cookie Scheme Validation */ #if 0 - if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) { - *text = "Invalid LCUP cookie"; - return LCUP_INVALID_COOKIE; - } - if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) { *text = "Unsupported LCUP cookie scheme"; return LCUP_UNSUPPORTED_SCHEME; } + + if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) { + *text = "Invalid LCUP cookie"; + return LCUP_INVALID_COOKIE; + } #endif ber_dupbv( &op->o_clientupdate_state, &cookie );