static int pg_dynacl_unparse( void *priv, struct berval *bv ) { pg_t *pg = (pg_t *)priv; char *ptr; bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len; bv->bv_val = ch_malloc( bv->bv_len + 1 ); ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" ); switch ( pg->pg_style ) { case ACL_STYLE_BASE: ptr = lutil_strcopy( ptr, ".exact=" ); break; case ACL_STYLE_EXPAND: ptr = lutil_strcopy( ptr, ".expand=" ); break; default: assert( 0 ); } ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len ); ptr[ 0 ] = '\0'; bv->bv_len = ptr - bv->bv_val; return 0; }
static void ERR (char * const argv[], const char * s, char c) { #ifdef DF_TRACE_DEBUG printf("DF_TRACE_DEBUG: static void ERR () in getopt.c\n"); #endif if (opterr) { char *ptr, outbuf[4096]; ptr = lutil_strncopy(outbuf, argv[0], sizeof(outbuf) - 2); ptr = lutil_strncopy(ptr, s, sizeof(outbuf)-2 -(ptr-outbuf)); *ptr++ = c; *ptr++ = '\n'; #ifdef HAVE_EBCDIC __atoe_l(outbuf, ptr - outbuf); #endif (void) write(STDERR_FILENO,outbuf,ptr - outbuf); } }
/* The __LIBASCII doesn't include a working vsprintf, so we make do * using just sprintf. This is a very simplistic parser that looks for * format strings and uses sprintf to process them one at a time. * Literal text is just copied straight to the destination. * The result is appended to the destination string. The parser * recognizes field-width specifiers and the 'l' qualifier; it * may need to be extended to recognize other qualifiers but so * far this seems to be enough. */ int ber_pvt_vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) { char *ptr, *pct, *s2, *f2, *end; char fm2[64]; int len, rem; ptr = (char *)fmt; s2 = str; fm2[0] = '%'; if (n) { end = str + n; } else { end = NULL; } for (pct = strchr(ptr, '%'); pct; pct = strchr(ptr, '%')) { len = pct-ptr; if (end) { rem = end-s2; if (rem < 1) return -1; if (rem < len) len = rem; } s2 = lutil_strncopy( s2, ptr, len ); /* Did we cheat the length above? If so, bail out */ if (len < pct-ptr) return -1; for (pct++, f2 = fm2+1; isdigit(*pct);) *f2++ = *pct++; if (*pct == 'l') *f2++ = *pct++; if (*pct == '%') { *s2++ = '%'; } else { *f2++ = *pct; *f2 = '\0'; if (*pct == 's') { char *ss = va_arg(ap, char *); /* Attempt to limit sprintf output. This * may be thrown off if field widths were * specified for this string. * * If it looks like the string is too * long for the remaining buffer, bypass * sprintf and just copy what fits, then * quit. */ if (end && strlen(ss) > (rem=end-s2)) { strncpy(s2, ss, rem); return -1; } else { s2 += sprintf(s2, fm2, ss); } } else { s2 += sprintf(s2, fm2, va_arg(ap, int)); } }
static int gssattr_dynacl_unparse( void *priv, struct berval *bv ) { gssattr_t *gssattr = (gssattr_t *)priv; char *ptr; bv->bv_len = STRLENOF( " dynacl/gss/.expand=" ) + gssattr->gssattr_name.bv_len + gssattr->gssattr_value.bv_len; bv->bv_val = ch_malloc( bv->bv_len + 1 ); ptr = lutil_strcopy( bv->bv_val, " dynacl/gss/" ); ptr = lutil_strncopy( ptr, gssattr->gssattr_name.bv_val, gssattr->gssattr_name.bv_len ); switch ( gssattr->gssattr_style ) { case ACL_STYLE_BASE: ptr = lutil_strcopy( ptr, ".exact=" ); break; case ACL_STYLE_REGEX: ptr = lutil_strcopy( ptr, ".regex=" ); break; case ACL_STYLE_EXPAND: ptr = lutil_strcopy( ptr, ".expand=" ); break; default: assert( 0 ); break; } ptr = lutil_strncopy( ptr, gssattr->gssattr_value.bv_val, gssattr->gssattr_value.bv_len ); ptr[ 0 ] = '\0'; bv->bv_len = ptr - bv->bv_val; return 0; }
static int rdnval_repair_cb( Operation *op, SlapReply *rs ) { int rc; rdnval_repair_cb_t *rcb = op->o_callback->sc_private; rdnval_mod_t *mod; BerVarray vals = NULL, nvals = NULL; int numvals = 0; ber_len_t len; BackendDB *save_bd = op->o_bd; switch ( rs->sr_type ) { case REP_SEARCH: break; case REP_SEARCHREF: case REP_RESULT: return rs->sr_err; default: assert( 0 ); } assert( rs->sr_entry != NULL ); op->o_bd = rcb->bd; rc = rdnval_rdn2vals( op, rs, &rs->sr_entry->e_name, &rs->sr_entry->e_nname, &vals, &nvals, &numvals ); op->o_bd = save_bd; if ( rc != LDAP_SUCCESS ) { return 0; } len = sizeof( rdnval_mod_t ) + rs->sr_entry->e_nname.bv_len + 1; mod = op->o_tmpalloc( len, op->o_tmpmemctx ); mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len; mod->ndn.bv_val = (char *)&mod[1]; lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len ); mod->vals = vals; mod->nvals = nvals; mod->numvals = numvals; mod->next = rcb->mods; rcb->mods = mod; Debug( LDAP_DEBUG_TRACE, "%s: rdnval_repair_cb: scheduling entry DN=\"%s\" for repair\n", op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 ); return 0; }
ID ndb_tool_entry_next( BackendDB *be ) { struct ndb_info *ni = (struct ndb_info *) be->be_private; char *ptr; ID id; int i; assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); if ( myScanOp->nextResult() ) { myScanOp->close(); myScanOp = NULL; myScanTxn->close(); myScanTxn = NULL; return NOID; } id = myScanID->u_64_value(); if ( myOcList ) { ber_bvarray_free( myOcList ); } myOcList = ndb_ref2oclist( myOcbuf, NULL ); for ( i=0; i<NDB_MAX_RDNS; i++ ) { if ( myScanDN[i]->isNULL() || !myRdns.nr_buf[i][0] ) break; } myRdns.nr_num = i; ptr = myDNbuf; for ( --i; i>=0; i-- ) { char *buf; int len; buf = myRdns.nr_buf[i]; len = *buf++; ptr = lutil_strncopy( ptr, buf, len ); if ( i ) *ptr++ = ','; } *ptr = '\0'; myDn.bv_val = myDNbuf; myDn.bv_len = ptr - myDNbuf; return id; }
static int idattr_dynacl_unparse( void *priv, struct berval *bv ) { idattr_t *id = (idattr_t *)priv; char *ptr = NULL, *start = NULL; size_t len = 0; bv->bv_len = MAX_ACE_LEN; bv->bv_val = ch_calloc( 1, bv->bv_len + 1 ); start = ptr = lutil_strcopy( bv->bv_val, " dynacl/idattr" ); if (idattr_dynacl_unparse_optionsavailable(id, &ptr) != 0) goto exit_on_error; if (idattr_dynacl_unparse_operation(id, &ptr) != 0) goto exit_on_error; if (idattr_dynacl_unparse_applyto(id, &ptr) != 0) goto exit_on_error; if (idattr_dynacl_unparse_selfattr(id, &ptr) != 0) goto exit_on_error; if (idattr_dynacl_unparse_boolattr(id, &ptr) != 0) goto exit_on_error; // remove trailing option terminator len = strlen(start); if (len && start[len - 1] == ';') { start[len - 1] = '\0'; ptr = start + len - 1; } if (idattr_dynacl_unparse_style(id, &ptr) != 0) goto exit_on_error; ptr = lutil_strncopy( ptr, id->idattr_pat.bv_val, id->idattr_pat.bv_len ); ptr[ 0 ] = '\0'; bv->bv_len = ptr - bv->bv_val; exit_on_error: return 0; }
void build_new_dn( struct berval * new_dn, struct berval * parent_dn, struct berval * newrdn, void *memctx ) { char *ptr; if ( parent_dn == NULL || parent_dn->bv_len == 0 ) { ber_dupbv_x( new_dn, newrdn, memctx ); return; } new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1; new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx ); ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len ); *ptr++ = ','; strcpy( ptr, parent_dn->bv_val ); }
static char * rwm_suffix_massage_regexize( const char *s ) { char *res, *ptr; const char *p, *r; int i; if ( s[0] == '\0' ) { return ch_strdup( "^(.+)$" ); } for ( i = 0, p = s; ( r = strchr( p, ',' ) ) != NULL; p = r + 1, i++ ) ; res = ch_calloc( sizeof( char ), strlen( s ) + STRLENOF( "((.+),)?" ) + STRLENOF( "[ ]?" ) * i + STRLENOF( "$" ) + 1 ); ptr = lutil_strcopy( res, "((.+),)?" ); for ( i = 0, p = s; ( r = strchr( p, ',' ) ) != NULL; p = r + 1 , i++ ) { ptr = lutil_strncopy( ptr, p, r - p + 1 ); ptr = lutil_strcopy( ptr, "[ ]?" ); if ( r[ 1 ] == ' ' ) { r++; } } ptr = lutil_strcopy( ptr, p ); ptr[0] = '$'; ptr[1] = '\0'; return res; }
static int vernum_repair_cb( Operation *op, SlapReply *rs ) { int rc; vernum_repair_cb_t *rcb = op->o_callback->sc_private; vernum_mod_t *mod; ber_len_t len; BackendDB *save_bd = op->o_bd; switch ( rs->sr_type ) { case REP_SEARCH: break; case REP_SEARCHREF: case REP_RESULT: return rs->sr_err; default: assert( 0 ); } assert( rs->sr_entry != NULL ); len = sizeof( vernum_mod_t ) + rs->sr_entry->e_nname.bv_len + 1; mod = op->o_tmpalloc( len, op->o_tmpmemctx ); mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len; mod->ndn.bv_val = (char *)&mod[1]; lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len ); mod->next = rcb->mods; rcb->mods = mod; Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair_cb: scheduling entry DN=\"%s\" for repair\n", op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 ); return 0; }
static int rc_cf_gen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; retcode_t *rd = (retcode_t *)on->on_bi.bi_private; int rc = ARG_BAD_CONF; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) { case RC_PARENT: if ( !BER_BVISEMPTY( &rd->rd_pdn )) { rc = value_add_one( &c->rvalue_vals, &rd->rd_pdn ); if ( rc == 0 ) { rc = value_add_one( &c->rvalue_nvals, &rd->rd_npdn ); } return rc; } rc = 0; break; case RC_ITEM: { retcode_item_t *rdi; int i; for ( rdi = rd->rd_item, i = 0; rdi; rdi = rdi->rdi_next, i++ ) { char buf[4096]; struct berval bv; char *ptr; bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); bv.bv_len += rdi->rdi_line.bv_len; ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 ); ptr = lutil_strcopy( ptr, buf ); ptr = lutil_strncopy( ptr, rdi->rdi_line.bv_val, rdi->rdi_line.bv_len ); ber_bvarray_add( &c->rvalue_vals, &bv ); } rc = 0; } break; default: LDAP_BUG(); break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case RC_PARENT: if ( rd->rd_pdn.bv_val ) { ber_memfree ( rd->rd_pdn.bv_val ); rc = 0; } if ( rd->rd_npdn.bv_val ) { ber_memfree ( rd->rd_npdn.bv_val ); } break; case RC_ITEM: if ( c->valx == -1 ) { retcode_item_t *rdi, *next; for ( rdi = rd->rd_item; rdi != NULL; rdi = next ) { next = rdi->rdi_next; retcode_item_destroy( rdi ); } } else { retcode_item_t **rdip, *rdi; int i; for ( rdip = &rd->rd_item, i = 0; i <= c->valx && *rdip; i++, rdip = &(*rdip)->rdi_next ) ; if ( *rdip == NULL ) { return 1; } rdi = *rdip; *rdip = rdi->rdi_next; retcode_item_destroy( rdi ); } rc = 0; break; default: LDAP_BUG(); break; } return rc; /* FIXME */ } switch( c->type ) { case RC_PARENT: if ( rd->rd_pdn.bv_val ) { ber_memfree ( rd->rd_pdn.bv_val ); } if ( rd->rd_npdn.bv_val ) { ber_memfree ( rd->rd_npdn.bv_val ); } rd->rd_pdn = c->value_dn; rd->rd_npdn = c->value_ndn; rc = 0; break; case RC_ITEM: { retcode_item_t rdi = { BER_BVNULL }, **rdip; struct berval bv, rdn, nrdn; char *next = NULL; int i; if ( c->argc < 3 ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"retcode-item <RDN> <retcode> [<text>]\": " "missing args" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( c->argv[ 1 ], 0, 0, &bv ); rc = dnPrettyNormal( NULL, &bv, &rdn, &nrdn, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to normalize RDN \"%s\": %d", c->argv[ 1 ], rc ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( !dnIsOneLevelRDN( &nrdn ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "value \"%s\" is not a RDN", c->argv[ 1 ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( BER_BVISNULL( &rd->rd_npdn ) ) { /* FIXME: we use the database suffix */ if ( c->be->be_nsuffix == NULL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "either \"retcode-parent\" " "or \"suffix\" must be defined" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_dupbv( &rd->rd_pdn, &c->be->be_suffix[ 0 ] ); ber_dupbv( &rd->rd_npdn, &c->be->be_nsuffix[ 0 ] ); } build_new_dn( &rdi.rdi_dn, &rd->rd_pdn, &rdn, NULL ); build_new_dn( &rdi.rdi_ndn, &rd->rd_npdn, &nrdn, NULL ); ch_free( rdn.bv_val ); ch_free( nrdn.bv_val ); rdi.rdi_err = strtol( c->argv[ 2 ], &next, 0 ); if ( next == c->argv[ 2 ] || next[ 0 ] != '\0' ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse return code \"%s\"", c->argv[ 2 ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } rdi.rdi_mask = SN_DG_OP_ALL; if ( c->argc > 3 ) { for ( i = 3; i < c->argc; i++ ) { if ( strncasecmp( c->argv[ i ], "op=", STRLENOF( "op=" ) ) == 0 ) { char **ops; int j; ops = ldap_str2charray( &c->argv[ i ][ STRLENOF( "op=" ) ], "," ); assert( ops != NULL ); rdi.rdi_mask = SN_DG_OP_NONE; for ( j = 0; ops[ j ] != NULL; j++ ) { if ( strcasecmp( ops[ j ], "add" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_ADD; } else if ( strcasecmp( ops[ j ], "bind" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_BIND; } else if ( strcasecmp( ops[ j ], "compare" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_COMPARE; } else if ( strcasecmp( ops[ j ], "delete" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_DELETE; } else if ( strcasecmp( ops[ j ], "modify" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_MODIFY; } else if ( strcasecmp( ops[ j ], "rename" ) == 0 || strcasecmp( ops[ j ], "modrdn" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_RENAME; } else if ( strcasecmp( ops[ j ], "search" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_SEARCH; } else if ( strcasecmp( ops[ j ], "extended" ) == 0 ) { rdi.rdi_mask |= SN_DG_EXTENDED; } else if ( strcasecmp( ops[ j ], "auth" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_AUTH; } else if ( strcasecmp( ops[ j ], "read" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_READ; } else if ( strcasecmp( ops[ j ], "write" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_WRITE; } else if ( strcasecmp( ops[ j ], "all" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_ALL; } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown op \"%s\"", ops[ j ] ); ldap_charray_free( ops ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } ldap_charray_free( ops ); } else if ( strncasecmp( c->argv[ i ], "text=", STRLENOF( "text=" ) ) == 0 ) { if ( !BER_BVISNULL( &rdi.rdi_text ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"text\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( &c->argv[ i ][ STRLENOF( "text=" ) ], 0, 1, &rdi.rdi_text ); } else if ( strncasecmp( c->argv[ i ], "matched=", STRLENOF( "matched=" ) ) == 0 ) { struct berval dn; if ( !BER_BVISNULL( &rdi.rdi_matched ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"matched\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( &c->argv[ i ][ STRLENOF( "matched=" ) ], 0, 0, &dn ); if ( dnPretty( NULL, &dn, &rdi.rdi_matched, NULL ) != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to prettify matched DN \"%s\"", &c->argv[ i ][ STRLENOF( "matched=" ) ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else if ( strncasecmp( c->argv[ i ], "ref=", STRLENOF( "ref=" ) ) == 0 ) { char **refs; int j; if ( rdi.rdi_ref != NULL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"ref\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( rdi.rdi_err != LDAP_REFERRAL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "providing \"ref\" " "along with a non-referral " "resultCode may cause slapd failures " "related to internal checks" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); } refs = ldap_str2charray( &c->argv[ i ][ STRLENOF( "ref=" ) ], " " ); assert( refs != NULL ); for ( j = 0; refs[ j ] != NULL; j++ ) { struct berval bv; ber_str2bv( refs[ j ], 0, 1, &bv ); ber_bvarray_add( &rdi.rdi_ref, &bv ); } ldap_charray_free( refs ); } else if ( strncasecmp( c->argv[ i ], "sleeptime=", STRLENOF( "sleeptime=" ) ) == 0 ) { if ( rdi.rdi_sleeptime != 0 ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"sleeptime\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( lutil_atoi( &rdi.rdi_sleeptime, &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse \"sleeptime=%s\"", &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else if ( strncasecmp( c->argv[ i ], "unsolicited=", STRLENOF( "unsolicited=" ) ) == 0 ) { char *data; if ( !BER_BVISNULL( &rdi.rdi_unsolicited_oid ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"unsolicited\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } data = strchr( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], ':' ); if ( data != NULL ) { struct berval oid; if ( ldif_parse_line2( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], &oid, &rdi.rdi_unsolicited_data, NULL ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse \"unsolicited\"" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_dupbv( &rdi.rdi_unsolicited_oid, &oid ); } else { ber_str2bv( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], 0, 1, &rdi.rdi_unsolicited_oid ); } } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) { char *arg = &c->argv[ i ][ STRLENOF( "flags=" ) ]; if ( strcasecmp( arg, "disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_PRE_DISCONNECT; } else if ( strcasecmp( arg, "pre-disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_PRE_DISCONNECT; } else if ( strcasecmp( arg, "post-disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_POST_DISCONNECT; } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown flag \"%s\"", arg ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown option \"%s\"", c->argv[ i ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } } rdi.rdi_line.bv_len = 2*(c->argc - 1) + c->argc - 2; for ( i = 1; i < c->argc; i++ ) { rdi.rdi_line.bv_len += strlen( c->argv[ i ] ); } next = rdi.rdi_line.bv_val = ch_malloc( rdi.rdi_line.bv_len + 1 ); for ( i = 1; i < c->argc; i++ ) { *next++ = '"'; next = lutil_strcopy( next, c->argv[ i ] ); *next++ = '"'; *next++ = ' '; } *--next = '\0'; for ( rdip = &rd->rd_item; *rdip; rdip = &(*rdip)->rdi_next ) /* go to last */ ; *rdip = ( retcode_item_t * )ch_malloc( sizeof( retcode_item_t ) ); *(*rdip) = rdi; rc = 0; } break; default: rc = SLAP_CONF_UNKNOWN; break; } return rc; }
static int rdnval_unique_check( Operation *op, BerVarray vals ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; BackendDB db = *op->o_bd; Operation op2 = *op; SlapReply rs2 = { 0 }; int i; BerVarray fvals; char *ptr; int gotit = 0; slap_callback cb = { 0 }; /* short-circuit attempts to add suffix entry */ if ( op->o_tag == LDAP_REQ_ADD && be_issuffix( op->o_bd, &op->o_req_ndn ) ) { return LDAP_SUCCESS; } op2.o_bd = &db; op2.o_bd->bd_info = (BackendInfo *)on->on_info; op2.o_tag = LDAP_REQ_SEARCH; op2.o_dn = op->o_bd->be_rootdn; op2.o_ndn = op->o_bd->be_rootndn; op2.o_callback = &cb; cb.sc_response = rdnval_unique_check_cb; cb.sc_private = (void *)&gotit; dnParent( &op->o_req_ndn, &op2.o_req_dn ); op2.o_req_ndn = op2.o_req_dn; op2.ors_limit = NULL; op2.ors_slimit = 1; op2.ors_tlimit = SLAP_NO_LIMIT; op2.ors_attrs = slap_anlist_no_attrs; op2.ors_attrsonly = 1; op2.ors_deref = LDAP_DEREF_NEVER; op2.ors_scope = LDAP_SCOPE_ONELEVEL; for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) /* just count */ ; fvals = op->o_tmpcalloc( sizeof( struct berval ), i + 1, op->o_tmpmemctx ); op2.ors_filterstr.bv_len = 0; if ( i > 1 ) { op2.ors_filterstr.bv_len = STRLENOF( "(&)" ); } for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { ldap_bv2escaped_filter_value_x( &vals[ i ], &fvals[ i ], 1, op->o_tmpmemctx ); op2.ors_filterstr.bv_len += ad_rdnValue->ad_cname.bv_len + fvals[ i ].bv_len + STRLENOF( "(=)" ); } op2.ors_filterstr.bv_val = op->o_tmpalloc( op2.ors_filterstr.bv_len + 1, op->o_tmpmemctx ); ptr = op2.ors_filterstr.bv_val; if ( i > 1 ) { ptr = lutil_strcopy( ptr, "(&" ); } for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { *ptr++ = '('; ptr = lutil_strncopy( ptr, ad_rdnValue->ad_cname.bv_val, ad_rdnValue->ad_cname.bv_len ); *ptr++ = '='; ptr = lutil_strncopy( ptr, fvals[ i ].bv_val, fvals[ i ].bv_len ); *ptr++ = ')'; } if ( i > 1 ) { *ptr++ = ')'; } *ptr = '\0'; assert( ptr == op2.ors_filterstr.bv_val + op2.ors_filterstr.bv_len ); op2.ors_filter = str2filter_x( op, op2.ors_filterstr.bv_val ); assert( op2.ors_filter != NULL ); (void)op2.o_bd->be_search( &op2, &rs2 ); filter_free_x( op, op2.ors_filter, 1 ); op->o_tmpfree( op2.ors_filterstr.bv_val, op->o_tmpmemctx ); for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { if ( vals[ i ].bv_val != fvals[ i ].bv_val ) { op->o_tmpfree( fvals[ i ].bv_val, op->o_tmpmemctx ); } } op->o_tmpfree( fvals, op->o_tmpmemctx ); if ( rs2.sr_err != LDAP_SUCCESS || gotit > 0 ) { return LDAP_CONSTRAINT_VIOLATION; } return LDAP_SUCCESS; }
/* * call from within ldap_back_db_open() */ int ldap_back_monitor_db_open( BackendDB *be ) { ldapinfo_t *li = (ldapinfo_t *) be->be_private; char buf[ BACKMONITOR_BUFSIZE ]; Entry *e = NULL; monitor_callback_t *cb = NULL; struct berval suffix, *filter, *base; char *ptr; time_t now; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval timestamp; int rc = 0; BackendInfo *mi; monitor_extra_t *mbe; if ( !SLAP_DBMONITORING( be ) ) { return 0; } /* check if monitor is configured and usable */ mi = backend_info( "monitor" ); if ( !mi || !mi->bi_extra ) { SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING; return 0; } mbe = mi->bi_extra; /* don't bother if monitor is not configured */ if ( !mbe->is_configured() ) { static int warning = 0; if ( warning++ == 0 ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "monitoring disabled; " "configure monitor database to enable\n", 0, 0, 0 ); } return 0; } /* set up the fake subsystem that is used to create * the volatile connection entries */ li->li_monitor_info.lmi_mss.mss_name = "back-ldap"; li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH; li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create; li->li_monitor_info.lmi_li = li; li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE; base = &li->li_monitor_info.lmi_base; BER_BVSTR( base, "cn=databases,cn=monitor" ); filter = &li->li_monitor_info.lmi_filter; BER_BVZERO( filter ); suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] ); if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) { suffix = be->be_nsuffix[ 0 ]; } else { ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix ); } filter->bv_len = STRLENOF( "(&" ) + li->li_monitor_info.lmi_more_filter.bv_len + STRLENOF( "(monitoredInfo=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( ")(!(monitorOverlay=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( "))(namingContexts:distinguishedNameMatch:=" ) + suffix.bv_len + STRLENOF( "))" ); ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 ); ptr = lutil_strcopy( ptr, "(&" ); ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val, li->li_monitor_info.lmi_more_filter.bv_len ); ptr = lutil_strcopy( ptr, "(monitoredInfo=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" ); ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len ); ptr = lutil_strcopy( ptr, "))" ); ptr[ 0 ] = '\0'; assert( ptr == &filter->bv_val[ filter->bv_len ] ); if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) { ch_free( suffix.bv_val ); } now = slap_get_time(); timestamp.bv_val = timebuf; timestamp.bv_len = sizeof( timebuf ); slap_timestamp( &now, ×tamp ); /* caller (e.g. an overlay based on back-ldap) may want to use * a different RDN... */ if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) { ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn ); } ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' ); assert( ptr != NULL ); ptr[ 0 ] = '\0'; ptr++; snprintf( buf, sizeof( buf ), "dn: %s=%s\n" "objectClass: monitorContainer\n" "%s: %s\n" "creatorsName: %s\n" "createTimestamp: %s\n" "modifiersName: %s\n" "modifyTimestamp: %s\n", li->li_monitor_info.lmi_rdn.bv_val, ptr, li->li_monitor_info.lmi_rdn.bv_val, ptr, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val ); e = str2entry( buf ); if ( e == NULL ) { rc = -1; goto cleanup; } ptr[ -1 ] = '='; /* add labeledURI and special, modifiable URI value */ if ( li->li_uri != NULL ) { struct berval bv; LDAPURLDesc *ludlist = NULL; int rc; rc = ldap_url_parselist_ext( &ludlist, li->li_uri, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); if ( rc != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "unable to parse URI list (ignored)\n", 0, 0, 0 ); } else { for ( ; ludlist != NULL; ) { LDAPURLDesc *next = ludlist->lud_next; bv.bv_val = ldap_url_desc2str( ludlist ); assert( bv.bv_val != NULL ); ldap_free_urldesc( ludlist ); bv.bv_len = strlen( bv.bv_val ); attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI, &bv, NULL ); ch_free( bv.bv_val ); ludlist = next; } } ber_str2bv( li->li_uri, 0, 0, &bv ); attr_merge_normalize_one( e, ad_olmDbURIList, &bv, NULL ); } ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname ); cb = ch_calloc( sizeof( monitor_callback_t ), 1 ); cb->mc_update = ldap_back_monitor_update; cb->mc_modify = ldap_back_monitor_modify; cb->mc_free = ldap_back_monitor_free; cb->mc_private = (void *)li; rc = mbe->register_entry_parent( e, cb, (monitor_subsys_t *)&li->li_monitor_info, MONITOR_F_VOLATILE_CH, base, LDAP_SCOPE_SUBORDINATE, filter ); cleanup:; if ( rc != 0 ) { if ( cb != NULL ) { ch_free( cb ); cb = NULL; } if ( e != NULL ) { entry_free( e ); e = NULL; } if ( !BER_BVISNULL( filter ) ) { ch_free( filter->bv_val ); BER_BVZERO( filter ); } } /* store for cleanup */ li->li_monitor_info.lmi_cb = (void *)cb; if ( e != NULL ) { entry_free( e ); } return rc; }
/* * call from within bdb_db_open() */ int bdb_monitor_db_open( BackendDB *be ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; Attribute *a, *next; monitor_callback_t *cb = NULL; int rc = 0; BackendInfo *mi; monitor_extra_t *mbe; struct berval dummy = BER_BVC(""); if ( !SLAP_DBMONITORING( be ) ) { return 0; } mi = backend_info( "monitor" ); if ( !mi || !mi->bi_extra ) { SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING; return 0; } mbe = mi->bi_extra; /* don't bother if monitor is not configured */ if ( !mbe->is_configured() ) { static int warning = 0; if ( warning++ == 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_monitor_db_open) ": monitoring disabled; " "configure monitor database to enable\n", 0, 0, 0 ); } return 0; } /* alloc as many as required (plus 1 for objectClass) */ a = attrs_alloc( 1 + 4 ); if ( a == NULL ) { rc = 1; goto cleanup; } a->a_desc = slap_schema.si_ad_objectClass; attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 ); next = a->a_next; { struct berval bv = BER_BVC( "0" ); next->a_desc = ad_olmBDBEntryCache; attr_valadd( next, &bv, NULL, 1 ); next = next->a_next; next->a_desc = ad_olmBDBDNCache; attr_valadd( next, &bv, NULL, 1 ); next = next->a_next; next->a_desc = ad_olmBDBIDLCache; attr_valadd( next, &bv, NULL, 1 ); next = next->a_next; } { struct berval bv, nbv; ber_len_t pathlen = 0, len = 0; char path[ MAXPATHLEN ] = { '\0' }; char *fname = bdb->bi_dbenv_home, *ptr; len = strlen( fname ); if ( fname[ 0 ] != '/' ) { /* get full path name */ getcwd( path, sizeof( path ) ); pathlen = strlen( path ); if ( fname[ 0 ] == '.' && fname[ 1 ] == '/' ) { fname += 2; len -= 2; } } bv.bv_len = pathlen + STRLENOF( "/" ) + len; ptr = bv.bv_val = ch_malloc( bv.bv_len + STRLENOF( "/" ) + 1 ); if ( pathlen ) { ptr = lutil_strncopy( ptr, path, pathlen ); ptr[ 0 ] = '/'; ptr++; } ptr = lutil_strncopy( ptr, fname, len ); if ( ptr[ -1 ] != '/' ) { ptr[ 0 ] = '/'; ptr++; } ptr[ 0 ] = '\0'; attr_normalize_one( ad_olmDbDirectory, &bv, &nbv, NULL ); next->a_desc = ad_olmDbDirectory; next->a_vals = ch_calloc( sizeof( struct berval ), 2 ); next->a_vals[ 0 ] = bv; next->a_numvals = 1; if ( BER_BVISNULL( &nbv ) ) { next->a_nvals = next->a_vals; } else { next->a_nvals = ch_calloc( sizeof( struct berval ), 2 ); next->a_nvals[ 0 ] = nbv; } next = next->a_next; } cb = ch_calloc( sizeof( monitor_callback_t ), 1 ); cb->mc_update = bdb_monitor_update; #if 0 /* uncomment if required */ cb->mc_modify = bdb_monitor_modify; #endif cb->mc_free = bdb_monitor_free; cb->mc_private = (void *)bdb; /* make sure the database is registered; then add monitor attributes */ rc = mbe->register_database( be, &bdb->bi_monitor.bdm_ndn ); if ( rc == 0 ) { rc = mbe->register_entry_attrs( &bdb->bi_monitor.bdm_ndn, a, cb, &dummy, 0, &dummy ); } cleanup:; if ( rc != 0 ) { if ( cb != NULL ) { ch_free( cb ); cb = NULL; } if ( a != NULL ) { attrs_free( a ); a = NULL; } } /* store for cleanup */ bdb->bi_monitor.bdm_cb = (void *)cb; /* we don't need to keep track of the attributes, because * bdb_monitor_free() takes care of everything */ if ( a != NULL ) { attrs_free( a ); } return rc; }
/* We add two elements to the DN2ID database - a data item under the parent's * entryID containing the child's RDN and entryID, and an item under the * child's entryID containing the parent's entryID. */ int mdb_dn2id_add( Operation *op, MDB_cursor *mcp, MDB_cursor *mcd, ID pid, ID nsubs, int upsub, Entry *e ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; MDB_val key, data; ID nid; int rc, rlen, nrlen; diskNode *d; char *ptr; Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id_add 0x%lx: \"%s\"\n", e->e_id, e->e_ndn ? e->e_ndn : "" ); nrlen = dn_rdnlen( op->o_bd, &e->e_nname ); if (nrlen) { rlen = dn_rdnlen( op->o_bd, &e->e_name ); } else { nrlen = e->e_nname.bv_len; rlen = e->e_name.bv_len; } d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen + sizeof(ID), op->o_tmpmemctx); d->nrdnlen[1] = nrlen & 0xff; d->nrdnlen[0] = (nrlen >> 8) | 0x80; ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen ); *ptr++ = '\0'; ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen ); *ptr++ = '\0'; memcpy( ptr, &e->e_id, sizeof( ID )); ptr += sizeof( ID ); memcpy( ptr, &nsubs, sizeof( ID )); key.mv_size = sizeof(ID); key.mv_data = &nid; nid = pid; /* Need to make dummy root node once. Subsequent attempts * will fail harmlessly. */ if ( pid == 0 ) { diskNode dummy = {{0, 0}, "", "", ""}; data.mv_data = &dummy; data.mv_size = sizeof(diskNode); mdb_cursor_put( mcp, &key, &data, MDB_NODUPDATA ); } data.mv_data = d; data.mv_size = sizeof(diskNode) + rlen + nrlen + sizeof( ID ); /* Add our child node under parent's key */ rc = mdb_cursor_put( mcp, &key, &data, MDB_NODUPDATA ); /* Add our own node */ if (rc == 0) { int flag = MDB_NODUPDATA; nid = e->e_id; /* drop subtree count */ data.mv_size -= sizeof( ID ); ptr -= sizeof( ID ); memcpy( ptr, &pid, sizeof( ID )); d->nrdnlen[0] ^= 0x80; if ((slapMode & SLAP_TOOL_MODE) || (e->e_id == mdb_read_nextid(mdb))) flag |= MDB_APPEND; rc = mdb_cursor_put( mcd, &key, &data, flag ); } op->o_tmpfree( d, op->o_tmpmemctx ); /* Add our subtree count to all superiors */ if ( rc == 0 && upsub && pid ) { ID subs; nid = pid; do { /* Get parent's RDN */ rc = mdb_cursor_get( mcp, &key, &data, MDB_SET ); if ( !rc ) { char *p2; ptr = (char *)data.mv_data + data.mv_size - sizeof( ID ); memcpy( &nid, ptr, sizeof( ID )); /* Get parent's node under grandparent */ d = data.mv_data; rlen = ( d->nrdnlen[0] << 8 ) | d->nrdnlen[1]; p2 = op->o_tmpalloc( rlen + 2, op->o_tmpmemctx ); memcpy( p2, data.mv_data, rlen+2 ); *p2 ^= 0x80; data.mv_data = p2; rc = mdb_cursor_get( mcp, &key, &data, MDB_GET_BOTH ); op->o_tmpfree( p2, op->o_tmpmemctx ); if ( !rc ) { /* Get parent's subtree count */ ptr = (char *)data.mv_data + data.mv_size - sizeof( ID ); memcpy( &subs, ptr, sizeof( ID )); subs += nsubs; p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx ); memcpy( p2, data.mv_data, data.mv_size - sizeof( ID )); memcpy( p2+data.mv_size - sizeof( ID ), &subs, sizeof( ID )); data.mv_data = p2; rc = mdb_cursor_put( mcp, &key, &data, MDB_CURRENT ); op->o_tmpfree( p2, op->o_tmpmemctx ); } } if ( rc ) break; } while ( nid ); } Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id_add 0x%lx: %d\n", e->e_id, rc ); return rc; }
/* return IDs from root to parent of DN */ int mdb_dn2sups( Operation *op, MDB_txn *txn, struct berval *in, ID *ids ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; MDB_cursor *cursor; MDB_dbi dbi = mdb->mi_dn2id; MDB_val key, data; int rc = 0, nrlen; diskNode *d; char *ptr; ID pid, nid; struct berval tmp; Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2sups(\"%s\")\n", in->bv_val ); if ( !in->bv_len ) { goto done; } tmp = *in; nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len; tmp.bv_val += nrlen; tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len; nid = 0; key.mv_size = sizeof(ID); rc = mdb_cursor_open( txn, dbi, &cursor ); if ( rc ) goto done; for (;;) { key.mv_data = &pid; pid = nid; data.mv_size = sizeof(diskNode) + tmp.bv_len; d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx ); d->nrdnlen[1] = tmp.bv_len & 0xff; d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80; ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len ); *ptr = '\0'; data.mv_data = d; rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH ); op->o_tmpfree( d, op->o_tmpmemctx ); if ( rc ) { mdb_cursor_close( cursor ); break; } ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID); memcpy( &nid, ptr, sizeof(ID)); if ( pid ) mdb_idl_insert( ids, pid ); if ( tmp.bv_val > in->bv_val ) { for (ptr = tmp.bv_val - 2; ptr > in->bv_val && !DN_SEPARATOR(*ptr); ptr--) /* empty */; if ( ptr >= in->bv_val ) { if (DN_SEPARATOR(*ptr)) ptr++; tmp.bv_len = tmp.bv_val - ptr - 1; tmp.bv_val = ptr; } } else { break; } } done: if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2sups: get failed: %s (%d)\n", mdb_strerror( rc ), rc ); } return rc; }
static int pguid_repair_cb( Operation *op, SlapReply *rs ) { int rc; pguid_repair_cb_t *pcb = op->o_callback->sc_private; Entry *e = NULL; Attribute *a; struct berval pdn, pndn; switch ( rs->sr_type ) { case REP_SEARCH: break; case REP_SEARCHREF: case REP_RESULT: return rs->sr_err; default: assert( 0 ); } assert( rs->sr_entry != NULL ); dnParent( &rs->sr_entry->e_name, &pdn ); dnParent( &rs->sr_entry->e_nname, &pndn ); rc = overlay_entry_get_ov( op, &pndn, NULL, slap_schema.si_ad_entryUUID, 0, &e, pcb->on ); if ( rc != LDAP_SUCCESS || e == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: pguid_repair_cb: unable to get parent entry DN=\"%s\" (%d)\n", op->o_log_prefix, pdn.bv_val, rc ); return 0; } a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID ); if ( a == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: pguid_repair_cb: unable to find entryUUID of parent entry DN=\"%s\" (%d)\n", op->o_log_prefix, pdn.bv_val, rc ); } else { ber_len_t len; pguid_mod_t *mod; assert( a->a_numvals == 1 ); len = sizeof( pguid_mod_t ) + rs->sr_entry->e_nname.bv_len + 1 + a->a_vals[0].bv_len + 1; mod = op->o_tmpalloc( len, op->o_tmpmemctx ); mod->ndn.bv_len = rs->sr_entry->e_nname.bv_len; mod->ndn.bv_val = (char *)&mod[1]; mod->pguid.bv_len = a->a_vals[0].bv_len; mod->pguid.bv_val = (char *)&mod->ndn.bv_val[mod->ndn.bv_len + 1]; lutil_strncopy( mod->ndn.bv_val, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len ); lutil_strncopy( mod->pguid.bv_val, a->a_vals[0].bv_val, a->a_vals[0].bv_len ); mod->next = pcb->mods; pcb->mods = mod; Debug( LDAP_DEBUG_TRACE, "%s: pguid_repair_cb: scheduling entry DN=\"%s\" for repair\n", op->o_log_prefix, rs->sr_entry->e_name.bv_val, 0 ); } if ( e != NULL ) { (void)overlay_entry_release_ov( op, e, 0, pcb->on ); } return 0; }
static int OpenLDAPaciNormalizeRight( struct berval *action, struct berval *naction, void *ctx ) { struct berval grantdeny, perms = BER_BVNULL, bv = BER_BVNULL; int idx, i; /* grant|deny */ if ( acl_get_part( action, 0, ';', &grantdeny ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: missing ';' in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &grantdeny, ACIgrantdeny ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: '%s' must be grant or deny\n", grantdeny.bv_val ); return LDAP_INVALID_SYNTAX; } ber_dupbv_x( naction, (struct berval *)ACIgrantdeny[ idx ], ctx ); for ( i = 1; acl_get_part( action, i, ';', &bv ) >= 0; i++ ) { struct berval nattrs = BER_BVNULL; int freenattrs = 1; if ( i & 1 ) { /* perms */ if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } perms = bv; } else { /* attr */ char *ptr; /* could be "[all]" or an attribute description */ if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; } else { AttributeDescription *ad = NULL; AttributeDescription adstatic= { 0 }; const char *text = NULL; struct berval attr, left, right; int j; int len; for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ ) { ad = NULL; text = NULL; /* openldap 2.1 aci compabitibility [entry] -> entry */ if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ENTRY ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_ENTRY ]; /* openldap 2.1 aci compabitibility [children] -> children */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_CHILDREN ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_CHILDREN ]; /* openldap 2.1 aci compabitibility [all] -> only [all] */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { ber_memfree_x( nattrs.bv_val, ctx ); nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; break; } else if ( acl_get_part( &attr, 0, '=', &left ) < 0 || acl_get_part( &attr, 1, '=', &right ) < 0 ) { if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", attr.bv_val ); return LDAP_INVALID_SYNTAX; } } else { if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", left.bv_val ); return LDAP_INVALID_SYNTAX; } } len = nattrs.bv_len + ( !BER_BVISEMPTY( &nattrs ) ? STRLENOF( "," ) : 0 ) + ad->ad_cname.bv_len; nattrs.bv_val = ber_memrealloc_x( nattrs.bv_val, len + 1, ctx ); ptr = &nattrs.bv_val[ nattrs.bv_len ]; if ( !BER_BVISEMPTY( &nattrs ) ) { *ptr++ = ','; } ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); ptr[ 0 ] = '\0'; nattrs.bv_len = len; } } naction->bv_val = ber_memrealloc_x( naction->bv_val, naction->bv_len + STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len + 1, ctx ); ptr = &naction->bv_val[ naction->bv_len ]; ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, perms.bv_val, perms.bv_len ); ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, nattrs.bv_val, nattrs.bv_len ); ptr[ 0 ] = '\0'; naction->bv_len += STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len; if ( freenattrs ) { ber_memfree_x( nattrs.bv_val, ctx ); } } } /* perms;attr go in pairs */ if ( i > 1 && ( i & 1 ) ) { return LDAP_SUCCESS; } else { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: perms:attr need to be pairs in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } }
int hdb_dn2id( Operation *op, struct berval *in, EntryInfo *ei, DB_TXN *txn, DBC **cursor ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; DBT key, data; int rc = 0, nrlen; diskNode *d; char *ptr; unsigned char dlen[2]; ID idp, parentID; Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 ); nrlen = dn_rdnlen( op->o_bd, in ); if (!nrlen) nrlen = in->bv_len; DBTzero(&key); key.size = sizeof(ID); key.data = &idp; key.ulen = sizeof(ID); key.flags = DB_DBT_USERMEM; parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0; BDB_ID2DISK( parentID, &idp ); DBTzero(&data); data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1; data.ulen = data.size * 3; data.dlen = data.ulen; data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags ); if ( rc ) return rc; d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx ); d->nrdnlen[1] = nrlen & 0xff; d->nrdnlen[0] = (nrlen >> 8) | 0x80; dlen[0] = d->nrdnlen[0]; dlen[1] = d->nrdnlen[1]; ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen ); *ptr = '\0'; data.data = d; rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE ); if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] || strncmp( d->nrdn, in->bv_val, nrlen ))) { rc = DB_NOTFOUND; } if ( rc == 0 ) { ptr = (char *) data.data + data.size - sizeof(ID); BDB_DISK2ID( ptr, &ei->bei_id ); ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen; ptr = d->nrdn + nrlen + 1; ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn ); if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) { db_recno_t dkids; /* How many children does the parent have? */ /* FIXME: do we need to lock the parent * entryinfo? Seems safe... */ (*cursor)->c_count( *cursor, &dkids, 0 ); ei->bei_parent->bei_dkids = dkids; } } op->o_tmpfree( d, op->o_tmpmemctx ); if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n", db_strerror( rc ), rc, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n", ei->bei_id, 0, 0 ); } return rc; }
static int collect_cf( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; int rc = 1, idx; switch( c->op ) { case SLAP_CONFIG_EMIT: { collect_info *ci; for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) { struct berval bv; char *ptr; int len; /* calculate the length & malloc memory */ bv.bv_len = ci->ci_dn.bv_len + STRLENOF("\"\" "); for (idx=0; idx<ci->ci_ad_num; idx++) { bv.bv_len += ci->ci_ad[idx]->ad_cname.bv_len; if (idx<(ci->ci_ad_num-1)) { bv.bv_len++; } } bv.bv_val = ch_malloc( bv.bv_len + 1 ); /* copy the value and update len */ len = snprintf( bv.bv_val, bv.bv_len + 1, "\"%s\" ", ci->ci_dn.bv_val); ptr = bv.bv_val + len; for (idx=0; idx<ci->ci_ad_num; idx++) { ptr = lutil_strncopy( ptr, ci->ci_ad[idx]->ad_cname.bv_val, ci->ci_ad[idx]->ad_cname.bv_len); if (idx<(ci->ci_ad_num-1)) { *ptr++ = ','; } } *ptr = '\0'; bv.bv_len = ptr - bv.bv_val; ber_bvarray_add( &c->rvalue_vals, &bv ); rc = 0; } } break; case LDAP_MOD_DELETE: if ( c->valx == -1 ) { /* Delete entire attribute */ collect_info *ci; while (( ci = on->on_bi.bi_private )) { on->on_bi.bi_private = ci->ci_next; ch_free( ci->ci_dn.bv_val ); ch_free( ci ); } } else { /* Delete just one value */ collect_info **cip, *ci; int i; cip = (collect_info **)&on->on_bi.bi_private; ci = *cip; for ( i=0; i < c->valx; i++ ) { cip = &ci->ci_next; ci = *cip; } *cip = ci->ci_next; ch_free( ci->ci_dn.bv_val ); ch_free( ci ); } rc = 0; break; case SLAP_CONFIG_ADD: case LDAP_MOD_ADD: { collect_info *ci; struct berval bv, dn; const char *text; int idx, count=0; char *arg; /* count delimiters in attribute argument */ arg = strtok(c->argv[2], ","); while (arg!=NULL) { count++; arg = strtok(NULL, ","); } /* validate and normalize dn */ ber_str2bv( c->argv[1], 0, 0, &bv ); if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"", c->argv[0], c->argv[1] ); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); return ARG_BAD_CONF; } /* check for duplicate DNs */ for ( ci = (collect_info *)on->on_bi.bi_private; ci; ci = ci->ci_next ) { /* If new DN is longest, there are no possible matches */ if ( dn.bv_len > ci->ci_dn.bv_len ) { ci = NULL; break; } if ( bvmatch( &dn, &ci->ci_dn )) { break; } } if ( ci ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s DN already configured: \"%s\"", c->argv[0], c->argv[1] ); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); return ARG_BAD_CONF; } /* allocate config info with room for attribute array */ ci = ch_malloc( sizeof( collect_info ) + sizeof( AttributeDescription * ) * count ); /* load attribute description for attribute list */ arg = c->argv[2]; for( idx=0; idx<count; idx++) { ci->ci_ad[idx] = NULL; if ( slap_str2ad( arg, &ci->ci_ad[idx], &text ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"", c->argv[0], arg); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); ch_free( ci ); return ARG_BAD_CONF; } while(*arg!='\0') { arg++; /* skip to end of argument */ } if (idx<count-1) { arg++; /* skip inner delimiters */ } } /* The on->on_bi.bi_private pointer can be used for * anything this instance of the overlay needs. */ ci->ci_ad[count] = NULL; ci->ci_ad_num = count; ci->ci_dn = dn; /* creates list of ci's ordered by dn length */ insert_ordered ( on, ci ); /* New ci wasn't simply appended to end, adjust its * position in the config entry's a_vals */ if ( c->ca_entry && ci->ci_next ) { Attribute *a = attr_find( c->ca_entry->e_attrs, collectcfg[0].ad ); if ( a ) { struct berval bv, nbv; collect_info *c2 = (collect_info *)on->on_bi.bi_private; int i, j; for ( i=0; c2 != ci; i++, c2 = c2->ci_next ); bv = a->a_vals[a->a_numvals-1]; nbv = a->a_nvals[a->a_numvals-1]; for ( j=a->a_numvals-1; j>i; j-- ) { a->a_vals[j] = a->a_vals[j-1]; a->a_nvals[j] = a->a_nvals[j-1]; } a->a_vals[j] = bv; a->a_nvals[j] = nbv; } } rc = 0; } } return rc; }
int slap_bv2ad( struct berval *bv, AttributeDescription **ad, const char **text ) { int rtn = LDAP_UNDEFINED_TYPE; AttributeDescription desc, *d2; char *name, *options, *optn; char *opt, *next; int ntags; int tagslen; /* hardcoded limits for speed */ #define MAX_TAGGING_OPTIONS 128 struct berval tags[MAX_TAGGING_OPTIONS+1]; #define MAX_TAGS_LEN 1024 char tagbuf[MAX_TAGS_LEN]; assert( ad != NULL ); assert( *ad == NULL ); /* temporary */ if( bv == NULL || BER_BVISNULL( bv ) || BER_BVISEMPTY( bv ) ) { *text = "empty AttributeDescription"; return rtn; } /* make sure description is IA5 */ if( ad_keystring( bv ) ) { *text = "AttributeDescription contains inappropriate characters"; return rtn; } /* find valid base attribute type; parse in place */ desc.ad_cname = *bv; desc.ad_flags = 0; BER_BVZERO( &desc.ad_tags ); name = bv->bv_val; options = ber_bvchr( bv, ';' ); if ( options != NULL && (unsigned) ( options - name ) < bv->bv_len ) { /* don't go past the end of the berval! */ desc.ad_cname.bv_len = options - name; } else { options = NULL; } desc.ad_type = at_bvfind( &desc.ad_cname ); if( desc.ad_type == NULL ) { *text = "attribute type undefined"; return rtn; } if( is_at_operational( desc.ad_type ) && options != NULL ) { *text = "operational attribute with options undefined"; return rtn; } /* * parse options in place */ ntags = 0; tagslen = 0; optn = bv->bv_val + bv->bv_len; for( opt=options; opt != NULL; opt=next ) { int optlen; opt++; next = strchrlen( opt, optn, ';', &optlen ); if( optlen == 0 ) { *text = "zero length option is invalid"; return rtn; } else if ( optlen == STRLENOF("binary") && strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 ) { /* binary option */ if( slap_ad_is_binary( &desc ) ) { *text = "option \"binary\" specified multiple times"; return rtn; } if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) { /* not stored in binary, disallow option */ *text = "option \"binary\" not supported with type"; return rtn; } desc.ad_flags |= SLAP_DESC_BINARY; continue; } else if ( ad_find_option_definition( opt, optlen ) ) { int i; if( opt[optlen-1] == '-' || ( opt[optlen-1] == '=' && msad_range_hack )) { desc.ad_flags |= SLAP_DESC_TAG_RANGE; } if( ntags >= MAX_TAGGING_OPTIONS ) { *text = "too many tagging options"; return rtn; } /* * tags should be presented in sorted order, * so run the array in reverse. */ for( i=ntags-1; i>=0; i-- ) { int rc; rc = strncasecmp( opt, tags[i].bv_val, (unsigned) optlen < tags[i].bv_len ? (unsigned) optlen : tags[i].bv_len ); if( rc == 0 && (unsigned)optlen == tags[i].bv_len ) { /* duplicate (ignore) */ ntags--; goto done; } else if ( rc > 0 || ( rc == 0 && (unsigned)optlen > tags[i].bv_len )) { AC_MEMCPY( &tags[i+2], &tags[i+1], (ntags-i-1)*sizeof(struct berval) ); tags[i+1].bv_val = opt; tags[i+1].bv_len = optlen; goto done; } } if( ntags ) { AC_MEMCPY( &tags[1], &tags[0], ntags*sizeof(struct berval) ); } tags[0].bv_val = opt; tags[0].bv_len = optlen; done:; tagslen += optlen + 1; ntags++; } else { *text = "unrecognized option"; return rtn; } } if( ntags > 0 ) { int i; if( tagslen > MAX_TAGS_LEN ) { *text = "tagging options too long"; return rtn; } desc.ad_tags.bv_val = tagbuf; tagslen = 0; for( i=0; i<ntags; i++ ) { AC_MEMCPY( &desc.ad_tags.bv_val[tagslen], tags[i].bv_val, tags[i].bv_len ); tagslen += tags[i].bv_len; desc.ad_tags.bv_val[tagslen++] = ';'; } desc.ad_tags.bv_val[--tagslen] = '\0'; desc.ad_tags.bv_len = tagslen; } /* see if a matching description is already cached */ for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) { if( d2->ad_flags != desc.ad_flags ) { continue; } if( d2->ad_tags.bv_len != desc.ad_tags.bv_len ) { continue; } if( d2->ad_tags.bv_len == 0 ) { break; } if( strncasecmp( d2->ad_tags.bv_val, desc.ad_tags.bv_val, desc.ad_tags.bv_len ) == 0 ) { break; } } /* Not found, add new one */ while (d2 == NULL) { size_t dlen = 0; ldap_pvt_thread_mutex_lock( &desc.ad_type->sat_ad_mutex ); /* check again now that we've locked */ for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) { if (d2->ad_flags != desc.ad_flags) continue; if (d2->ad_tags.bv_len != desc.ad_tags.bv_len) continue; if (d2->ad_tags.bv_len == 0) break; if (strncasecmp(d2->ad_tags.bv_val, desc.ad_tags.bv_val, desc.ad_tags.bv_len) == 0) break; } if (d2) { ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex ); break; } /* Allocate a single contiguous block. If there are no * options, we just need space for the AttrDesc structure. * Otherwise, we need to tack on the full name length + * options length, + maybe tagging options length again. */ if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) { dlen = desc.ad_type->sat_cname.bv_len + 1; if (desc.ad_tags.bv_len) { dlen += 1 + desc.ad_tags.bv_len; } if ( slap_ad_is_binary( &desc ) ) { dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len; } } d2 = ch_malloc(sizeof(AttributeDescription) + dlen); d2->ad_next = NULL; d2->ad_type = desc.ad_type; d2->ad_flags = desc.ad_flags; d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len; d2->ad_tags.bv_len = desc.ad_tags.bv_len; ldap_pvt_thread_mutex_lock( &ad_index_mutex ); d2->ad_index = ++ad_count; ldap_pvt_thread_mutex_unlock( &ad_index_mutex ); if (dlen == 0) { d2->ad_cname.bv_val = d2->ad_type->sat_cname.bv_val; d2->ad_tags.bv_val = NULL; } else { char *cp, *op, *lp; int j; d2->ad_cname.bv_val = (char *)(d2+1); strcpy(d2->ad_cname.bv_val, d2->ad_type->sat_cname.bv_val); cp = d2->ad_cname.bv_val + d2->ad_cname.bv_len; if( slap_ad_is_binary( &desc ) ) { op = cp; lp = NULL; if( desc.ad_tags.bv_len ) { lp = desc.ad_tags.bv_val; while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0 && (lp = strchr( lp, ';' )) != NULL ) ++lp; if( lp != desc.ad_tags.bv_val ) { *cp++ = ';'; j = (lp ? (unsigned) (lp - desc.ad_tags.bv_val - 1) : strlen( desc.ad_tags.bv_val )); cp = lutil_strncopy(cp, desc.ad_tags.bv_val, j); } } cp = lutil_strcopy(cp, ";binary"); if( lp != NULL ) { *cp++ = ';'; cp = lutil_strcopy(cp, lp); } d2->ad_cname.bv_len = cp - d2->ad_cname.bv_val; if( desc.ad_tags.bv_len ) ldap_pvt_str2lower(op); j = 1; } else { j = 0; } if( desc.ad_tags.bv_len ) { lp = d2->ad_cname.bv_val + d2->ad_cname.bv_len + j; if ( j == 0 ) *lp++ = ';'; d2->ad_tags.bv_val = lp; strcpy(lp, desc.ad_tags.bv_val); ldap_pvt_str2lower(lp); if( j == 0 ) d2->ad_cname.bv_len += 1 + desc.ad_tags.bv_len; } } /* Add new desc to list. We always want the bare Desc with * no options to stay at the head of the list, assuming * that one will be used most frequently. */ if (desc.ad_type->sat_ad == NULL || dlen == 0) { d2->ad_next = desc.ad_type->sat_ad; desc.ad_type->sat_ad = d2; } else { d2->ad_next = desc.ad_type->sat_ad->ad_next; desc.ad_type->sat_ad->ad_next = d2; } ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex ); } if( *ad == NULL ) { *ad = d2; } else { **ad = *d2; } return LDAP_SUCCESS; }
static int constraint_cf_gen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)(c->bi); constraint *cn = on->on_bi.bi_private, *cp; struct berval bv; int i, rc = 0; constraint ap = { NULL }; const char *text = NULL; switch ( c->op ) { case SLAP_CONFIG_EMIT: switch (c->type) { case CONSTRAINT_ATTRIBUTE: for (cp=cn; cp; cp=cp->ap_next) { char *s; char *tstr = NULL; int quotes = 0; int j; bv.bv_len = STRLENOF(" "); for (j = 0; cp->ap[j]; j++) { bv.bv_len += cp->ap[j]->ad_cname.bv_len; } /* room for commas */ bv.bv_len += j - 1; if (cp->re) { tstr = REGEX_STR; } else if (cp->lud) { tstr = URI_STR; quotes = 1; } else if (cp->set) { tstr = SET_STR; quotes = 1; } else if (cp->size) { tstr = SIZE_STR; } else if (cp->count) { tstr = COUNT_STR; } bv.bv_len += strlen(tstr); bv.bv_len += cp->val.bv_len + 2*quotes; if (cp->restrict_lud != NULL) { bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\""); } s = bv.bv_val = ch_malloc(bv.bv_len + 1); s = lutil_strncopy( s, cp->ap[0]->ad_cname.bv_val, cp->ap[0]->ad_cname.bv_len ); for (j = 1; cp->ap[j]; j++) { *s++ = ','; s = lutil_strncopy( s, cp->ap[j]->ad_cname.bv_val, cp->ap[j]->ad_cname.bv_len ); } *s++ = ' '; s = lutil_strcopy( s, tstr ); *s++ = ' '; if ( quotes ) *s++ = '"'; s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len ); if ( quotes ) *s++ = '"'; if (cp->restrict_lud != NULL) { s = lutil_strcopy( s, " restrict=\"" ); s = lutil_strncopy( s, cp->restrict_val.bv_val, cp->restrict_val.bv_len ); *s++ = '"'; } *s = '\0'; rc = value_add_one( &c->rvalue_vals, &bv ); if (rc == LDAP_SUCCESS) rc = value_add_one( &c->rvalue_nvals, &bv ); ch_free(bv.bv_val); if (rc) return rc; } break; default: abort(); break; } break; case LDAP_MOD_DELETE: switch (c->type) { case CONSTRAINT_ATTRIBUTE: if (!cn) break; /* nothing to do */ if (c->valx < 0) { /* zap all constraints */ while (cn) { cp = cn->ap_next; constraint_free( cn, 1 ); cn = cp; } on->on_bi.bi_private = NULL; } else { constraint **cpp; /* zap constraint numbered 'valx' */ for(i=0, cp = cn, cpp = &cn; (cp) && (i<c->valx); i++, cpp = &cp->ap_next, cp = *cpp); if (cp) { /* zap cp, and join cpp to cp->ap_next */ *cpp = cp->ap_next; constraint_free( cp, 1 ); } on->on_bi.bi_private = cn; } break; default: abort(); break; } break; case SLAP_CONFIG_ADD: case LDAP_MOD_ADD: switch (c->type) { case CONSTRAINT_ATTRIBUTE: { int j; char **attrs = ldap_str2charray( c->argv[1], "," ); for ( j = 0; attrs[j]; j++) /* just count */ ; ap.ap = ch_calloc( sizeof(AttributeDescription*), j + 1 ); for ( j = 0; attrs[j]; j++) { if ( slap_str2ad( attrs[j], &ap.ap[j], &text ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], attrs[j], text ); rc = ARG_BAD_CONF; goto done; } } if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) { int err; ap.re = ch_malloc( sizeof(regex_t) ); if ((err = regcomp( ap.re, c->argv[3], REG_EXTENDED )) != 0) { char errmsg[1024]; regerror( err, ap.re, errmsg, sizeof(errmsg) ); ch_free(ap.re); snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Illegal regular expression \"%s\": Error %s", c->argv[0], c->argv[1], c->argv[3], errmsg); ap.re = NULL; rc = ARG_BAD_CONF; goto done; } ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) { size_t size; if ( ( size = atoi(c->argv[3]) ) != 0 ) ap.size = size; } else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) { size_t count; if ( ( count = atoi(c->argv[3]) ) != 0 ) ap.count = count; } else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) { int err; err = ldap_url_parse(c->argv[3], &ap.lud); if ( err != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Invalid URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); rc = ARG_BAD_CONF; goto done; } if (ap.lud->lud_host != NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unsupported hostname in URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); ldap_free_urldesc(ap.lud); rc = ARG_BAD_CONF; goto done; } for ( i=0; ap.lud->lud_attrs[i]; i++); /* FIXME: This is worthless without at least one attr */ if ( i ) { ap.attrs = ch_malloc( (i+1)*sizeof(AttributeDescription *)); for ( i=0; ap.lud->lud_attrs[i]; i++) { ap.attrs[i] = NULL; if ( slap_str2ad( ap.lud->lud_attrs[i], &ap.attrs[i], &text ) ) { ch_free( ap.attrs ); snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text ); rc = ARG_BAD_CONF; goto done; } } ap.attrs[i] = NULL; } if (ap.lud->lud_dn == NULL) { ap.lud->lud_dn = ch_strdup(""); } else { struct berval dn, ndn; ber_str2bv( ap.lud->lud_dn, 0, 0, &dn ); if (dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) ) { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: URI %s DN normalization failed", c->argv[0], c->argv[1], c->argv[3] ); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); rc = ARG_BAD_CONF; goto done; } ldap_memfree( ap.lud->lud_dn ); ap.lud->lud_dn = ndn.bv_val; } if (ap.lud->lud_filter == NULL) { ap.lud->lud_filter = ch_strdup("objectClass=*"); } else if ( ap.lud->lud_filter[0] == '(' ) { ber_len_t len = strlen( ap.lud->lud_filter ); if ( ap.lud->lud_filter[len - 1] != ')' ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: invalid URI filter: %s", c->argv[0], c->argv[1], ap.lud->lud_filter ); rc = ARG_BAD_CONF; goto done; } AC_MEMCPY( &ap.lud->lud_filter[0], &ap.lud->lud_filter[1], len - 2 ); ap.lud->lud_filter[len - 2] = '\0'; } ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) { ap.set = 1; ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Unknown constraint type: %s", c->argv[0], c->argv[1], c->argv[2] ); rc = ARG_BAD_CONF; goto done; } if ( c->argc > 4 ) { int argidx; for ( argidx = 4; argidx < c->argc; argidx++ ) { if ( strncasecmp( c->argv[argidx], "restrict=", STRLENOF("restrict=") ) == 0 ) { int err; char *arg = c->argv[argidx] + STRLENOF("restrict="); err = ldap_url_parse(arg, &ap.restrict_lud); if ( err != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Invalid restrict URI \"%s\"", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } if (ap.restrict_lud->lud_host != NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unsupported hostname in restrict URI \"%s\"", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } if ( ap.restrict_lud->lud_attrs != NULL ) { if ( ap.restrict_lud->lud_attrs[0] != '\0' ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: attrs not allowed in restrict URI %s\n", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } ldap_memvfree((void *)ap.restrict_lud->lud_attrs); ap.restrict_lud->lud_attrs = NULL; } if (ap.restrict_lud->lud_dn != NULL) { if (ap.restrict_lud->lud_dn[0] == '\0') { ldap_memfree(ap.restrict_lud->lud_dn); ap.restrict_lud->lud_dn = NULL; } else { struct berval dn, ndn; int j; ber_str2bv(ap.restrict_lud->lud_dn, 0, 0, &dn); if (dnNormalize(0, NULL, NULL, &dn, &ndn, NULL)) { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI %s DN normalization failed", c->argv[0], c->argv[1], arg ); rc = ARG_BAD_CONF; goto done; } assert(c->be != NULL); if (c->be->be_nsuffix == NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI requires suffix", c->argv[0], c->argv[1] ); rc = ARG_BAD_CONF; goto done; } for ( j = 0; !BER_BVISNULL(&c->be->be_nsuffix[j]); j++) { if (dnIsSuffix(&ndn, &c->be->be_nsuffix[j])) break; } if (BER_BVISNULL(&c->be->be_nsuffix[j])) { /* error */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI DN %s not within database naming context(s)", c->argv[0], c->argv[1], dn.bv_val ); rc = ARG_BAD_CONF; goto done; } ap.restrict_ndn = ndn; } } if (ap.restrict_lud->lud_filter != NULL) { ap.restrict_filter = str2filter(ap.restrict_lud->lud_filter); if (ap.restrict_filter == NULL) { /* error */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI filter %s invalid", c->argv[0], c->argv[1], ap.restrict_lud->lud_filter ); rc = ARG_BAD_CONF; goto done; } } ber_str2bv(c->argv[argidx], 0, 1, &ap.restrict_val); } else { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unrecognized arg #%d (%s)", c->argv[0], c->argv[1], argidx, c->argv[argidx] ); rc = ARG_BAD_CONF; goto done; } } } done:; if ( rc == LDAP_SUCCESS ) { constraint *a2 = ch_calloc( sizeof(constraint), 1 ); a2->ap_next = on->on_bi.bi_private; a2->ap = ap.ap; a2->re = ap.re; a2->val = ap.val; a2->lud = ap.lud; a2->set = ap.set; a2->size = ap.size; a2->count = ap.count; if ( a2->lud ) { ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn); ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter); } a2->attrs = ap.attrs; a2->restrict_lud = ap.restrict_lud; a2->restrict_ndn = ap.restrict_ndn; a2->restrict_filter = ap.restrict_filter; a2->restrict_val = ap.restrict_val; on->on_bi.bi_private = a2; } else { Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg, 0 ); constraint_free( &ap, 0 ); } ldap_memvfree((void**)attrs); } break; default: abort(); break; } break; default: abort(); } return rc; }
/* We add two elements to the DN2ID database - a data item under the parent's * entryID containing the child's RDN and entryID, and an item under the * child's entryID containing the parent's entryID. */ int hdb_dn2id_add( Operation *op, DB_TXN *txn, EntryInfo *eip, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; DBT key, data; ID nid; int rc, rlen, nrlen; diskNode *d; char *ptr; Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_add 0x%lx: \"%s\"\n", e->e_id, e->e_ndn, 0 ); nrlen = dn_rdnlen( op->o_bd, &e->e_nname ); if (nrlen) { rlen = dn_rdnlen( op->o_bd, &e->e_name ); } else { nrlen = e->e_nname.bv_len; rlen = e->e_name.bv_len; } d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx); d->nrdnlen[1] = nrlen & 0xff; d->nrdnlen[0] = (nrlen >> 8) | 0x80; ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen ); *ptr++ = '\0'; ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen ); *ptr++ = '\0'; BDB_ID2DISK( e->e_id, ptr ); DBTzero(&key); DBTzero(&data); key.size = sizeof(ID); key.flags = DB_DBT_USERMEM; BDB_ID2DISK( eip->bei_id, &nid ); key.data = &nid; /* Need to make dummy root node once. Subsequent attempts * will fail harmlessly. */ if ( eip->bei_id == 0 ) { diskNode dummy = {{0, 0}, "", "", ""}; data.data = &dummy; data.size = sizeof(diskNode); data.flags = DB_DBT_USERMEM; db->put( db, txn, &key, &data, DB_NODUPDATA ); } data.data = d; data.size = sizeof(diskNode) + rlen + nrlen; data.flags = DB_DBT_USERMEM; rc = db->put( db, txn, &key, &data, DB_NODUPDATA ); if (rc == 0) { BDB_ID2DISK( e->e_id, &nid ); BDB_ID2DISK( eip->bei_id, ptr ); d->nrdnlen[0] ^= 0x80; rc = db->put( db, txn, &key, &data, DB_NODUPDATA ); } /* Update all parents' IDL cache entries */ if ( rc == 0 && bdb->bi_idl_cache_size ) { ID tmp[2]; char *ptr = ((char *)&tmp[1])-1; key.data = ptr; key.size = sizeof(ID)+1; tmp[1] = eip->bei_id; *ptr = DN_ONE_PREFIX; bdb_idl_cache_add_id( bdb, db, &key, e->e_id ); if ( eip->bei_parent ) { *ptr = DN_SUBTREE_PREFIX; for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) { tmp[1] = eip->bei_id; bdb_idl_cache_add_id( bdb, db, &key, e->e_id ); } /* Handle DB with empty suffix */ if ( !op->o_bd->be_suffix[0].bv_len && eip ) { tmp[1] = eip->bei_id; bdb_idl_cache_add_id( bdb, db, &key, e->e_id ); } } } op->o_tmpfree( d, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 ); return rc; }
static int dl_cfgen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; int rc = 0, i; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) { case DL_ATTRSET: for ( i = 0; dli; i++, dli = dli->dli_next ) { struct berval bv; char *ptr = c->cr_msg; dynlist_map_t *dlm; assert( dli->dli_oc != NULL ); assert( dli->dli_ad != NULL ); /* FIXME: check buffer overflow! */ ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ), SLAP_X_ORDERED_FMT "%s", i, dli->dli_oc->soc_cname.bv_val ); if ( !BER_BVISNULL( &dli->dli_uri ) ) { *ptr++ = ' '; *ptr++ = '"'; ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val, dli->dli_uri.bv_len ); *ptr++ = '"'; } *ptr++ = ' '; ptr = lutil_strncopy( ptr, dli->dli_ad->ad_cname.bv_val, dli->dli_ad->ad_cname.bv_len ); for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { ptr[ 0 ] = ' '; ptr++; if ( dlm->dlm_mapped_ad ) { ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val ); ptr[ 0 ] = ':'; ptr++; } ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val ); } bv.bv_val = c->cr_msg; bv.bv_len = ptr - bv.bv_val; value_add_one( &c->rvalue_vals, &bv ); } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case DL_ATTRSET: if ( c->valx < 0 ) { dynlist_info_t *dli_next; for ( dli_next = dli; dli_next; dli = dli_next ) { dynlist_map_t *dlm = dli->dli_dlm; dynlist_map_t *dlm_next; dli_next = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); } on->on_bi.bi_private = NULL; } else { dynlist_info_t **dlip; dynlist_map_t *dlm; dynlist_map_t *dlm_next; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { return 1; } dlip = &(*dlip)->dli_next; } dli = *dlip; *dlip = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); dlm = dli->dli_dlm; while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); dli = (dynlist_info_t *)on->on_bi.bi_private; } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } switch( c->type ) { case DL_ATTRSET: { dynlist_info_t **dlip, *dli_next = NULL; ObjectClass *oc = NULL; AttributeDescription *ad = NULL; int attridx = 2; LDAPURLDesc *lud = NULL; struct berval nbase = BER_BVNULL; Filter *filter = NULL; struct berval uri = BER_BVNULL; dynlist_map_t *dlm = NULL, *dlml = NULL; const char *text; oc = oc_find( c->argv[ 1 ] ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find ObjectClass \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) { if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to parse URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_host != NULL ) { if ( lud->lud_host[0] == '\0' ) { ch_free( lud->lud_host ); lud->lud_host = NULL; } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "host not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } if ( lud->lud_attrs != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "attrs not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_exts != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "extensions not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) { struct berval dn; ber_str2bv( lud->lud_dn, 0, 0, &dn ); rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "DN normalization failed in URI \"%s\"", c->argv[ attridx ] ); goto done_uri; } } if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) { filter = str2filter( lud->lud_filter ); if ( filter == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "filter parsing failed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } ber_str2bv( c->argv[ attridx ], 0, 1, &uri ); done_uri:; if ( rc ) { if ( lud ) { ldap_free_urldesc( lud ); } if ( !BER_BVISNULL( &nbase ) ) { ber_memfree( nbase.bv_val ); } if ( filter != NULL ) { filter_free( filter ); } while ( dlm != NULL ) { dlml = dlm; dlm = dlm->dlm_next; ch_free( dlml ); } Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return rc; } attridx++; } rc = slap_str2ad( c->argv[ attridx ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription \"%s\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } attridx++; for ( i = attridx; i < c->argc; i++ ) { char *arg; char *cp; AttributeDescription *member_ad = NULL; AttributeDescription *mapped_ad = NULL; dynlist_map_t *dlmp; /* * If no mapped attribute is given, dn is used * for backward compatibility. */ arg = c->argv[i]; if ( ( cp = strchr( arg, ':' ) ) != NULL ) { struct berval bv; ber_str2bv( arg, cp - arg, 0, &bv ); rc = slap_bv2ad( &bv, &mapped_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find mapped AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } arg = cp + 1; } rc = slap_str2ad( arg, &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); if ( dlm == NULL ) { dlm = dlmp; } dlmp->dlm_member_ad = member_ad; dlmp->dlm_mapped_ad = mapped_ad; dlmp->dlm_next = NULL; if ( dlml != NULL ) dlml->dlm_next = dlmp; dlml = dlmp; } if ( c->valx > 0 ) { int i; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "invalid index {%d}\n", c->valx ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlip = &(*dlip)->dli_next; } dli_next = *dlip; } else { for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) /* goto last */; } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = dlm; (*dlip)->dli_next = dli_next; (*dlip)->dli_lud = lud; (*dlip)->dli_uri_nbase = nbase; (*dlip)->dli_uri_filter = filter; (*dlip)->dli_uri = uri; rc = dynlist_build_def_filter( *dlip ); } break; case DL_ATTRPAIR_COMPAT: snprintf( c->cr_msg, sizeof( c->cr_msg ), "warning: \"attrpair\" only supported for limited " "backward compatibility with overlay \"dyngroup\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); /* fallthru */ case DL_ATTRPAIR: { dynlist_info_t **dlip; ObjectClass *oc = NULL; AttributeDescription *ad = NULL, *member_ad = NULL; const char *text; oc = oc_find( "groupOfURLs" ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find default ObjectClass \"groupOfURLs\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 2 ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"\n", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) { /* * The same URL attribute / member attribute pair * cannot be repeated, but we enforce this only * when the member attribute is unique. Performing * the check for multiple values would require * sorting and comparing the lists, which is left * as a future improvement */ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_dlm->dlm_next == NULL && member_ad == (*dlip)->dli_dlm->dlm_member_ad ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "URL attributeDescription \"%s\" already mapped.\n", ad->ad_cname.bv_val ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); #if 0 /* make it a warning... */ return 1; #endif } } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); (*dlip)->dli_dlm->dlm_member_ad = member_ad; (*dlip)->dli_dlm->dlm_mapped_ad = NULL; rc = dynlist_build_def_filter( *dlip ); } break; default: rc = 1; break; } return rc; }
int do_search( Operation *op, /* info about the op to which we're responding */ SlapReply *rs /* all the response data we'll send */ ) { struct berval base = BER_BVNULL; ber_len_t siz, off, i; Debug( LDAP_DEBUG_TRACE, "%s do_search\n", op->o_log_prefix, 0, 0 ); /* * Parse the search request. It looks like this: * * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2), * subordinate (3) -- OpenLDAP extension * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } */ /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ if ( ber_scanf( op->o_ber, "{miiiib" /*}*/, &base, &op->ors_scope, &op->ors_deref, &op->ors_slimit, &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" ); goto return_results; } if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" ); goto return_results; } switch( op->ors_scope ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" ); goto return_results; } switch( op->ors_deref ) { case LDAP_DEREF_NEVER: case LDAP_DEREF_FINDING: case LDAP_DEREF_SEARCHING: case LDAP_DEREF_ALWAYS: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" ); goto return_results; } rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n", op->o_log_prefix, base.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto return_results; } Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base.bv_val, op->ors_scope, op->ors_deref ); Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", op->ors_slimit, op->ors_tlimit, op->ors_attrsonly); /* filter - returns a "normalized" version */ rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { if( rs->sr_err == SLAPD_DISCONNECT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; send_ldap_disconnect( op, rs ); rs->sr_err = SLAPD_DISCONNECT; } else { send_ldap_result( op, rs ); } goto return_results; } filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); Debug( LDAP_DEBUG_ARGS, " filter: %s\n", !BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 ); /* attributes */ siz = sizeof(AttributeName); off = offsetof(AttributeName,an_name); if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } for ( i=0; i<siz; i++ ) { const char *dummy; /* ignore msgs from bv2ad */ op->ors_attrs[i].an_desc = NULL; op->ors_attrs[i].an_oc = NULL; op->ors_attrs[i].an_flags = 0; if ( slap_bv2ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS ) { if ( slap_bv2undef_ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ) ) { struct berval *bv = &op->ors_attrs[i].an_name; /* RFC 4511 LDAPv3: All User Attributes */ if ( bvmatch( bv, slap_bv_all_user_attrs ) ) { continue; } /* RFC 3673 LDAPv3: All Operational Attributes */ if ( bvmatch( bv, slap_bv_all_operational_attrs ) ) { continue; } /* RFC 4529 LDAP: Requesting Attributes by Object Class */ if ( bv->bv_len > 1 && bv->bv_val[0] == '@' ) { /* FIXME: check if remaining is valid oc name? */ continue; } /* add more "exceptions" to RFC 4511 4.5.1.8. */ /* invalid attribute description? remove */ if ( ad_keystring( bv ) ) { /* NOTE: parsed in-place, don't modify; * rather add "1.1", which must be ignored */ BER_BVSTR( &op->ors_attrs[i].an_name, LDAP_NO_ATTRS ); } /* otherwise leave in place... */ } } } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto return_results; } Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 ); if ( siz != 0 ) { for ( i = 0; i<siz; i++ ) { Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 ); } } Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; unsigned len = 0, alen; sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref); Statslog( LDAP_DEBUG_STATS, "%s SRCH base=\"%s\" %s filter=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, abuf, op->ors_filterstr.bv_val, 0 ); for ( i = 0; i<siz; i++ ) { alen = op->ors_attrs[i].an_name.bv_len; if (alen >= sizeof(abuf)) { alen = sizeof(abuf)-1; } if (len && (len + 1 + alen >= sizeof(abuf))) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen); len += alen; *ptr = '\0'; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); return_results:; if ( !BER_BVISNULL( &op->o_req_dn ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->o_req_ndn ) ) { slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->ors_filterstr ) ) { op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } if ( op->ors_filter != NULL) { filter_free_x( op, op->ors_filter, 1 ); } if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); } return rs->sr_err; }
/* return last found ID in *id if no match * If mc is provided, it will be left pointing to the RDN's * record under the parent's ID. If nsubs is provided, return * the number of entries in this entry's subtree. */ int mdb_dn2id( Operation *op, MDB_txn *txn, MDB_cursor *mc, struct berval *in, ID *id, ID *nsubs, struct berval *matched, struct berval *nmatched ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; MDB_cursor *cursor; MDB_dbi dbi = mdb->mi_dn2id; MDB_val key, data; int rc = 0, nrlen; diskNode *d; char *ptr; char dn[SLAP_LDAPDN_MAXLEN]; ID pid, nid; struct berval tmp; Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id(\"%s\")\n", in->bv_val ? in->bv_val : "" ); if ( matched ) { matched->bv_val = dn + sizeof(dn) - 1; matched->bv_len = 0; *matched->bv_val-- = '\0'; } if ( nmatched ) { nmatched->bv_len = 0; nmatched->bv_val = 0; } if ( !in->bv_len ) { *id = 0; nid = 0; goto done; } tmp = *in; if ( op->o_bd->be_nsuffix[0].bv_len ) { nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len; tmp.bv_val += nrlen; tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len; } else { for ( ptr = tmp.bv_val + tmp.bv_len - 1; ptr >= tmp.bv_val; ptr-- ) if (DN_SEPARATOR(*ptr)) break; ptr++; tmp.bv_len -= ptr - tmp.bv_val; tmp.bv_val = ptr; } nid = 0; key.mv_size = sizeof(ID); if ( mc ) { cursor = mc; } else { rc = mdb_cursor_open( txn, dbi, &cursor ); if ( rc ) goto done; } for (;;) { key.mv_data = &pid; pid = nid; data.mv_size = sizeof(diskNode) + tmp.bv_len; d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx ); d->nrdnlen[1] = tmp.bv_len & 0xff; d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80; ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len ); *ptr = '\0'; data.mv_data = d; rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH ); op->o_tmpfree( d, op->o_tmpmemctx ); if ( rc ) break; ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID); memcpy( &nid, ptr, sizeof(ID)); /* grab the non-normalized RDN */ if ( matched ) { int rlen; d = data.mv_data; rlen = data.mv_size - sizeof(diskNode) - tmp.bv_len - sizeof(ID); matched->bv_len += rlen; matched->bv_val -= rlen + 1; ptr = lutil_strcopy( matched->bv_val, d->rdn + tmp.bv_len ); if ( pid ) { *ptr = ','; matched->bv_len++; } } if ( nmatched ) { nmatched->bv_val = tmp.bv_val; } if ( tmp.bv_val > in->bv_val ) { for (ptr = tmp.bv_val - 2; ptr > in->bv_val && !DN_SEPARATOR(*ptr); ptr--) /* empty */; if ( ptr >= in->bv_val ) { if (DN_SEPARATOR(*ptr)) ptr++; tmp.bv_len = tmp.bv_val - ptr - 1; tmp.bv_val = ptr; } } else { break; } } *id = nid; /* return subtree count if requested */ if ( !rc && nsubs ) { ptr = (char *)data.mv_data + data.mv_size - sizeof(ID); memcpy( nsubs, ptr, sizeof( ID )); } if ( !mc ) mdb_cursor_close( cursor ); done: if ( matched ) { if ( matched->bv_len ) { ptr = op->o_tmpalloc( matched->bv_len+1, op->o_tmpmemctx ); strcpy( ptr, matched->bv_val ); matched->bv_val = ptr; } else { if ( BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] ) && !nid ) { ber_dupbv( matched, (struct berval *)&slap_empty_bv ); } else { matched->bv_val = NULL; } } } if ( nmatched ) { if ( nmatched->bv_val ) { nmatched->bv_len = in->bv_len - (nmatched->bv_val - in->bv_val); } else { *nmatched = slap_empty_bv; } } if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: get failed: %s (%d)\n", mdb_strerror( rc ), rc ); } else { Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: got id=0x%lx\n", nid ); } return rc; }
static int OpenLDAPaciPrettyNormal( struct berval *val, struct berval *out, void *ctx, int normalize ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, nrights = BER_BVNULL, type = BER_BVNULL, ntype = BER_BVNULL, subject = BER_BVNULL, nsubject = BER_BVNULL; int idx, rc = LDAP_SUCCESS, freesubject = 0, freetype = 0; char *ptr; BER_BVZERO( out ); if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid: if valid, it's already normalized */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope: normalize by replacing with OpenLDAPaciscopes */ if ( acl_get_part( val, 1, '#', &scope ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &scope, OpenLDAPaciscopes ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } scope = *OpenLDAPaciscopes[ idx ]; /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } } ntype = *OpenLDAPacitypes[ idx ]; /* subject */ bv_get_tail( val, &type, &subject ); if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } subject.bv_val++; subject.bv_len--; if ( idx < LAST_DNVALUED ) { /* FIXME: pass DN syntax? */ if ( normalize ) { rc = dnNormalize( 0, NULL, NULL, &subject, &nsubject, ctx ); } else { rc = dnPretty( NULL, &subject, &nsubject, ctx ); } if ( rc == LDAP_SUCCESS ) { freesubject = 1; } else { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val ); goto cleanup; } if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; const char *text = NULL; int rc; struct berval bv; bv.bv_len = ntype.bv_len; ocbv.bv_val++; ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len; } oc = oc_bvfind( &ocbv ); if ( oc == NULL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len; bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx ); ptr = bv.bv_val; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, oc->soc_cname.bv_val, oc->soc_cname.bv_len ); if ( ad != NULL ) { ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); } ptr[ 0 ] = '\0'; ntype = bv; freetype = 1; } } } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } nsubject = ad->ad_cname; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] ) { /* NOTE: dunno how to normalize it... */ nsubject = subject; } out->bv_len = oid.bv_len + STRLENOF( "#" ) + scope.bv_len + STRLENOF( "#" ) + nrights.bv_len + STRLENOF( "#" ) + ntype.bv_len + STRLENOF( "#" ) + nsubject.bv_len; out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx ); ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '#'; ptr++; if ( !BER_BVISNULL( &nsubject ) ) { ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len ); } ptr[ 0 ] = '\0'; cleanup:; if ( freesubject ) { ber_memfree_x( nsubject.bv_val, ctx ); } if ( freetype ) { ber_memfree_x( ntype.bv_val, ctx ); } if ( !BER_BVISNULL( &nrights ) ) { ber_memfree_x( nrights.bv_val, ctx ); } return rc; }
static int authzid_response( Operation *op, SlapReply *rs ) { LDAPControl **ctrls; struct berval edn = BER_BVNULL; ber_len_t len = 0; int n = 0; assert( rs->sr_tag = LDAP_RES_BIND ); if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) { authzid_conn_t *ac = op->o_controls[ authzid_cid ]; if ( ac ) { authzid_conn_release( ac ); } else { (void)authzid_conn_insert( op->o_conn, op->o_ctrlflag[ authzid_cid ] ); } return SLAP_CB_CONTINUE; } (void)authzid_conn_remove( op->o_conn ); if ( rs->sr_err != LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } if ( !BER_BVISEMPTY( &op->orb_edn ) ) { edn = op->orb_edn; } else if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { edn = op->o_conn->c_dn; } if ( !BER_BVISEMPTY( &edn ) ) { ber_tag_t save_tag = op->o_tag; struct berval save_dn = op->o_dn; struct berval save_ndn = op->o_ndn; int rc; /* pretend it's an extop without data, * so it is treated as a generic write */ op->o_tag = LDAP_REQ_EXTENDED; op->o_dn = edn; op->o_ndn = edn; rc = backend_check_restrictions( op, rs, NULL ); op->o_tag = save_tag; op->o_dn = save_dn; op->o_ndn = save_ndn; if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED; return SLAP_CB_CONTINUE; } len = STRLENOF("dn:") + edn.bv_len; } /* save original controls in sc_private; * will be restored by sc_cleanup */ if ( rs->sr_ctrls != NULL ) { op->o_callback->sc_private = rs->sr_ctrls; for ( ; rs->sr_ctrls[n] != NULL; n++ ) ; } ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( n + 2 ), op->o_tmpmemctx ); n = 0; if ( rs->sr_ctrls ) { for ( ; rs->sr_ctrls[n] != NULL; n++ ) { ctrls[n] = rs->sr_ctrls[n]; } } /* anonymous: "", otherwise "dn:<dn>" */ ctrls[n] = op->o_tmpalloc( sizeof( LDAPControl ) + len + 1, op->o_tmpmemctx ); ctrls[n]->ldctl_oid = LDAP_CONTROL_AUTHZID_RESPONSE; ctrls[n]->ldctl_iscritical = 0; ctrls[n]->ldctl_value.bv_len = len; ctrls[n]->ldctl_value.bv_val = (char *)&ctrls[n][1]; if ( len ) { char *ptr; ptr = lutil_strcopy( ctrls[n]->ldctl_value.bv_val, "dn:" ); ptr = lutil_strncopy( ptr, edn.bv_val, edn.bv_len ); } ctrls[n]->ldctl_value.bv_val[len] = '\0'; ctrls[n + 1] = NULL; rs->sr_ctrls = ctrls; return SLAP_CB_CONTINUE; }