Exemple #1
0
int
LDAP_CALL
ldap_is_ldap_url( const char *url )
{
	int	enclosed, secure;

	return( url != NULL
	    && skip_url_prefix( &url, &enclosed, &secure ));
}
/**
 * Is this URL an ldap socket url?
 *
 */
APU_DECLARE(int) apr_ldap_is_ldapi_url(const char *url)
{
    int enclosed;
    const char * scheme;

    if( url == NULL ) {
        return 0;
    }

    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
        return 0;
    }

    return strcmp(scheme, "ldapi") == 0;
}
Exemple #3
0
/*
 * like ldap_url_parse() with a few exceptions:
 *   1) if dn_required is zero, a missing DN does not generate an error
 *	(we just leave the lud_dn field NULL)
 *   2) no defaults are set for lud_scope and lud_filter (they are set to -1
 *	and NULL respectively if no SCOPE or FILTER are present in the URL).
 *   3) when there is a zero-length DN in a URL we do not set lud_dn to NULL.
 *
 * note that LDAPv3 URL extensions are ignored unless they are marked
 * critical, in which case an LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION error
 * is returned.
 */
int
nsldapi_url_parse( const char *url, LDAPURLDesc **ludpp, int dn_required )
{

	LDAPURLDesc	*ludp;
	char		*urlcopy, *attrs, *scope, *extensions = NULL, *p, *q;
	int		enclosed, secure, i, nattrs, at_start;

	LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_url_parse(%s)\n", url, 0, 0 );

	if ( url == NULL || ludpp == NULL ) {
		return( LDAP_URL_ERR_PARAM );
	}

	*ludpp = NULL;	/* pessimistic */

	if ( !skip_url_prefix( &url, &enclosed, &secure )) {
		return( LDAP_URL_ERR_NOTLDAP );
	}

	/* allocate return struct */
	if (( ludp = (LDAPURLDesc *)NSLDAPI_CALLOC( 1, sizeof( LDAPURLDesc )))
	    == NULLLDAPURLDESC ) {
		return( LDAP_URL_ERR_MEM );
	}

	if ( secure ) {
		ludp->lud_options |= LDAP_URL_OPT_SECURE;
	}

	/* make working copy of the remainder of the URL */
	if (( urlcopy = nsldapi_strdup( url )) == NULL ) {
		ldap_free_urldesc( ludp );
		return( LDAP_URL_ERR_MEM );
	}

	if ( enclosed && *((p = urlcopy + strlen( urlcopy ) - 1)) == '>' ) {
		*p = '\0';
	}

	/* initialize scope and filter */
	ludp->lud_scope = -1;
	ludp->lud_filter = NULL;

	/* lud_string is the only malloc'd string space we use */
	ludp->lud_string = urlcopy;

	/* scan forward for '/' that marks end of hostport and begin. of dn */
	if (( ludp->lud_dn = strchr( urlcopy, '/' )) == NULL ) {
		if ( dn_required ) {
			ldap_free_urldesc( ludp );
			return( LDAP_URL_ERR_NODN );
		}
	} else {
		/* terminate hostport; point to start of dn */
		*ludp->lud_dn++ = '\0';
	}


	if ( *urlcopy == '\0' ) {
		ludp->lud_host = NULL;
	} else {
		ludp->lud_host = urlcopy;
		nsldapi_hex_unescape( ludp->lud_host );

		/*
		 * Locate and strip off optional port number (:#) in host
		 * portion of URL.
		 *
		 * If more than one space-separated host is listed, we only
		 * look for a port number within the right-most one since
		 * ldap_init() will handle host parameters that look like
		 * host:port anyway.
		 */
		if (( p = strrchr( ludp->lud_host, ' ' )) == NULL ) {
			p = ludp->lud_host;
		} else {
			++p;
		}
		if ( *p == '[' && ( q = strchr( p, ']' )) != NULL ) {
			 /* square brackets present -- skip past them */
			p = q++;
		}
		if (( p = strchr( p, ':' )) != NULL ) {
			*p++ = '\0';
			ludp->lud_port = atoi( p );
			if ( *ludp->lud_host == '\0' ) {
				ludp->lud_host = NULL;  /* no hostname */
			}
		}
	}

	/* scan for '?' that marks end of dn and beginning of attributes */
	attrs = NULL;
	if ( ludp->lud_dn != NULL &&
	    ( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) {
		/* terminate dn; point to start of attrs. */
		*attrs++ = '\0';

		/* scan for '?' that marks end of attrs and begin. of scope */
		if (( p = strchr( attrs, '?' )) != NULL ) {
			/*
			 * terminate attrs; point to start of scope and scan for
			 * '?' that marks end of scope and begin. of filter
			 */
			*p++ = '\0';
			scope = p;

			if (( p = strchr( scope, '?' )) != NULL ) {
				/* terminate scope; point to start of filter */
				*p++ = '\0';
				if ( *p != '\0' ) {
					ludp->lud_filter = p;
					/*
					 * scan for the '?' that marks the end
					 * of the filter and the start of any
					 * extensions
					 */
					if (( p = strchr( ludp->lud_filter, '?' ))
					    != NULL ) {
						*p++ = '\0'; /* term. filter */
						extensions = p;
					}
					if ( *ludp->lud_filter == '\0' ) {
						ludp->lud_filter = NULL;
					} else {
						nsldapi_hex_unescape( ludp->lud_filter );
					}
				}
			}

			if ( strcasecmp( scope, "one" ) == 0 ) {
				ludp->lud_scope = LDAP_SCOPE_ONELEVEL;
			} else if ( strcasecmp( scope, "base" ) == 0 ) {
				ludp->lud_scope = LDAP_SCOPE_BASE;
			} else if ( strcasecmp( scope, "sub" ) == 0 ) {
				ludp->lud_scope = LDAP_SCOPE_SUBTREE;
			} else if ( *scope != '\0' ) {
				ldap_free_urldesc( ludp );
				return( LDAP_URL_ERR_BADSCOPE );
			}
		}
	}

	if ( ludp->lud_dn != NULL ) {
		nsldapi_hex_unescape( ludp->lud_dn );
	}

	/*
	 * if attrs list was included, turn it into a null-terminated array
	 */
	if ( attrs != NULL && *attrs != '\0' ) {
		nsldapi_hex_unescape( attrs );
		for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) {
		    if ( *p == ',' ) {
			    ++nattrs;
		    }
		}

		if (( ludp->lud_attrs = (char **)NSLDAPI_CALLOC( nattrs + 1,
		    sizeof( char * ))) == NULL ) {
			ldap_free_urldesc( ludp );
			return( LDAP_URL_ERR_MEM );
		}

		for ( i = 0, p = attrs; i < nattrs; ++i ) {
			ludp->lud_attrs[ i ] = p;
			if (( p = strchr( p, ',' )) != NULL ) {
				*p++ ='\0';
			}
			nsldapi_hex_unescape( ludp->lud_attrs[ i ] );
		}
	}

	/* if extensions list was included, check for critical ones */
	if ( extensions != NULL && *extensions != '\0' ) {
		/* Note: at present, we do not recognize ANY extensions */
		at_start = 1;
		for ( p = extensions; *p != '\0'; ++p ) {
			if ( at_start ) {
				if ( *p == '!' ) {	/* critical extension */
					ldap_free_urldesc( ludp );
					return( LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION );
				}
				at_start = 0;
			} else if ( *p == ',' ) {
				at_start = 1;
			}
		}
	}

	*ludpp = ludp;

	return( 0 );
}
/**
 * Parse the URL provided into an apr_ldap_url_desc_t object.
 *
 * APR_SUCCESS is returned on success, APR_EGENERAL on failure.
 * The LDAP result code and reason string is returned in the
 * apr_ldap_err_t structure.
 */
