From: <svn...@op...> - 2010-01-18 19:41:46
|
Author: scriptor Date: Mon Jan 18 20:41:36 2010 New Revision: 6016 URL: http://www.opensync.org/changeset/6016 Log: The schema discovery still had issues. Should be fixed, now. Modified: plugins/ldap-sync/src/ldap_connect.c plugins/ldap-sync/src/ldap_plugin.h Modified: plugins/ldap-sync/src/ldap_connect.c ============================================================================== --- plugins/ldap-sync/src/ldap_connect.c Mon Jan 18 20:41:28 2010 (r6015) +++ plugins/ldap-sync/src/ldap_connect.c Mon Jan 18 20:41:36 2010 (r6016) @@ -703,10 +703,9 @@ /** - * @brief Sets the LDAP protocol version to be used (2 or 3) + * @brief This function sets the LDAP protocol version to be used (2 or 3). * * @param ctx The libopensync environment. - * @param info The environment for the whole plugin. * @param sinkenv Sink specific environment. * @param error The libopensync error pointer. * @@ -1304,34 +1303,46 @@ + + + + + + + + + /** - * @brief Check whether the LDAP server offers support for a - * particular LDAP schema, like - * "mozillaAbPersonAlpha", - * "evolutionPerson" or - * "InetOrgPerson" (RFC 2798). - * - * @param ctx The libopensync context - * @param sinkenv The object type specific environment - * @param ldap_schema The name of the LDAP schema to ask whether or not it - * is supported by the LDAP server. - * @param result As a result of this function this boolean variable is set - * to TRUE, if the LDAP schema requested is supported by the - * LDAP server. - * @param error The libopensync error pointer. + * @brief This function tries and find out which one is the correct search base + * to start a search from, when looking for the available schemata. + * This is the first step in what is called "the schema discovery". + * + * See also ldap_plugin_check_ldap_schema_support(). + * + * @param[in] ctx The libopensync context. + * @param[in] sinkenv The object type specific environment. + * @param[in] attribute_type This will indicate the attribute to search for + * when calling ldap_search(). + * @param[out] search_base As a result of this function, this will be filled + * with the search base to use when performing the + * second step of the schema discovery. Usually + * "cn=Subschema" with slapd from openldap, or + * "cn=schema" with ns-slapd from 389-ds (fedora-ds). + * @param[out] error * - * @returns TRUE if this function could perform the check successfully (regardless of the result), FALSE on error. + * @returns TRUE on success, FALSE in case of any error. */ -osync_bool ldap_plugin_check_ldap_schema_support(OSyncContext *ctx, sink_environment *sinkenv, const char *ldap_schema, osync_bool *result, OSyncError **error) +osync_bool +ldap_plugin_schema_discovery_first_step(OSyncContext *ctx, sink_environment *sinkenv, int attribute_type, char **search_base, OSyncError **error) { - LDAPMessage *res = NULL, *res2 = NULL, *res3 = NULL, *res4 = NULL; - int i = 0; - struct berval **ber = NULL, **ber2 = NULL; + struct berval **ber2 = NULL; BerElement *ber3 = NULL; - char *search_base = NULL, *attr = NULL; + LDAPMessage *res3 = NULL, *res4 = NULL; + char *attr = NULL; + int i = 0; - osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, (void *)ctx, (void *)sinkenv, (void *)ldap_schema, (void *)result, (void *)error); + osync_trace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p)", __func__, (void *)ctx, (void *)sinkenv, attribute_type, (void *)search_base, (void *)error); if (ctx == NULL) { @@ -1339,37 +1350,20 @@ goto error; } - if (sinkenv == NULL) { osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: sinkenv = NULL. Returning.\n", __FILE__, __LINE__); goto error; } - if (result == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: result = NULL. Returning.\n", __FILE__, __LINE__); - goto error; - } - - if (ldap_schema == NULL) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_schema = NULL. Returning.\n", __FILE__, __LINE__); + if (search_base == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: search_base = NULL. Returning.\n", __FILE__, __LINE__); goto error; } - if (ldap_schema[0] == 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_schema[0] = 0. Returning.\n", __FILE__, __LINE__); - goto error; - } - *result = FALSE; - - // Get the relevant search_base. It may differ from server to server. -#ifdef USE_MOZLDAP - if (!ldap_plugin_call_ldap_search(ctx, sinkenv->ld, "", "(objectClass=*)", LDAP_SCOPE_BASE, FEDORADSsubschemaSubentry, sinkenv, TRUE, &res3, error)) -#else - if (!ldap_plugin_call_ldap_search(ctx, sinkenv->ld, "", "(objectClass=*)", LDAP_SCOPE_BASE, OPERATIONAL_ATTRIBUTES, sinkenv, TRUE, &res3, error)) -#endif + if (!ldap_plugin_call_ldap_search(ctx, sinkenv->ld, "", "(objectClass=*)", LDAP_SCOPE_BASE, attribute_type, sinkenv, TRUE, &res3, error)) { if (!osync_error_is_set(error)) { osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_plugin_call_ldap_search() has failed.\n", __FILE__, __LINE__); @@ -1430,7 +1424,7 @@ #ifdef DEBUG_subschema_discovery ldap_plugin_printf("%s ", ber2[i]->bv_val); #endif - search_base = g_strdup(ber2[i]->bv_val); + *search_base = g_strdup(ber2[i]->bv_val); break; } @@ -1440,17 +1434,18 @@ #ifdef DEBUG_subschema_discovery ldap_plugin_printf("\n-------------------------\n"); #endif - if (search_base != NULL && search_base[0] != 0) { + if (*search_base != NULL && (*search_base)[0] != 0) { break; } } else { ldap_plugin_printf("%s:%i: WARNING: ber2 = NULL.", __FILE__, __LINE__); } - ldap_memfree(attr); + ldap_memfree(attr); + attr = NULL; } - if (search_base != NULL && search_base[0] != 0) { + if (*search_base != NULL && (*search_base)[0] != 0) { break; } } @@ -1460,7 +1455,162 @@ - // We haven't found the real search_base, yet. So let's assume, it is + if (attr) { + ldap_memfree(attr); + attr = NULL; + } + + if (res3) { + ldap_msgfree(res3); + res3 = NULL; + } + + osync_trace(TRACE_EXIT, "%s", __func__); + return TRUE; + + +error: + if (attr){ + ldap_memfree(attr); + attr = NULL; + } + + if (res3){ + ldap_msgfree(res3); + res3 = NULL; + } + + + if (!osync_error_is_set(error)) + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); + + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return FALSE; +} + + + + + + + + + +/** + * @brief Check whether the LDAP server offers support for a + * particular LDAP schema, like + * "mozillaAbPersonAlpha", + * "evolutionPerson" or + * "InetOrgPerson" (RFC 2798). + * + * @remarks Schema discovery must be performed in two steps: + * 1. Which one is the search base to start the search from? + * 2. Which are the objectclasses that can be found at this + * very search base? + * + * @example slapd from openldap: + * + * 1. + * ldapsearch -h 192.168.1.2 -p 389 -Y GSSAPI -LLL -Q -b "" -s base subschemaSubentry + * dn: + * subschemaSubentry: cn=Subschema + * + * 2. + * ldapsearch -h 192.168.1.2 -p 389 -Y GSSAPI -LLL -Q -b 'cn=Subschema' -s base '(objectClass=subschema)' objectClasses + * + * + * + * @example ns-slapd (389-ds = fedora-ds): + * + * 1. + * ldapsearch -h 192.168.1.2 -p 3890 -Y GSSAPI -LLL -Q -b "" -s base subschemaSubentry + * dn: + * subschemaSubentry: cn=schema + * + * 2. + * ldapsearch -h 192.168.1.2 -p 3890 -Y GSSAPI -LLL -Q -b 'cn=schema' -s base '(objectClass=subschema)' objectClasses + * + * + * @param ctx The libopensync context. + * @param sinkenv The object type specific environment. + * @param ldap_schema The name of the LDAP schema to ask whether or not it + * is supported by the LDAP server. + * @param result As a result of this function this boolean variable is set + * to TRUE, if the LDAP schema requested is supported by the + * LDAP server. + * @param error The libopensync error pointer. + * + * @returns TRUE if this function could perform the check successfully (regardless of the result), FALSE on error. + */ +osync_bool ldap_plugin_check_ldap_schema_support(OSyncContext *ctx, sink_environment *sinkenv, const char *ldap_schema, osync_bool *result, OSyncError **error) +{ + LDAPMessage *res = NULL, *res2 = NULL; + int i = 0; + struct berval **ber = NULL; + char *search_base = NULL; + + + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, (void *)ctx, (void *)sinkenv, (void *)ldap_schema, (void *)result, (void *)error); + + + if (ctx == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ctx = NULL. Returning.\n", __FILE__, __LINE__); + goto error; + } + + + if (sinkenv == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: sinkenv = NULL. Returning.\n", __FILE__, __LINE__); + goto error; + } + + if (result == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: result = NULL. Returning.\n", __FILE__, __LINE__); + goto error; + } + + if (ldap_schema == NULL) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_schema = NULL. Returning.\n", __FILE__, __LINE__); + goto error; + } + + if (ldap_schema[0] == 0) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_schema[0] = 0. Returning.\n", __FILE__, __LINE__); + goto error; + } + + + *result = FALSE; + + + /****************** Schema discovery, 1st step **********************/ + // Get the relevant search_base. It may differ from server to server. + // And from library to library. + if (!ldap_plugin_schema_discovery_first_step(ctx, sinkenv, SUBSCHEMASUBENTRY, &search_base, error)){ + if (!osync_error_is_set(error)) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_plugin_schema_discovery_first_step() has failed.\n", __FILE__, __LINE__); + } + + goto error; + } + + + /************* Schema discovery, 1st step has failed **************/ + if (search_base == NULL) { + // Fall back to a slightly modified search, that would at least work + // with slapd from openldap: + if (!ldap_plugin_schema_discovery_first_step(ctx, sinkenv, OPERATIONAL_ATTRIBUTES, &search_base, error)){ + if (!osync_error_is_set(error)) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "%s:%i: ERROR: ldap_plugin_schema_discovery_first_step() has failed.\n", __FILE__, __LINE__); + } + + goto error; + } + } + + + /********* Schema discovery, 1st step has failed, again ************/ + // We still haven't found the real search_base, yet. So let's assume, it is // "cn=Subschema" or "cn=schema" for ns-slapd. if (search_base == NULL) { #ifdef USE_MOZLDAP @@ -1473,6 +1623,7 @@ } + /***************** Schema discovery, 2nd step ***********************/ // Look for all the LDAP subschemata (as used by slapd from openldap): if (!ldap_plugin_call_ldap_search(ctx, sinkenv->ld, search_base, "(objectClass=subschema)", LDAP_SCOPE_BASE, OBJECTCLASSES, sinkenv, TRUE, &res, error)) { if (!osync_error_is_set(error)) { @@ -1533,6 +1684,7 @@ if (ber) { while (ber[i]) { if (strstr(ber[i]->bv_val, ldap_schema)) { + // Found! *result = TRUE; break; } @@ -1550,9 +1702,6 @@ if (res) ldap_msgfree(res); - if (res3) - ldap_msgfree(res3); - if (search_base) g_free(search_base); @@ -1568,16 +1717,12 @@ if (res) ldap_msgfree(res); - if (res3) - ldap_msgfree(res3); - if (search_base) g_free(search_base); if (!osync_error_is_set(error)) osync_error_set(error, OSYNC_ERROR_GENERIC, "Unknown reason.\n"); - osync_context_report_osyncwarning(ctx, *error); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } @@ -1843,7 +1988,7 @@ userattributes[0] = "modifyTimestamp"; break; - case FEDORADSsubschemaSubentry: + case SUBSCHEMASUBENTRY: userattributes[0] = "subschemaSubentry"; break; Modified: plugins/ldap-sync/src/ldap_plugin.h ============================================================================== --- plugins/ldap-sync/src/ldap_plugin.h Mon Jan 18 20:41:28 2010 (r6015) +++ plugins/ldap-sync/src/ldap_plugin.h Mon Jan 18 20:41:36 2010 (r6016) @@ -238,7 +238,7 @@ ///< LDAP_ALL_USER_ATTRIBUTES and ///< LDAP_ALL_OPERATIONAL_ATTRIBUTES. ///< This is sloppy. -#define FEDORADSsubschemaSubentry 5 ///< dto. +#define SUBSCHEMASUBENTRY 5 ///< dto. @@ -533,6 +533,7 @@ osync_bool ldap_plugin_report_sasl_authentication_error(sink_environment *sinkenv, const char *file, const int line, const int ldap_errno, const struct berval passwd, char *tmp_authmech, char *tmp_authcid, OSyncError **error); osync_bool ldap_plugin_report_simple_authentication_error(sink_environment *sinkenv, const char *file, const int line, const int ldap_errno, const char *binddn, const struct berval passwd, OSyncError **error); osync_bool ldap_plugin_rewrite_ldap_entry(ldap_entry *entry, GList *modifications, OSyncError **error); +osync_bool ldap_plugin_schema_discovery_first_step(OSyncContext *ctx, sink_environment *sinkenv, int attribute_type, char **search_base, OSyncError **error); osync_bool ldap_plugin_set_ldap_protocol (OSyncContext *ctx, sink_environment *sinkenv, OSyncError **error); |