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; }
/* * 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; }