int asyncmeta_referral_result_rewrite( a_dncookie *dc, BerVarray a_vals, void *memctx ) { int i, last; assert( dc != NULL ); assert( a_vals != NULL ); for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ ) ; last--; for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) { struct berval dn, olddn = BER_BVNULL; int rc; LDAPURLDesc *ludp; rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp ); if ( rc != LDAP_URL_SUCCESS ) { /* leave attr untouched if massage failed */ continue; } /* FIXME: URLs like "ldap:///dc=suffix" if passed * thru ldap_url_parse() and ldap_url_desc2str() * get rewritten as "ldap:///dc=suffix??base"; * we don't want this to occur... */ if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { ludp->lud_scope = LDAP_SCOPE_DEFAULT; } ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); rc = asyncmeta_dn_massage( dc, &olddn, &dn ); switch ( rc ) { case LDAP_UNWILLING_TO_PERFORM: /* * FIXME: need to check if it may be considered * legal to trim values when adding/modifying; * it should be when searching (e.g. ACLs). */ ber_memfree( a_vals[ i ].bv_val ); if ( last > i ) { a_vals[ i ] = a_vals[ last ]; } BER_BVZERO( &a_vals[ last ] ); last--; i--; break; default: /* leave attr untouched if massage failed */ if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) { char *newurl; ludp->lud_dn = dn.bv_val; newurl = ldap_url_desc2str( ludp ); free( dn.bv_val ); if ( newurl == NULL ) { /* FIXME: leave attr untouched * even if ldap_url_desc2str failed... */ break; } ber_memfree_x( a_vals[ i ].bv_val, memctx ); ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx ); ber_memfree( newurl ); ludp->lud_dn = olddn.bv_val; } break; } ldap_free_urldesc( ludp ); } return 0; }
static int vc_exop( Operation *op, SlapReply *rs ) { int rc = LDAP_SUCCESS; ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval reqdata = BER_BVNULL; struct berval cookie = BER_BVNULL; struct berval bdn = BER_BVNULL; ber_tag_t authtag; struct berval cred = BER_BVNULL; struct berval ndn = BER_BVNULL; struct berval mechanism = BER_BVNULL; vc_conn_t *conn = NULL; vc_cb_t vc = { 0 }; slap_callback sc = { 0 }; SlapReply rs2 = { 0 }; if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) { rs->sr_text = "empty request data field in VerifyCredentials exop"; return LDAP_PROTOCOL_ERROR; } /* optimistic */ rs->sr_err = LDAP_SUCCESS; ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx ); /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, &reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag != LBER_SEQUENCE ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) { /* * cookie: the pointer to the connection * of this operation */ ber_scanf( ber, "m", &cookie ); if ( cookie.bv_len != sizeof(Connection *) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } /* DN, authtag */ tag = ber_scanf( ber, "mt", &bdn, &authtag ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: /* cookie only makes sense for SASL bind (so far) */ if ( !BER_BVISNULL( &cookie ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_scanf( ber, "m", &cred ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } break; case LDAP_AUTH_SASL: tag = ber_scanf( ber, "{s" /*}*/ , &mechanism ); if ( tag == LBER_ERROR || BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LBER_OCTETSTRING ) { ber_scanf( ber, "m", &cred ); } tag = ber_scanf( ber, /*{*/ "}" ); break; default: rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } if ( !BER_BVISNULL( &cookie ) ) { vc_conn_t tmp = { 0 }; AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len ); ldap_pvt_thread_mutex_lock( &vc_mutex ); conn = (vc_conn_t *)avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp ); if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) { conn = NULL; ldap_pvt_thread_mutex_unlock( &vc_mutex ); rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } conn->refcnt++; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } else { void *thrctx; conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) ); conn->refcnt = 1; thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 ); conn->op = &conn->opbuf.ob_op; snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ), "%s VERIFYCREDENTIALS", op->o_log_prefix ); } conn->op->o_tag = LDAP_REQ_BIND; memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) ); conn->op->o_req_dn = ndn; conn->op->o_req_ndn = ndn; conn->op->o_protocol = LDAP_VERSION3; conn->op->orb_method = authtag; conn->op->o_callback = ≻ /* TODO: controls */ tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) { conn->op->o_ber = ber; rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } tag = ber_skip_tag( ber, &len ); if ( len || tag != LBER_DEFAULT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: break; case LDAP_AUTH_SASL: conn->op->orb_mech = mechanism; break; } conn->op->orb_cred = cred; sc.sc_response = vc_cb; sc.sc_private = &vc; conn->op->o_bd = frontendDB; rs->sr_err = frontendDB->be_bind( conn->op, &rs2 ); if ( conn->op->o_conn->c_sasl_bind_in_progress ) { rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text, !BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL, NULL, vc.ctrls, &rs->sr_rspdata ); } else { rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text, NULL, &conn->op->o_conn->c_dn, vc.ctrls, &rs->sr_rspdata ); } if ( rc != 0 ) { rs->sr_err = LDAP_OTHER; goto done; } if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) && conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val ) ber_memfree( conn->op->o_conn->c_dn.bv_val ); if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) ) ber_memfree( conn->op->o_conn->c_ndn.bv_val ); done:; if ( conn ) { if ( conn->op->o_conn->c_sasl_bind_in_progress ) { if ( conn->conn == NULL ) { conn->conn = conn; conn->refcnt--; ldap_pvt_thread_mutex_lock( &vc_mutex ); rc = avl_insert( &vc_tree, (caddr_t)conn, vc_conn_cmp, vc_conn_dup ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); assert( rc == 0 ); } else { ldap_pvt_thread_mutex_lock( &vc_mutex ); conn->refcnt--; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } } else { if ( conn->conn != NULL ) { vc_conn_t *tmp; ldap_pvt_thread_mutex_lock( &vc_mutex ); tmp = avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); } SLAP_FREE( conn ); } } if ( vc.ctrls ) { ldap_controls_free( vc.ctrls ); vc.ctrls = NULL; } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ndn ); } op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx ); BER_BVZERO( &reqdata ); return rs->sr_err; }
static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err) { ldapconninfo *li = conn->proto.generic; struct SessionHandle *data=conn->data; ldapreqinfo *lr = data->state.proto.generic; int rc, ret; LDAPMessage *result = NULL; LDAPMessage *ent; BerElement *ber = NULL; struct timeval tv = {0,1}; (void)len; (void)buf; (void)sockindex; rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result); if(rc < 0) { failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); *err = CURLE_RECV_ERROR; return -1; } *err = CURLE_AGAIN; ret = -1; /* timed out */ if(result == NULL) return ret; for(ent = ldap_first_message(li->ld, result); ent; ent = ldap_next_message(li->ld, ent)) { struct berval bv, *bvals, **bvp = &bvals; int binary = 0, msgtype; msgtype = ldap_msgtype(ent); if(msgtype == LDAP_RES_SEARCH_RESULT) { int code; char *info = NULL; rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); if(rc) { failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc)); *err = CURLE_LDAP_SEARCH_FAILED; } else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), info ? info : ""); *err = CURLE_LDAP_SEARCH_FAILED; } else { /* successful */ if(code == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", lr->nument); data->req.size = data->req.bytecount; *err = CURLE_OK; ret = 0; } lr->msgid = 0; ldap_memfree(info); break; } else if(msgtype != LDAP_RES_SEARCH_ENTRY) continue; lr->nument++; rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); if(rc < 0) { /* TODO: verify that this is really how this return code should be handled */ *err = CURLE_RECV_ERROR; return -1; } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); data->req.bytecount += bv.bv_len + 5; for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); rc == LDAP_SUCCESS; rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { int i; if(bv.bv_val == NULL) break; if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) binary = 1; else binary = 0; for(i=0; bvals[i].bv_val != NULL; i++) { int binval = 0; Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); data->req.bytecount += bv.bv_len + 2; if(!binary) { /* check for leading or trailing whitespace */ if(ISSPACE(bvals[i].bv_val[0]) || ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) binval = 1; else { /* check for unprintable characters */ unsigned int j; for(j=0; j<bvals[i].bv_len; j++) if(!ISPRINT(bvals[i].bv_val[j])) { binval = 1; break; } } } if(binary || binval) { char *val_b64 = NULL; size_t val_b64_sz = 0; /* Binary value, encode to base64. */ CURLcode error = Curl_base64_encode(data, bvals[i].bv_val, bvals[i].bv_len, &val_b64, &val_b64_sz); if(error) { ber_memfree(bvals); ber_free(ber, 0); ldap_msgfree(result); *err = error; return -1; } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); data->req.bytecount += 2; if(val_b64_sz > 0) { Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); free(val_b64); data->req.bytecount += val_b64_sz; } } else { Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, bvals[i].bv_len); data->req.bytecount += bvals[i].bv_len + 1; } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); data->req.bytecount++; } ber_memfree(bvals); Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); data->req.bytecount++; } Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); data->req.bytecount++; ber_free(ber, 0); } ldap_msgfree(result); return ret; }
static int map_attr_value( a_dncookie *dc, AttributeDescription *ad, struct berval *mapped_attr, struct berval *value, struct berval *mapped_value, int remap, void *memctx ) { struct berval vtmp; int freeval = 0; asyncmeta_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap ); if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { #if 0 /* * FIXME: are we sure we need to search oc_map if at_map fails? */ asyncmeta_map( &dc->target->mt_rwmap.rwm_oc, &ad->ad_cname, mapped_attr, remap ); if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { *mapped_attr = ad->ad_cname; } #endif if ( dc->target->mt_rwmap.rwm_at.drop_missing ) { return -1; } *mapped_attr = ad->ad_cname; } if ( value == NULL ) { return 0; } if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { a_dncookie fdc = *dc; fdc.ctx = "searchFilterAttrDN"; switch ( asyncmeta_dn_massage( &fdc, value, &vtmp ) ) { case LDAP_SUCCESS: if ( vtmp.bv_val != value->bv_val ) { freeval = 1; } break; case LDAP_UNWILLING_TO_PERFORM: return -1; case LDAP_OTHER: return -1; } } else if ( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) { if ( ad->ad_type->sat_equality->smr_normalize( (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX), NULL, NULL, value, &vtmp, memctx ) ) { return -1; } freeval = 2; } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) { asyncmeta_map( &dc->target->mt_rwmap.rwm_oc, value, &vtmp, remap ); if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { vtmp = *value; } } else { vtmp = *value; } filter_escape_value_x( &vtmp, mapped_value, memctx ); switch ( freeval ) { case 1: ber_memfree( vtmp.bv_val ); break; case 2: ber_memfree_x( vtmp.bv_val, memctx ); break; } return 0; }
/* Get a password from a file. */ int lutil_get_filed_password( const char *filename, struct berval *passwd ) { size_t nread, nleft, nr; FILE *f = fopen( filename, "r" ); if( f == NULL ) { perror( filename ); return -1; } passwd->bv_val = NULL; passwd->bv_len = 4096; #ifdef HAVE_FSTAT { struct stat sb; if ( fstat( fileno( f ), &sb ) == 0 ) { if( sb.st_mode & 006 ) { fprintf( stderr, _("Warning: Password file %s" " is publicly readable/writeable\n"), filename ); } if ( sb.st_size ) passwd->bv_len = sb.st_size; } } #endif /* HAVE_FSTAT */ passwd->bv_val = (char *) ber_memalloc( passwd->bv_len + 1 ); if( passwd->bv_val == NULL ) { perror( filename ); return -1; } nread = 0; nleft = passwd->bv_len; do { if( nleft == 0 ) { /* double the buffer size */ char *p = (char *) ber_memrealloc( passwd->bv_val, 2 * passwd->bv_len + 1 ); if( p == NULL ) { ber_memfree( passwd->bv_val ); passwd->bv_val = NULL; passwd->bv_len = 0; return -1; } nleft = passwd->bv_len; passwd->bv_len *= 2; passwd->bv_val = p; } nr = fread( &passwd->bv_val[nread], 1, nleft, f ); if( nr < nleft && ferror( f ) ) { ber_memfree( passwd->bv_val ); passwd->bv_val = NULL; passwd->bv_len = 0; return -1; } nread += nr; nleft -= nr; } while ( !feof(f) ); passwd->bv_len = nread; passwd->bv_val[nread] = '\0'; fclose( f ); 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: assert( 0 ); 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: assert( 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); } 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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, 0 ); 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; }
int alock_recover ( alock_info_t * info ) { struct stat statbuf; alock_slot_t slot_data; alock_info_t scan_info; int res, max_slot; assert (info != NULL); scan_info.al_fd = info->al_fd; (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t)); res = alock_grab_lock (info->al_fd, 0); if (res == -1) { goto fail; } res = fstat (info->al_fd, &statbuf); if (res == -1) { goto fail; } max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE; for (scan_info.al_slot = 1; scan_info.al_slot < max_slot; ++ scan_info.al_slot) { if (scan_info.al_slot != info->al_slot) { res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE; if (res == ALOCK_LOCKED || res == ALOCK_UNIQUE) { /* recovery attempt on an active db? */ goto fail; } else if (res == ALOCK_DIRTY) { /* mark it clean */ res = alock_read_slot (&scan_info, &slot_data); if (res == -1) { goto fail; } slot_data.al_lock = ALOCK_UNLOCKED; res = alock_write_slot (&scan_info, &slot_data); if (res == -1) { if (slot_data.al_appname != NULL) ber_memfree (slot_data.al_appname); goto fail; } if (slot_data.al_appname != NULL) { ber_memfree (slot_data.al_appname); slot_data.al_appname = NULL; } } else if (res == -1) { goto fail; } } } res = alock_release_lock (info->al_fd, 0); if (res == -1) { close (info->al_fd); return ALOCK_UNSTABLE; } return ALOCK_CLEAN; fail: alock_release_lock (info->al_fd, 0); close (info->al_fd); return ALOCK_UNSTABLE; }
int alock_open ( alock_info_t * info, const char * appname, const char * envdir, int locktype ) { struct stat statbuf; alock_info_t scan_info; alock_slot_t slot_data; char * filename; int res, max_slot; int dirty_count, live_count, nosave; char *ptr; assert (info != NULL); assert (appname != NULL); assert (envdir != NULL); assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2); slot_data.al_lock = locktype; slot_data.al_stamp = time(NULL); slot_data.al_pid = getpid(); slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME); if (slot_data.al_appname == NULL) { return ALOCK_UNSTABLE; } strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1); slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0'; filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1); if (filename == NULL ) { ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } ptr = lutil_strcopy(filename, envdir); lutil_strcopy(ptr, "/alock"); #ifdef _WIN32 { HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); info->al_fd = _open_osfhandle (handle, 0); } #else info->al_fd = open (filename, O_CREAT|O_RDWR, 0666); #endif ber_memfree (filename); if (info->al_fd < 0) { ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } info->al_slot = 0; res = alock_grab_lock (info->al_fd, 0); if (res == -1) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } res = fstat (info->al_fd, &statbuf); if (res == -1) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE; dirty_count = 0; live_count = 0; nosave = 0; scan_info.al_fd = info->al_fd; for (scan_info.al_slot = 1; scan_info.al_slot < max_slot; ++ scan_info.al_slot) { if (scan_info.al_slot != info->al_slot) { res = alock_query_slot (&scan_info); if (res & ALOCK_NOSAVE) { nosave = ALOCK_NOSAVE; res ^= ALOCK_NOSAVE; } if (res == ALOCK_UNLOCKED && info->al_slot == 0) { info->al_slot = scan_info.al_slot; } else if (res == ALOCK_LOCKED) { ++live_count; } else if (res == ALOCK_UNIQUE && (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE || nosave )) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_BUSY; } else if (res == ALOCK_DIRTY) { ++dirty_count; } else if (res == -1) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } } } if (dirty_count && live_count) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } if (info->al_slot == 0) info->al_slot = max_slot + 1; res = alock_grab_lock (info->al_fd, info->al_slot); if (res == -1) { close (info->al_fd); ber_memfree (slot_data.al_appname); return ALOCK_UNSTABLE; } res = alock_write_slot (info, &slot_data); ber_memfree (slot_data.al_appname); if (res == -1) { close (info->al_fd); return ALOCK_UNSTABLE; } alock_share_lock (info->al_fd, info->al_slot); res = alock_release_lock (info->al_fd, 0); if (res == -1) { close (info->al_fd); return ALOCK_UNSTABLE; } if (dirty_count) return ALOCK_RECOVER | nosave; return ALOCK_CLEAN | nosave; }
int main( int argc, char *argv[] ) { int rc; LDAP *ld = NULL; char *matcheddn = NULL, *text = NULL, **refs = NULL; char *retoid = NULL; struct berval *retdata = NULL; int id, code = 0; LDAPMessage *res; LDAPControl **ctrls = NULL; tool_init( TOOL_WHOAMI ); prog = lutil_progname( "ldapwhoami", argc, argv ); /* LDAPv3 only */ protocol = LDAP_VERSION3; tool_args( argc, argv ); if( argc - optind > 0 ) { usage(); } if ( pw_file || want_bindpw ) { if ( pw_file ) { rc = lutil_get_filed_password( pw_file, &passwd ); if( rc ) return EXIT_FAILURE; } else { passwd.bv_val = getpassphrase( _("Enter LDAP Password: "******"ldap_whoami", rc, NULL, NULL, NULL, NULL ); rc = EXIT_FAILURE; goto skip; } for ( ; ; ) { struct timeval tv; if ( tool_check_abandon( ld, id ) ) { return LDAP_CANCELLED; } tv.tv_sec = 0; tv.tv_usec = 100000; rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); if ( rc < 0 ) { tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); return rc; } if ( rc != 0 ) { break; } } rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { rc = code; } if ( rc != LDAP_SUCCESS ) { tool_perror( "ldap_parse_result", rc, NULL, matcheddn, text, refs ); rc = EXIT_FAILURE; goto skip; } rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 ); if( rc != LDAP_SUCCESS ) { tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); rc = EXIT_FAILURE; goto skip; } if( retdata != NULL ) { if( retdata->bv_len == 0 ) { printf(_("anonymous\n") ); } else { printf("%s\n", retdata->bv_val ); } } skip: if ( verbose || ( code != LDAP_SUCCESS ) || matcheddn || text || refs || ctrls ) { printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code ); if( text && *text ) { printf( _("Additional info: %s\n"), text ); } if( matcheddn && *matcheddn ) { printf( _("Matched DN: %s\n"), matcheddn ); } if( refs ) { int i; for( i=0; refs[i]; i++ ) { printf(_("Referral: %s\n"), refs[i] ); } } if (ctrls) { tool_print_ctrls( ld, ctrls ); ldap_controls_free( ctrls ); } } ber_memfree( text ); ber_memfree( matcheddn ); ber_memvfree( (void **) refs ); ber_memfree( retoid ); ber_bvfree( retdata ); /* disconnect from server */ tool_unbind( ld ); tool_destroy(); return code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; }