APU_DECLARE(int) apr_ldap_url_parse_ext(apr_pool_t *pool,
                                        const char *url_in,
                                        apr_ldap_url_desc_t **ludpp,
                                        apr_ldap_err_t **result_err)
{
    apr_ldap_url_desc_t *ludp;
    char        *p, *q, *r;
    int         i, enclosed;
    const char  *scheme = NULL;
    const char  *url_tmp;
    char        *url;

    apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
    *result_err = result;

    /* sanity check our parameters */
    if( url_in == NULL || ludpp == NULL ) {
        result->reason = "Either the LDAP URL, or the URL structure was NULL. Oops.";
        result->rc = APR_LDAP_URL_ERR_PARAM;
        return APR_EGENERAL;
    }

    *ludpp = NULL;  /* pessimistic */

    url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
    if ( url_tmp == NULL ) {
        result->reason = "The scheme was not recognised as a valid LDAP URL scheme.";
        result->rc = APR_LDAP_URL_ERR_BADSCHEME;
        return APR_EGENERAL;
    }

    /* make working copy of the remainder of the URL */
    url = (char *)apr_pstrdup(pool, url_tmp);
    if ( url == NULL ) {
        result->reason = "Out of memory parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_MEM;
        return APR_EGENERAL;
    }

    if ( enclosed ) {
        p = &url[strlen(url)-1];

        if( *p != '>' ) {
            result->reason = "Bad enclosure error while parsing LDAP URL.";
            result->rc = APR_LDAP_URL_ERR_BADENCLOSURE;
            return APR_EGENERAL;
        }

        *p = '\0';
    }

    /* allocate return struct */
    ludp = (apr_ldap_url_desc_t *)apr_pcalloc(pool, sizeof(apr_ldap_url_desc_t));
    if ( ludp == NULL ) {
        result->reason = "Out of memory parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_MEM;
        return APR_EGENERAL;
    }

    ludp->lud_next = NULL;
    ludp->lud_host = NULL;
    ludp->lud_port = LDAP_PORT;
    ludp->lud_dn = NULL;
    ludp->lud_attrs = NULL;
    ludp->lud_filter = NULL;
    ludp->lud_scope = -1;
    ludp->lud_filter = NULL;
    ludp->lud_exts = NULL;

    ludp->lud_scheme = (char *)apr_pstrdup(pool, scheme);
    if ( ludp->lud_scheme == NULL ) {
        result->reason = "Out of memory parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_MEM;
        return APR_EGENERAL;
    }

    if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
        ludp->lud_port = LDAPS_PORT;
    }

    /* scan forward for '/' that marks end of hostport and begin. of dn */
    p = strchr( url, '/' );

    if( p != NULL ) {
        /* terminate hostport; point to start of dn */
        *p++ = '\0';
    }

    /* IPv6 syntax with [ip address]:port */
    if ( *url == '[' ) {
        r = strchr( url, ']' );
        if ( r == NULL ) {
            result->reason = "Bad LDAP URL while parsing IPV6 syntax.";
            result->rc = APR_LDAP_URL_ERR_BADURL;
            return APR_EGENERAL;
        }
        *r++ = '\0';
        q = strrchr( r, ':' );
    } else {
        q = strrchr( url, ':' );
    }

    if ( q != NULL ) {
        apr_ldap_pvt_hex_unescape( ++q );

        if( *q == '\0' ) {
            result->reason = "Bad LDAP URL while parsing.";
            result->rc = APR_LDAP_URL_ERR_BADURL;
            return APR_EGENERAL;
        }

        ludp->lud_port = atoi( q );
    }

    apr_ldap_pvt_hex_unescape( url );

    /* If [ip address]:port syntax, url is [ip and we skip the [ */
    ludp->lud_host = (char *)apr_pstrdup(pool, url + ( *url == '[' ));
    if( ludp->lud_host == NULL ) {
        result->reason = "Out of memory parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_MEM;
        return APR_EGENERAL;
    }

    /*
     * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
     *
     * On early Novell releases, search references/referrals were returned
     * in this format, i.e., the dn was kind of in the scope position,
     * but the required slash is missing. The whole thing is illegal syntax,
     * but we need to account for it. Fortunately it can't be confused with
     * anything real.
     */
    if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
        q++;
        /* ? immediately followed by question */
        if( *q == '?') {
            q++;
            if( *q != '\0' ) {
                /* parse dn part */
                apr_ldap_pvt_hex_unescape( q );
                ludp->lud_dn = (char *)apr_pstrdup(pool, q);
            } else {
                ludp->lud_dn = (char *)apr_pstrdup(pool, "");
            }

            if( ludp->lud_dn == NULL ) {
                result->reason = "Out of memory parsing LDAP URL.";
                result->rc = APR_LDAP_URL_ERR_MEM;
                return APR_EGENERAL;
            }
        }
    }

    if( p == NULL ) {
        *ludpp = ludp;
        return APR_SUCCESS;
    }

    /* scan forward for '?' that may marks end of dn */
    q = strchr( p, '?' );

    if( q != NULL ) {
        /* terminate dn part */
        *q++ = '\0';
    }

    if( *p != '\0' ) {
        /* parse dn part */
        apr_ldap_pvt_hex_unescape( p );
        ludp->lud_dn = (char *)apr_pstrdup(pool, p);
    } else {
        ludp->lud_dn = (char *)apr_pstrdup(pool, "");
    }

    if( ludp->lud_dn == NULL ) {
        result->reason = "Out of memory parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_MEM;
        return APR_EGENERAL;
    }

    if( q == NULL ) {
        /* no more */
        *ludpp = ludp;
        return APR_SUCCESS;
    }

    /* scan forward for '?' that may marks end of attributes */
    p = q;
    q = strchr( p, '?' );

    if( q != NULL ) {
        /* terminate attributes part */
        *q++ = '\0';
    }

    if( *p != '\0' ) {
        /* parse attributes */
        apr_ldap_pvt_hex_unescape( p );
        ludp->lud_attrs = apr_ldap_str2charray(pool, p, ",");

        if( ludp->lud_attrs == NULL ) {
            result->reason = "Bad attributes encountered while parsing LDAP URL.";
            result->rc = APR_LDAP_URL_ERR_BADATTRS;
            return APR_EGENERAL;
        }
    }

    if ( q == NULL ) {
        /* no more */
        *ludpp = ludp;
        return APR_SUCCESS;
    }

    /* scan forward for '?' that may marks end of scope */
    p = q;
    q = strchr( p, '?' );

    if( q != NULL ) {
        /* terminate the scope part */
        *q++ = '\0';
    }

    if( *p != '\0' ) {
        /* parse the scope */
        apr_ldap_pvt_hex_unescape( p );
        ludp->lud_scope = str2scope( p );

        if( ludp->lud_scope == -1 ) {
            result->reason = "Bad scope encountered while parsing LDAP URL.";
            result->rc = APR_LDAP_URL_ERR_BADSCOPE;
            return APR_EGENERAL;
        }
    }

    if ( q == NULL ) {
        /* no more */
        *ludpp = ludp;
        return APR_SUCCESS;
    }

    /* scan forward for '?' that may marks end of filter */
    p = q;
    q = strchr( p, '?' );

    if( q != NULL ) {
        /* terminate the filter part */
        *q++ = '\0';
    }

    if( *p != '\0' ) {
        /* parse the filter */
        apr_ldap_pvt_hex_unescape( p );

        if( ! *p ) {
            /* missing filter */
            result->reason = "Bad filter encountered while parsing LDAP URL.";
            result->rc = APR_LDAP_URL_ERR_BADFILTER;
            return APR_EGENERAL;
        }

        ludp->lud_filter = (char *)apr_pstrdup(pool, p);
        if( ludp->lud_filter == NULL ) {
            result->reason = "Out of memory parsing LDAP URL.";
            result->rc = APR_LDAP_URL_ERR_MEM;
            return APR_EGENERAL;
        }
    }

    if ( q == NULL ) {
        /* no more */
        *ludpp = ludp;
        return APR_SUCCESS;
    }

    /* scan forward for '?' that may marks end of extensions */
    p = q;
    q = strchr( p, '?' );

    if( q != NULL ) {
        /* extra '?' */
        result->reason = "Bad URL encountered while parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_BADURL;
        return APR_EGENERAL;
    }

    /* parse the extensions */
    ludp->lud_exts = apr_ldap_str2charray(pool, p, ",");
    if( ludp->lud_exts == NULL ) {
        result->reason = "Bad extensions encountered while parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_BADEXTS;
        return APR_EGENERAL;
    }

    for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
        apr_ldap_pvt_hex_unescape( ludp->lud_exts[i] );

        if( *ludp->lud_exts[i] == '!' ) {
            /* count the number of critical extensions */
            ludp->lud_crit_exts++;
        }
    }

    if( i == 0 ) {
        /* must have 1 or more */
        result->reason = "Bad extensions encountered while parsing LDAP URL.";
        result->rc = APR_LDAP_URL_ERR_BADEXTS;
        return APR_EGENERAL;
    }

    /* no more */
    *ludpp = ludp;
    return APR_SUCCESS;
}