int dnssrv_back_search( Operation *op, SlapReply *rs ) { int i; int rc; char *domain = NULL; char *hostlist = NULL; char **hosts = NULL; char *refdn; struct berval nrefdn = BER_BVNULL; BerVarray urls = NULL; int manageDSAit; rs->sr_ref = NULL; if ( BER_BVISEMPTY( &op->o_req_ndn ) ) { /* FIXME: need some means to determine whether the database * is a glue instance; if we got here with empty DN, then * we passed this same test in dnssrv_back_referrals() */ if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; } else { rs->sr_err = LDAP_SUCCESS; } goto done; } manageDSAit = get_manageDSAit( op ); /* * FIXME: we may return a referral if manageDSAit is not set */ if ( !manageDSAit ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "manageDSAit must be set" ); goto done; } if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) { rs->sr_err = LDAP_REFERRAL; rs->sr_ref = default_referral; send_ldap_result( op, rs ); rs->sr_ref = NULL; goto done; } Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain ); if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n", rc ); send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT, "no DNS SRV RR available for DN" ); goto done; } hosts = ldap_str2charray( hostlist, " " ); if( hosts == NULL ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charray error\n" ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } for( i=0; hosts[i] != NULL; i++) { struct berval url; url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]); url.bv_val = ch_malloc( url.bv_len + 1 ); strcpy( url.bv_val, "ldap://" ); strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] ); if( ber_bvarray_add( &urls, &url ) < 0 ) { free( url.bv_val ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } } Debug( LDAP_DEBUG_STATS, "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", op->o_log_prefix, op->o_protocol, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); Debug( LDAP_DEBUG_TRACE, "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n", op->oq_search.rs_scope, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); rc = ldap_domain2dn(domain, &refdn); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } else { struct berval bv; bv.bv_val = refdn; bv.bv_len = strlen( refdn ); rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } } if( !dn_match( &nrefdn, &op->o_req_ndn ) ) { /* requested dn is subordinate */ Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", refdn == NULL ? "" : refdn ); rs->sr_matched = refdn; rs->sr_err = LDAP_NO_SUCH_OBJECT; send_ldap_result( op, rs ); rs->sr_matched = NULL; } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) { send_ldap_error( op, rs, LDAP_SUCCESS, NULL ); } else { Entry e = { 0 }; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_ref = slap_schema.si_ad_ref; e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val ); e.e_name.bv_len = op->o_req_dn.bv_len; e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val ); e.e_nname.bv_len = op->o_req_ndn.bv_len; e.e_attrs = NULL; e.e_private = NULL; attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL ); attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL ); if ( ad_dc ) { char *p; struct berval bv; bv.bv_val = domain; p = strchr( bv.bv_val, '.' ); if ( p == bv.bv_val ) { bv.bv_len = 1; } else if ( p != NULL ) { bv.bv_len = p - bv.bv_val; } else { bv.bv_len = strlen( bv.bv_val ); } attr_merge_normalize_one( &e, ad_dc, &bv, NULL ); } if ( ad_associatedDomain ) { struct berval bv; ber_str2bv( domain, 0, 0, &bv ); attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL ); } attr_merge_normalize_one( &e, ad_ref, urls, NULL ); rc = test_filter( op, &e, op->oq_search.rs_filter ); if( rc == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->oq_search.rs_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_flags = 0; } entry_clean( &e ); rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); } free( refdn ); if ( nrefdn.bv_val ) free( nrefdn.bv_val ); done: if( domain != NULL ) ch_free( domain ); if( hostlist != NULL ) ch_free( hostlist ); if( hosts != NULL ) ldap_charray_free( hosts ); if( urls != NULL ) ber_bvarray_free( urls ); return 0; }
static int _mu_conn_setup (LDAP **pld) { int rc; LDAPURLDesc *ludlist, **ludp; char **urls = NULL; int nurls = 0; char *ldapuri = NULL; LDAP *ld = NULL; int protocol = LDAP_VERSION3; /* FIXME: must be configurable */ if (ldap_param.debug) { if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &ldap_param.debug) != LBER_OPT_SUCCESS ) mu_error (_("cannot set LBER_OPT_DEBUG_LEVEL %d"), ldap_param.debug); if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_param.debug) != LDAP_OPT_SUCCESS ) mu_error (_("could not set LDAP_OPT_DEBUG_LEVEL %d"), ldap_param.debug); } if (ldap_param.url) { rc = ldap_url_parse (ldap_param.url, &ludlist); if (rc != LDAP_URL_SUCCESS) { mu_error (_("cannot parse LDAP URL(s)=%s (%d)"), ldap_param.url, rc); return 1; } for (ludp = &ludlist; *ludp; ) { LDAPURLDesc *lud = *ludp; char **tmp; if (lud->lud_dn && lud->lud_dn[0] && (lud->lud_host == NULL || lud->lud_host[0] == '\0')) { /* if no host but a DN is provided, try DNS SRV to gather the host list */ char *domain = NULL, *hostlist = NULL; size_t i; struct mu_wordsplit ws; if (ldap_dn2domain (lud->lud_dn, &domain) || !domain) { mu_error (_("DNS SRV: cannot convert DN=\"%s\" into a domain"), lud->lud_dn ); goto dnssrv_free; } rc = ldap_domain2hostlist (domain, &hostlist); if (rc) { mu_error (_("DNS SRV: cannot convert domain=%s into a hostlist"), domain); goto dnssrv_free; } if (mu_wordsplit (hostlist, &ws, MU_WRDSF_DEFFLAGS)) { mu_error (_("DNS SRV: could not parse hostlist=\"%s\": %s"), hostlist, mu_wordsplit_strerror (&ws)); goto dnssrv_free; } tmp = realloc (urls, sizeof(char *) * (nurls + ws.ws_wordc + 1)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); goto dnssrv_free; } urls = tmp; urls[nurls] = NULL; for (i = 0; i < ws.ws_wordc; i++) { urls[nurls + i + 1] = NULL; rc = mu_asprintf (&urls[nurls + i], "%s://%s", lud->lud_scheme, ws.ws_wordv[i]); if (rc) { mu_error ("DNS SRV %s", mu_strerror (rc)); goto dnssrv_free; } } nurls += i; dnssrv_free: mu_wordsplit_free (&ws); ber_memfree (hostlist); ber_memfree (domain); } else { tmp = realloc (urls, sizeof(char *) * (nurls + 2)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } urls = tmp; urls[nurls + 1] = NULL; urls[nurls] = ldap_url_desc2str (lud); if (!urls[nurls]) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } nurls++; } *ludp = lud->lud_next; lud->lud_next = NULL; ldap_free_urldesc (lud); } if (ludlist) { ldap_free_urldesc (ludlist); return 1; } else if (!urls) return 1; rc = mu_argcv_string (nurls, urls, &ldapuri); if (rc) { mu_error ("%s", mu_strerror (rc)); return 1; } ber_memvfree ((void **)urls); } mu_diag_output (MU_DIAG_INFO, "constructed LDAP URI: %s", ldapuri ? ldapuri : "<DEFAULT>"); rc = ldap_initialize (&ld, ldapuri); if (rc != LDAP_SUCCESS) { mu_error (_("cannot create LDAP session handle for URI=%s (%d): %s"), ldapuri, rc, ldap_err2string (rc)); free (ldapuri); return 1; } free (ldapuri); ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol); if (ldap_param.tls) { rc = ldap_start_tls_s (ld, NULL, NULL); if (rc != LDAP_SUCCESS) { char *msg = NULL; ldap_get_option (ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); mu_error (_("ldap_start_tls failed: %s"), ldap_err2string (rc)); mu_error (_("TLS diagnostics: %s"), msg); ldap_memfree (msg); ldap_unbind_ext (ld, NULL, NULL); return 1; } } /* FIXME: Timeouts, SASL, etc. */ *pld = ld; return 0; }
int dnssrv_back_referrals( Operation *op, SlapReply *rs ) { int i; int rc = LDAP_OTHER; char *domain = NULL; char *hostlist = NULL; char **hosts = NULL; BerVarray urls = NULL; if ( BER_BVISEMPTY( &op->o_req_dn ) ) { /* FIXME: need some means to determine whether the database * is a glue instance */ if ( SLAP_GLUE_INSTANCE( op->o_bd ) ) { return LDAP_SUCCESS; } rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; return LDAP_UNWILLING_TO_PERFORM; } if( get_manageDSAit( op ) ) { if( op->o_tag == LDAP_REQ_SEARCH ) { return LDAP_SUCCESS; } rs->sr_text = "DNS SRV problem processing manageDSAit control"; return LDAP_OTHER; } if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) { rs->sr_err = LDAP_REFERRAL; rs->sr_ref = default_referral; send_ldap_result( op, rs ); rs->sr_ref = NULL; return LDAP_REFERRAL; } Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", op->o_req_dn.bv_val, domain, 0 ); i = ldap_domain2hostlist( domain, &hostlist ); if ( i ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist(%s) returned %d\n", domain, i, 0 ); rs->sr_text = "no DNS SRV RR available for DN"; rc = LDAP_NO_SUCH_OBJECT; goto done; } hosts = ldap_str2charray( hostlist, " " ); if( hosts == NULL ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 ); rs->sr_text = "problem processing DNS SRV records for DN"; goto done; } for( i=0; hosts[i] != NULL; i++) { struct berval url; url.bv_len = STRLENOF( "ldap://" ) + strlen( hosts[i] ); url.bv_val = ch_malloc( url.bv_len + 1 ); strcpy( url.bv_val, "ldap://" ); strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] ); if ( ber_bvarray_add( &urls, &url ) < 0 ) { free( url.bv_val ); rs->sr_text = "problem processing DNS SRV records for DN"; goto done; } } Statslog( LDAP_DEBUG_STATS, "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", op->o_log_prefix, op->o_protocol, op->o_req_dn.bv_val, urls[0].bv_val, 0 ); Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> url=\"%s\"\n", op->o_req_dn.bv_val, urls[0].bv_val, 0 ); rs->sr_ref = urls; send_ldap_error( op, rs, LDAP_REFERRAL, "DNS SRV generated referrals" ); rs->sr_ref = NULL; rc = LDAP_REFERRAL; done: if( domain != NULL ) ch_free( domain ); if( hostlist != NULL ) ch_free( hostlist ); if( hosts != NULL ) ldap_charray_free( hosts ); ber_bvarray_free( urls ); return rc; }
int main( int argc, char *argv[] ) { int rc, i, debug = 0, f2 = 0; unsigned flags[ 2 ] = { 0U, 0 }; char *strin, *str = NULL, buf[ 1024 ]; LDAPDN dn, dn2 = NULL; while ( 1 ) { int opt = getopt( argc, argv, "d:" ); if ( opt == EOF ) { break; } switch ( opt ) { case 'd': debug = atoi( optarg ); break; } } optind--; argc -= optind; argv += optind; if ( argc < 2 ) { fprintf( stderr, "usage: dntest <dn> [flags-in[,...]] [flags-out[,...]]\n\n" ); fprintf( stderr, "\tflags-in: V3,V2,DCE,<flags>\n" ); fprintf( stderr, "\tflags-out: V3,V2,UFN,DCE,AD,<flags>\n\n" ); fprintf( stderr, "\t<flags>: PRETTY,PEDANTIC,NOSPACES,NOONESPACE\n\n" ); return( 0 ); } if ( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) { fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug ); } if ( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) { fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug ); } if ( strcmp( argv[ 1 ], "-" ) == 0 ) { size_t len = fgets( buf, sizeof( buf ), stdin ) ? strlen( buf ) : 0; if ( len == 0 || buf[ --len ] == '\n' ) { buf[ len ] = '\0'; } strin = buf; } else { strin = argv[ 1 ]; } if ( argc >= 3 ) { for ( i = 0; i < argc - 2; i++ ) { char *s, *e; for ( s = argv[ 2 + i ]; s; s = e ) { e = strchr( s, ',' ); if ( e != NULL ) { e[ 0 ] = '\0'; e++; } if ( !strcasecmp( s, "V3" ) ) { flags[ i ] |= LDAP_DN_FORMAT_LDAPV3; } else if ( !strcasecmp( s, "V2" ) ) { flags[ i ] |= LDAP_DN_FORMAT_LDAPV2; } else if ( !strcasecmp( s, "DCE" ) ) { flags[ i ] |= LDAP_DN_FORMAT_DCE; } else if ( !strcasecmp( s, "UFN" ) ) { flags[ i ] |= LDAP_DN_FORMAT_UFN; } else if ( !strcasecmp( s, "AD" ) ) { flags[ i ] |= LDAP_DN_FORMAT_AD_CANONICAL; } else if ( !strcasecmp( s, "PRETTY" ) ) { flags[ i ] |= LDAP_DN_PRETTY; } else if ( !strcasecmp( s, "PEDANTIC" ) ) { flags[ i ] |= LDAP_DN_PEDANTIC; } else if ( !strcasecmp( s, "NOSPACES" ) ) { flags[ i ] |= LDAP_DN_P_NOLEADTRAILSPACES; } else if ( !strcasecmp( s, "NOONESPACE" ) ) { flags[ i ] |= LDAP_DN_P_NOSPACEAFTERRDN; } } } } if ( flags[ 1 ] == 0 ) flags[ 1 ] = LDAP_DN_FORMAT_LDAPV3; f2 = 1; rc = ldap_str2dn( strin, &dn, flags[ 0 ] ); if ( rc == LDAP_SUCCESS ) { int i; if ( dn ) { for ( i = 0; dn[ i ]; i++ ) { LDAPRDN rdn = dn[ i ]; char *rstr = NULL; if ( ldap_rdn2str( rdn, &rstr, flags[ f2 ] ) ) { fprintf( stdout, "\tldap_rdn2str() failed\n" ); continue; } fprintf( stdout, "\tldap_rdn2str() = \"%s\"\n", rstr ); ldap_memfree( rstr ); } } else { fprintf( stdout, "\tempty DN\n" ); } } str = NULL; if ( rc == LDAP_SUCCESS && ldap_dn2str( dn, &str, flags[ f2 ] ) == LDAP_SUCCESS ) { char **values, *tmp, *tmp2, *str2 = NULL; int n; fprintf( stdout, "\nldap_dn2str(ldap_str2dn(\"%s\"))\n" "\t= \"%s\"\n", strin, str ); switch ( flags[ f2 ] & LDAP_DN_FORMAT_MASK ) { case LDAP_DN_FORMAT_UFN: case LDAP_DN_FORMAT_AD_CANONICAL: return( 0 ); case LDAP_DN_FORMAT_LDAPV3: case LDAP_DN_FORMAT_LDAPV2: n = ldap_dn2domain( strin, &tmp ); if ( n ) { fprintf( stdout, "\nldap_dn2domain(\"%s\") FAILED\n", strin ); } else { fprintf( stdout, "\nldap_dn2domain(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); } ldap_memfree( tmp ); tmp = ldap_dn2ufn( strin ); fprintf( stdout, "\nldap_dn2ufn(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); ldap_memfree( tmp ); tmp = ldap_dn2dcedn( strin ); fprintf( stdout, "\nldap_dn2dcedn(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); tmp2 = ldap_dcedn2dn( tmp ); fprintf( stdout, "\nldap_dcedn2dn(\"%s\")\n" "\t= \"%s\"\n", tmp ? tmp : "", tmp2 ? tmp2 : "" ); ldap_memfree( tmp ); ldap_memfree( tmp2 ); tmp = ldap_dn2ad_canonical( strin ); fprintf( stdout, "\nldap_dn2ad_canonical(\"%s\")\n" "\t= \"%s\"\n", strin, tmp ? tmp : "" ); ldap_memfree( tmp ); fprintf( stdout, "\nldap_explode_dn(\"%s\"):\n", str ); values = ldap_explode_dn( str, 0 ); for ( n = 0; values && values[ n ]; n++ ) { char **vv; int nn; fprintf( stdout, "\t\"%s\"\n", values[ n ] ); fprintf( stdout, "\tldap_explode_rdn(\"%s\")\n", values[ n ] ); vv = ldap_explode_rdn( values[ n ], 0 ); for ( nn = 0; vv && vv[ nn ]; nn++ ) { fprintf( stdout, "\t\t'%s'\n", vv[ nn ] ); } LDAP_VFREE( vv ); fprintf( stdout, "\tldap_explode_rdn(\"%s\")" " (no types)\n", values[ n ] ); vv = ldap_explode_rdn( values[ n ], 1 ); for ( nn = 0; vv && vv[ nn ]; nn++ ) { fprintf( stdout, "\t\t\t\"%s\"\n", vv[ nn ] ); } LDAP_VFREE( vv ); } LDAP_VFREE( values ); fprintf( stdout, "\nldap_explode_dn(\"%s\")" " (no types):\n", str ); values = ldap_explode_dn( str, 1 ); for ( n = 0; values && values[ n ]; n++ ) { fprintf( stdout, "\t\"%s\"\n", values[ n ] ); } LDAP_VFREE( values ); break; } dn2 = NULL; rc = ldap_str2dn( str, &dn2, flags[ f2 ] ); str2 = NULL; if ( rc == LDAP_SUCCESS && ldap_dn2str( dn2, &str2, flags[ f2 ] ) == LDAP_SUCCESS ) { int iRDN; fprintf( stdout, "\n\"%s\"\n\t == \"%s\" ? %s\n", str, str2, strcmp( str, str2 ) == 0 ? "yes" : "no" ); if( dn != NULL && dn2 == NULL ) { fprintf( stdout, "dn mismatch\n" ); } else if (( dn != NULL ) && (dn2 != NULL)) for ( iRDN = 0; dn[ iRDN ] && dn2[ iRDN ]; iRDN++ ) { LDAPRDN r = dn[ iRDN ]; LDAPRDN r2 = dn2[ iRDN ]; int iAVA; for ( iAVA = 0; r[ iAVA ] && r2[ iAVA ]; iAVA++ ) { LDAPAVA *a = r[ iAVA ]; LDAPAVA *a2 = r2[ iAVA ]; if ( a->la_attr.bv_len != a2->la_attr.bv_len ) { fprintf( stdout, "ava(%d), rdn(%d) attr len mismatch (%ld->%ld)\n", iAVA + 1, iRDN + 1, a->la_attr.bv_len, a2->la_attr.bv_len ); } else if ( memcmp( a->la_attr.bv_val, a2->la_attr.bv_val, a->la_attr.bv_len ) ) { fprintf( stdout, "ava(%d), rdn(%d) attr mismatch\n", iAVA + 1, iRDN + 1 ); } else if ( a->la_flags != a2->la_flags ) { fprintf( stdout, "ava(%d), rdn(%d) flag mismatch (%x->%x)\n", iAVA + 1, iRDN + 1, a->la_flags, a2->la_flags ); } else if ( a->la_value.bv_len != a2->la_value.bv_len ) { fprintf( stdout, "ava(%d), rdn(%d) value len mismatch (%ld->%ld)\n", iAVA + 1, iRDN + 1, a->la_value.bv_len, a2->la_value.bv_len ); } else if ( memcmp( a->la_value.bv_val, a2->la_value.bv_val, a->la_value.bv_len ) ) { fprintf( stdout, "ava(%d), rdn(%d) value mismatch\n", iAVA + 1, iRDN + 1 ); } } } ldap_dnfree( dn2 ); ldap_memfree( str2 ); } ldap_memfree( str ); } ldap_dnfree( dn ); /* note: dn is not freed */ return( 0 ); }