Commit 5011db07 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Referrals and misc other changes

parent 04e2636d
......@@ -187,33 +187,27 @@ int ldap_int_get_controls(
tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
if( tag != LBER_ERROR ) {
tag = ber_peek_tag( ber, &len );
if( tag == LBER_ERROR ) {
*ctrls = NULL;
ldap_controls_free( tctrls );
return LDAP_DECODING_ERROR;
}
tag = ber_peek_tag( ber, &len );
if( tag == LBER_BOOLEAN ) {
ber_int_t crit;
tag = ber_scanf( ber, "b", &crit );
tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
}
if( tag != LBER_ERROR ) {
tag = ber_peek_tag( ber, &len );
}
if( tag == LBER_OCTETSTRING ) {
tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
} else {
tctrl->ldctl_value.bv_val = NULL;
}
if( tag == LBER_ERROR ) {
*ctrls = NULL;
ldap_controls_free( tctrls );
return LDAP_DECODING_ERROR;
}
*ctrls = tctrls;
}
......
......@@ -121,46 +121,49 @@ int ldap_domain2dn(
LDAP_CONST char *domain_in,
char **dnp)
{
char *domain, *s, *tok_r, *dn;
size_t loc;
char *domain, *s, *tok_r, *dn, *dntmp;
size_t loc;
assert( domain_in != NULL );
assert( dnp != NULL );
domain = LDAP_STRDUP(domain_in);
if (domain == NULL) {
domain = LDAP_STRDUP(domain_in);
if (domain == NULL) {
return LDAP_NO_MEMORY;
}
dn = NULL;
loc = 0;
for (s = ldap_pvt_strtok(domain, ".", &tok_r);
s != NULL;
s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
size_t len = strlen(s);
dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
if (dn == NULL) {
LDAP_FREE(domain);
return LDAP_NO_MEMORY;
}
if (loc > 0) {
/* not first time. */
strcpy(dn + loc, ",");
loc++;
}
strcpy(dn + loc, "dc=");
loc += sizeof("dc=")-1;
dn = NULL;
loc = 0;
for (s = ldap_pvt_strtok(domain, ".", &tok_r);
s != NULL;
s = ldap_pvt_strtok(NULL, ".", &tok_r))
{
size_t len = strlen(s);
dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
if (dn == NULL) {
LDAP_FREE(dn);
LDAP_FREE(domain);
return LDAP_NO_MEMORY;
}
strcpy(dn + loc, s);
loc += len;
}
dn = dntmp;
LDAP_FREE(domain);
if (loc > 0) {
/* not first time. */
strcpy(dn + loc, ",");
loc++;
}
strcpy(dn + loc, "dc=");
loc += sizeof("dc=")-1;
*dnp = dn;
strcpy(dn + loc, s);
loc += len;
}
return LDAP_SUCCESS;
LDAP_FREE(domain);
*dnp = dn;
return LDAP_SUCCESS;
}
/*
......
......@@ -161,6 +161,7 @@ ldap_err2string( int err )
void
ldap_perror( LDAP *ld, LDAP_CONST char *str )
{
int i;
const struct ldaperror *e;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "ldap_perror\n", 0,0,0 );
......@@ -187,6 +188,13 @@ ldap_perror( LDAP *ld, LDAP_CONST char *str )
fprintf( stderr, "\tadditional info: %s\n", ld->ld_error );
}
if ( ld->ld_referrals != NULL && ld->ld_referrals[0] != NULL) {
fprintf( stderr, "\treferrals:\n" );
for (i=0; ld->ld_referrals[i]; i++) {
fprintf( stderr, "\t\t%s\n", ld->ld_referrals[i] );
}
}
fflush( stderr );
}
......@@ -282,6 +290,10 @@ ldap_parse_result(
LDAP_FREE( ld->ld_matched );
ld->ld_matched = NULL;
}
if ( ld->ld_referrals ) {
LDAP_VFREE( ld->ld_referrals );
ld->ld_referrals = NULL;
}
/* parse results */
......@@ -298,13 +310,7 @@ ldap_parse_result(
if( tag != LBER_ERROR ) {
/* peek for referrals */
if( ber_peek_tag(ber, &len) == LDAP_TAG_REFERRAL ) {
if( referralsp != NULL ) {
tag = ber_scanf( ber, "v", referralsp );
} else {
/* no place to put them so skip 'em */
tag = ber_scanf( ber, "x" );
}
tag = ber_scanf( ber, "v", &ld->ld_referrals );
}
}
......@@ -366,6 +372,10 @@ ldap_parse_result(
*errmsgp = LDAP_STRDUP( ld->ld_error );
}
if( referralsp != NULL) {
*referralsp = ldap_value_dup( ld->ld_referrals );
}
/* Find the next result... */
for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) {
/* skip over entries and references */
......
......@@ -175,3 +175,39 @@ ldap_value_free_len( struct berval **vals )
{
ber_bvecfree( vals );
}
char **
ldap_value_dup( char *const *vals )
{
char **new;
int i;
if( vals == NULL ) {
return NULL;
}
for( i=0; vals[i]; i++ ) {
; /* Count the number of values */
}
if( i == 0 ) {
return NULL;
}
new = LDAP_MALLOC( (i+1)*sizeof(char *) ); /* Alloc array of pointers */
if( new == NULL ) {
return NULL;
}
for( i=0; vals[i]; i++ ) {
new[i] = LDAP_STRDUP( vals[i] ); /* Dup each value */
if( new[i] == NULL ) {
LDAP_VFREE( new );
return NULL;
}
}
new[i] = NULL;
return new;
}
......@@ -295,6 +295,7 @@ struct ldap {
ber_int_t ld_errno;
char *ld_error;
char *ld_matched;
char **ld_referrals;
ber_len_t ld_msgid;
/* do not mess with these */
......@@ -574,6 +575,12 @@ LDAP_F (int) ldap_int_tls_config LDAP_P(( LDAP *ld,
LDAP_F (int) ldap_int_tls_start LDAP_P(( LDAP *ld,
LDAPConn *conn, LDAPURLDesc *srv ));
/*
* in getvalues.c
*/
LDAP_F (char **) ldap_value_dup LDAP_P((
char *const *vals ));
LDAP_END_DECL
#endif /* _LDAP_INT_H */
......@@ -250,6 +250,20 @@ ldap_get_option(
return LDAP_OPT_SUCCESS;
case LDAP_OPT_REFERRAL_URLS:
if(ld == NULL) {
/* bad param */
break;
}
if( ld->ld_referrals == NULL ) {
* (char ***) outvalue = NULL;
} else {
* (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
}
return LDAP_OPT_SUCCESS;
case LDAP_OPT_API_FEATURE_INFO: {
LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
int i;
......@@ -316,8 +330,9 @@ ldap_set_option(
* problem. Thus, we introduce a fix here.
*/
if (option == LDAP_OPT_DEBUG_LEVEL)
dbglvl = (int *) invalue;
if (option == LDAP_OPT_DEBUG_LEVEL) {
dbglvl = (int *) invalue;
}
if( lo->ldo_valid != LDAP_INITIALIZED ) {
ldap_int_initialize(lo, dbglvl);
......@@ -573,6 +588,21 @@ ldap_set_option(
ld->ld_matched = LDAP_STRDUP(err);
} return LDAP_OPT_SUCCESS;
case LDAP_OPT_REFERRAL_URLS: {
char *const *referrals = (char *const *) invalue;
if(ld == NULL) {
/* need a struct ldap */
break;
}
if( ld->ld_referrals ) {
LDAP_VFREE(ld->ld_referrals);
}
ld->ld_referrals = ldap_value_dup(referrals);
} return LDAP_OPT_SUCCESS;
case LDAP_OPT_API_FEATURE_INFO:
/* read-only */
break;
......@@ -584,7 +614,7 @@ ldap_set_option(
default:
#ifdef HAVE_TLS
if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
return LDAP_OPT_SUCCESS;
return LDAP_OPT_SUCCESS;
#endif
#ifdef HAVE_CYRUS_SASL
if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
......
......@@ -56,6 +56,11 @@ ldap_objectclass2name( LDAPObjectClass * oc )
return( choose_name( oc->oc_names, oc->oc_oid ) );
}
LDAP_CONST char *
ldap_contentrule2name( LDAPContentRule * cr )
{
return( choose_name( cr->cr_names, cr->cr_oid ) );
}
/*
* When pretty printing the entities we will be appending to a buffer.
......@@ -383,7 +388,7 @@ ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
print_qdstring(ss,mr->mr_desc);
}
if ( mr->mr_obsolete == LDAP_SCHEMA_YES ) {
if ( mr->mr_obsolete ) {
print_literal(ss, "OBSOLETE");
print_whsp(ss);
}
......@@ -442,7 +447,7 @@ ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
print_qdstring(ss,mru->mru_desc);
}
if ( mru->mru_obsolete == LDAP_SCHEMA_YES ) {
if ( mru->mru_obsolete ) {
print_literal(ss, "OBSOLETE");
print_whsp(ss);
}
......@@ -501,7 +506,7 @@ ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
print_qdstring(ss,oc->oc_desc);
}
if ( oc->oc_obsolete == LDAP_SCHEMA_YES ) {
if ( oc->oc_obsolete ) {
print_literal(ss, "OBSOLETE");
print_whsp(ss);
}
......@@ -555,6 +560,85 @@ ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
return(bv);
}
char *
ldap_contentrule2str( LDAPContentRule * cr )
{
struct berval bv;
if (ldap_contentrule2bv( cr, &bv ))
return(bv.bv_val);
else
return NULL;
}
struct berval *
ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
{
safe_string * ss;
ss = new_safe_string(256);
if ( !ss )
return NULL;
print_literal(ss,"("/*)*/);
print_whsp(ss);
print_numericoid(ss, cr->cr_oid);
print_whsp(ss);
if ( cr->cr_names ) {
print_literal(ss,"NAME");
print_qdescrs(ss,cr->cr_names);
}
if ( cr->cr_desc ) {
print_literal(ss,"DESC");
print_qdstring(ss,cr->cr_desc);
}
if ( cr->cr_obsolete ) {
print_literal(ss, "OBSOLETE");
print_whsp(ss);
}
if ( cr->cr_oc_oids_aux ) {
print_literal(ss,"AUX");
print_whsp(ss);
print_oids(ss,cr->cr_oc_oids_aux);
print_whsp(ss);
}
if ( cr->cr_at_oids_must ) {
print_literal(ss,"MUST");
print_whsp(ss);
print_oids(ss,cr->cr_at_oids_must);
print_whsp(ss);
}
if ( cr->cr_at_oids_may ) {
print_literal(ss,"MAY");
print_whsp(ss);
print_oids(ss,cr->cr_at_oids_may);
print_whsp(ss);
}
if ( cr->cr_at_oids_not ) {
print_literal(ss,"NOT");
print_whsp(ss);
print_oids(ss,cr->cr_at_oids_not);
print_whsp(ss);
}
print_whsp(ss);
print_extensions(ss, cr->cr_extensions);
print_literal(ss, /*(*/")");
bv->bv_val = safe_strdup(ss);
bv->bv_len = ss->pos;
safe_string_free(ss);
return(bv);
}
char *
ldap_attributetype2str( LDAPAttributeType * at )
{
......@@ -590,7 +674,7 @@ ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
print_qdstring(ss,at->at_desc);
}
if ( at->at_obsolete == LDAP_SCHEMA_YES ) {
if ( at->at_obsolete ) {
print_literal(ss, "OBSOLETE");
print_whsp(ss);
}
......@@ -2124,6 +2208,7 @@ ldap_str2objectclass( LDAP_CONST char * s,
!strcmp(sval, "STRUCTURAL") ||
!strcmp(sval, "AUXILIARY") ||
!strcmp(sval, "MUST") ||
!strcmp(sval, "MAY") ||
!strncmp(sval, "X-", 2) ) {
/* Missing OID, backtrack */
ss = savepos;
......@@ -2324,6 +2409,267 @@ ldap_str2objectclass( LDAP_CONST char * s,
}
}
void
ldap_contentrule_free(LDAPContentRule * cr)
{
LDAP_FREE(cr->cr_oid);
if (cr->cr_names) LDAP_VFREE(cr->cr_names);
if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
free_extensions(cr->cr_extensions);
LDAP_FREE(cr);
}
LDAPContentRule *
ldap_str2contentrule( LDAP_CONST char * s,
int * code,
LDAP_CONST char ** errp,
LDAP_CONST int flags )
{
int kind;
const char * ss = s;
char * sval;
int seen_name = 0;
int seen_desc = 0;
int seen_obsolete = 0;
int seen_aux = 0;
int seen_must = 0;
int seen_may = 0;
int seen_not = 0;
LDAPContentRule * cr;
char ** ext_vals;
const char * savepos;
if ( !s ) {
*code = LDAP_SCHERR_EMPTY;
*errp = "";
return NULL;
}
*errp = s;
cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
if ( !cr ) {
*code = LDAP_SCHERR_OUTOFMEM;
return NULL;
}
kind = get_token(&ss,&sval);
if ( kind != TK_LEFTPAREN ) {
*code = LDAP_SCHERR_NOLEFTPAREN;
LDAP_FREE(sval);
ldap_contentrule_free(cr);
return NULL;
}
/*
* Definitions MUST begin with an OID in the numericoid format.
* However, this routine is used by clients to parse the response
* from servers and very well known servers will provide an OID
* in the wrong format or even no OID at all. We do our best to
* extract info from those servers.
*/
parse_whsp(&ss);
savepos = ss;
cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
if ( !cr->cr_oid ) {
if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
/* Backtracking */
ss = savepos;
kind = get_token(&ss,&sval);
if ( kind == TK_BAREWORD ) {
if ( !strcmp(sval, "NAME") ||
!strcmp(sval, "DESC") ||
!strcmp(sval, "OBSOLETE") ||
!strcmp(sval, "AUX") ||
!strcmp(sval, "MUST") ||
!strcmp(sval, "MAY") ||
!strcmp(sval, "NOT") ||
!strncmp(sval, "X-", 2) ) {
/* Missing OID, backtrack */
ss = savepos;
} else if ( flags &
LDAP_SCHEMA_ALLOW_OID_MACRO ) {
/* Non-numerical OID, ignore */
int len = ss-savepos;
cr->cr_oid = LDAP_MALLOC(len+1);
strncpy(cr->cr_oid, savepos, len);
cr->cr_oid[len] = 0;
}
}
LDAP_FREE(sval);
} else {
*errp = ss;
ldap_contentrule_free(cr);
return NULL;
}
}
parse_whsp(&ss);
/*
* Beyond this point we will be liberal an accept the items
* in any order.
*/
while (1) {
kind = get_token(&ss,&sval);
switch (kind) {
case TK_EOS:
*code = LDAP_SCHERR_NORIGHTPAREN;
*errp = ss;
ldap_contentrule_free(cr);
return NULL;
case TK_RIGHTPAREN:
return cr;
case TK_BAREWORD:
if ( !strcmp(sval,"NAME") ) {
LDAP_FREE(sval);
if ( seen_name ) {
*code = LDAP_SCHERR_DUPOPT;
*errp = ss;
ldap_contentrule_free(cr);
return(NULL);
}
seen_name = 1;
cr->cr_names = parse_qdescrs(&ss,code);
if ( !cr->cr_names ) {
if ( *code != LDAP_SCHERR_OUTOFMEM )
*code = LDAP_SCHERR_BADNAME;
*errp = ss;
ldap_contentrule_free(cr);
return NULL;
}
} else if ( !strcmp(sval,"DESC") ) {
LDAP_FREE(sval);
if ( seen_desc ) {
*code = LDAP_SCHERR_DUPOPT;
*errp = ss;
ldap_contentrule_free(cr);
return(NULL);
}
seen_desc = 1;
parse_whsp(&ss);
kind = get_token(&ss,&sval);
if ( kind != TK_QDSTRING ) {
*code = LDAP_SCHERR_UNEXPTOKEN;
*errp = ss;
LDAP_FREE(sval);
ldap_contentrule_free(cr);
return NULL;
}
cr->cr_desc = sval;
parse_whsp(&ss);
} else if ( !strcmp(sval,"OBSOLETE") ) {
LDAP_FREE(sval);
if ( seen_obsolete ) {
*code = LDAP_SCHERR_DUPOPT;
*errp = ss;
ldap_contentrule_free(cr);
return(NULL);
}
seen_obsolete = 1;
cr->cr_obsolete = LDAP_SCHEMA_YES;
parse_whsp(&ss);
} else if ( !strcmp(sval,"AUX") ) {
LDAP_FREE(sval);
if ( seen_aux ) {
*code = LDAP_SCHERR_DUPOPT;
*errp = ss;
ldap_contentrule_free(cr);
return(NULL);