static int sasl_ap_lookup( Operation *op, SlapReply *rs ) { BerVarray bv; AttributeDescription *ad; Attribute *a; const char *text; int rc, i; lookup_info *sl = (lookup_info *)op->o_callback->sc_private; /* return the actual error code, * to allow caller to handle specific errors */ if (rs->sr_type != REP_SEARCH) return rs->sr_err; for( i = 0; sl->list[i].name; i++ ) { const char *name = sl->list[i].name; if ( name[0] == '*' ) { if ( sl->flags & SASL_AUXPROP_AUTHZID ) continue; /* Skip our private properties */ if ( !strcmp( name, slap_propnames[0] )) { i += SLAP_SASL_PROP_COUNT - 1; continue; } name++; } else if ( !(sl->flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( sl->list[i].values ) { if ( !(sl->flags & SASL_AUXPROP_OVERRIDE) ) continue; } ad = NULL; rc = slap_str2ad( name, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "slap_ap_lookup: str2ad(%s): %s\n", name, text, 0 ); continue; } /* If it's the rootdn and a rootpw was present, we already set * it so don't override it here. */ if ( ad == slap_schema.si_ad_userPassword && sl->list[i].values && be_isroot_dn( op->o_bd, &op->o_req_ndn )) continue; a = attr_find( rs->sr_entry->e_attrs, ad ); if ( !a ) continue; if ( ! access_allowed( op, rs->sr_entry, ad, NULL, ACL_AUTH, NULL ) ) { continue; } if ( sl->list[i].values && ( sl->flags & SASL_AUXPROP_OVERRIDE ) ) { sl->sparams->utils->prop_erase( sl->sparams->propctx, sl->list[i].name ); } for ( bv = a->a_vals; bv->bv_val; bv++ ) { /* ITS#3846 don't give hashed passwords to SASL */ if ( ad == slap_schema.si_ad_userPassword && bv->bv_val[0] == '{' /*}*/ ) { if ( lutil_passwd_scheme( bv->bv_val ) ) { /* If it's not a recognized scheme, just assume it's * a cleartext password that happened to include brackets. * * If it's a recognized scheme, skip this value, unless the * scheme is {CLEARTEXT}. In that case, skip over the * scheme name and use the remainder. If there is nothing * past the scheme name, skip this value. */ #ifdef SLAPD_CLEARTEXT if ( !strncasecmp( bv->bv_val, sc_cleartext.bv_val, sc_cleartext.bv_len )) { struct berval cbv; cbv.bv_len = bv->bv_len - sc_cleartext.bv_len; if ( cbv.bv_len > 0 ) { cbv.bv_val = bv->bv_val + sc_cleartext.bv_len; sl->sparams->utils->prop_set( sl->sparams->propctx, sl->list[i].name, cbv.bv_val, cbv.bv_len ); } } #endif continue; } } sl->sparams->utils->prop_set( sl->sparams->propctx, sl->list[i].name, bv->bv_val, bv->bv_len ); } } return LDAP_SUCCESS; }
static int #else static void #endif slap_auxprop_lookup( void *glob_context, sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { OperationBuffer opbuf = {{ NULL }}; Operation *op = (Operation *)&opbuf; int i, doit = 0; Connection *conn = NULL; lookup_info sl; int rc = LDAP_SUCCESS; #ifdef SLAP_AUXPROP_DONTUSECOPY int dontUseCopy = 0; BackendDB *dontUseCopy_bd = NULL; #endif /* SLAP_AUXPROP_DONTUSECOPY */ sl.list = sparams->utils->prop_get( sparams->propctx ); sl.sparams = sparams; sl.flags = flags; /* Find our DN and conn first */ for( i = 0; sl.list[i].name; i++ ) { if ( sl.list[i].name[0] == '*' ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) ); continue; } if ( flags & SASL_AUXPROP_AUTHZID ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) { if ( sl.list[i].values ) op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; break; } } if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( sl.list[i].values ) { op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; if ( !(flags & SASL_AUXPROP_AUTHZID) ) break; } } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( slap_dontUseCopy_propnames != NULL ) { int j; struct berval bv; ber_str2bv( &sl.list[i].name[1], 0, 1, &bv ); for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ]); j++ ) { if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) { dontUseCopy = 1; break; } } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } /* Now see what else needs to be fetched */ for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; /* Skip our private properties */ if ( !strcmp( name, slap_propnames[0] )) { i += SLAP_SASL_PROP_COUNT - 1; continue; } name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( sl.list[i].values ) { if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue; } doit = 1; break; } if (doit) { slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL }; cb.sc_private = &sl; op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd ) { /* For rootdn, see if we can use the rootpw */ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) && !BER_BVISEMPTY( &op->o_bd->be_rootpw )) { struct berval cbv = BER_BVNULL; /* If there's a recognized scheme, see if it's CLEARTEXT */ if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) { if ( !strncasecmp( op->o_bd->be_rootpw.bv_val, sc_cleartext.bv_val, sc_cleartext.bv_len )) { /* If it's CLEARTEXT, skip past scheme spec */ cbv.bv_len = op->o_bd->be_rootpw.bv_len - sc_cleartext.bv_len; if ( cbv.bv_len ) { cbv.bv_val = op->o_bd->be_rootpw.bv_val + sc_cleartext.bv_len; } } /* No scheme, use the whole value */ } else { cbv = op->o_bd->be_rootpw; } if ( !BER_BVISEMPTY( &cbv )) { for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( !strcasecmp(name,"userPassword") ) { sl.sparams->utils->prop_set( sl.sparams->propctx, sl.list[i].name, cbv.bv_val, cbv.bv_len ); break; } } } } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( SLAP_SHADOW( op->o_bd ) && dontUseCopy ) { dontUseCopy_bd = op->o_bd; op->o_bd = frontendDB; } retry_dontUseCopy:; #endif /* SLAP_AUXPROP_DONTUSECOPY */ if ( op->o_bd->be_search ) { SlapReply rs = {REP_RESULT}; #ifdef SLAP_AUXPROP_DONTUSECOPY LDAPControl **save_ctrls = NULL, c; int save_dontUseCopy; #endif /* SLAP_AUXPROP_DONTUSECOPY */ op->o_hdr = conn->c_sasl_bindop->o_hdr; op->o_controls = opbuf.ob_controls; op->o_tag = LDAP_REQ_SEARCH; op->o_dn = conn->c_ndn; op->o_ndn = conn->c_ndn; op->o_callback = &cb; slap_op_time( &op->o_time, &op->o_tincr ); op->o_do_not_cache = 1; op->o_is_auth_check = 1; op->o_req_dn = op->o_req_ndn; op->ors_scope = LDAP_SCOPE_BASE; op->ors_deref = LDAP_DEREF_NEVER; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 1; op->ors_filter = &generic_filter; op->ors_filterstr = generic_filterstr; op->o_authz = conn->c_authz; /* FIXME: we want all attributes, right? */ op->ors_attrs = NULL; #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy ) { save_dontUseCopy = op->o_dontUseCopy; if ( !op->o_dontUseCopy ) { int cnt = 0; save_ctrls = op->o_ctrls; if ( op->o_ctrls ) { for ( ; op->o_ctrls[ cnt ]; cnt++ ) ; } op->o_ctrls = op->o_tmpcalloc( sizeof(LDAPControl *), cnt + 2, op->o_tmpmemctx ); if ( cnt ) { for ( cnt = 0; save_ctrls[ cnt ]; cnt++ ) { op->o_ctrls[ cnt ] = save_ctrls[ cnt ]; } } c.ldctl_oid = LDAP_CONTROL_DONTUSECOPY; c.ldctl_iscritical = 1; BER_BVZERO( &c.ldctl_value ); op->o_ctrls[ cnt ] = &c; } op->o_dontUseCopy = SLAP_CONTROL_CRITICAL; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ rc = op->o_bd->be_search( op, &rs ); #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy ) { if ( save_ctrls != op->o_ctrls ) { op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx ); op->o_ctrls = save_ctrls; op->o_dontUseCopy = save_dontUseCopy; } if ( rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore ) { op->o_bd = dontUseCopy_bd; dontUseCopy = 0; goto retry_dontUseCopy; } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } } #if SASL_VERSION_FULL >= 0x020118 return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; #endif }
static int #else static void #endif slap_auxprop_lookup( void *glob_context, sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { OperationBuffer opbuf = {{ NULL }}; Operation *op = (Operation *)&opbuf; int i, doit = 0; Connection *conn = NULL; lookup_info sl; int rc = LDAP_SUCCESS; sl.list = sparams->utils->prop_get( sparams->propctx ); sl.sparams = sparams; sl.flags = flags; /* Find our DN and conn first */ for( i = 0; sl.list[i].name; i++ ) { if ( sl.list[i].name[0] == '*' ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &conn, sl.list[i].values[0], sizeof( conn ) ); continue; } if ( flags & SASL_AUXPROP_AUTHZID ) { if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) { if ( sl.list[i].values ) op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; break; } } if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( sl.list[i].values && sl.list[i].values[0] ) AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0], sizeof( op->o_req_ndn.bv_len ) ); } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( sl.list[i].values ) { op->o_req_ndn.bv_val = (char *)sl.list[i].values[0]; if ( !(flags & SASL_AUXPROP_AUTHZID) ) break; } } } } /* we don't know anything about this, ignore it */ if ( !conn ) { rc = LDAP_SUCCESS; goto done; } /* Now see what else needs to be fetched */ for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; /* Skip our private properties */ if ( !strcmp( name, slap_propnames[0] )) { i += SLAP_SASL_PROP_COUNT - 1; continue; } name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( sl.list[i].values ) { if ( !(flags & SASL_AUXPROP_OVERRIDE) ) continue; } doit = 1; break; } if (doit) { slap_callback cb = { NULL, sasl_ap_lookup, NULL, NULL }; cb.sc_private = &sl; op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd ) { /* For rootdn, see if we can use the rootpw */ if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) && !BER_BVISEMPTY( &op->o_bd->be_rootpw )) { struct berval cbv = BER_BVNULL; /* If there's a recognized scheme, see if it's CLEARTEXT */ if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) { if ( !strncasecmp( op->o_bd->be_rootpw.bv_val, sc_cleartext.bv_val, sc_cleartext.bv_len )) { /* If it's CLEARTEXT, skip past scheme spec */ cbv.bv_len = op->o_bd->be_rootpw.bv_len - sc_cleartext.bv_len; if ( cbv.bv_len ) { cbv.bv_val = op->o_bd->be_rootpw.bv_val + sc_cleartext.bv_len; } } /* No scheme, use the whole value */ } else { cbv = op->o_bd->be_rootpw; } if ( !BER_BVISEMPTY( &cbv )) { for( i = 0; sl.list[i].name; i++ ) { const char *name = sl.list[i].name; if ( name[0] == '*' ) { if ( flags & SASL_AUXPROP_AUTHZID ) continue; name++; } else if ( !(flags & SASL_AUXPROP_AUTHZID ) ) continue; if ( !strcasecmp(name,"userPassword") ) { sl.sparams->utils->prop_set( sl.sparams->propctx, sl.list[i].name, cbv.bv_val, cbv.bv_len ); break; } } } } if ( op->o_bd->be_search ) { SlapReply rs = {REP_RESULT}; op->o_hdr = conn->c_sasl_bindop->o_hdr; op->o_controls = opbuf.ob_controls; op->o_tag = LDAP_REQ_SEARCH; op->o_dn = conn->c_ndn; op->o_ndn = conn->c_ndn; op->o_callback = &cb; slap_op_time( &op->o_time, &op->o_tincr ); op->o_do_not_cache = 1; op->o_is_auth_check = 1; op->o_req_dn = op->o_req_ndn; op->ors_scope = LDAP_SCOPE_BASE; op->ors_deref = LDAP_DEREF_NEVER; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 1; op->ors_filter = &generic_filter; op->ors_filterstr = generic_filterstr; op->o_authz = conn->c_authz; /* FIXME: we want all attributes, right? */ op->ors_attrs = NULL; rc = op->o_bd->be_search( op, &rs ); } } } done:; #if SASL_VERSION_FULL >= 0x020118 return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; #endif }