#include "ldap_plugin.h" #include int lutil_sasl_interact( LDAP *ld, unsigned flags, lutilSASLdefaults *defaults, void *in ) { sasl_interact_t *interact = in; if( ld == NULL ) return LDAP_PARAM_ERROR; while( interact->id != SASL_CB_LIST_END ) { switch( interact->id ) { case SASL_CB_GETREALM: interact->result = (defaults->realm && *defaults->realm) ? defaults->realm : ""; interact->len = strlen( interact->result ); break; case SASL_CB_AUTHNAME: interact->result = (defaults->authcid && *defaults->authcid) ? defaults->authcid : ""; interact->len = strlen( interact->result ); break; case SASL_CB_PASS: interact->result = (defaults->passwd && *defaults->passwd) ? defaults->passwd : ""; interact->len = strlen( interact->result ); break; case SASL_CB_USER: interact->result = (defaults->authzid && *defaults->authzid) ? defaults->authzid : ""; interact->len = strlen( interact->result ); break; } interact++; } return LDAP_SUCCESS; } lutilSASLdefaults *lutil_sasl_defaults(LDAP *ld, char *mech, char *realm, char *authcid, char *passwd, char *authzid) { lutilSASLdefaults *defaults; defaults = ber_memalloc( sizeof( lutilSASLdefaults ) ); if( defaults == NULL ) return NULL; defaults->mech = mech ? ber_strdup(mech) : NULL; defaults->realm = realm ? ber_strdup(realm) : NULL; defaults->authcid = authcid ? ber_strdup(authcid) : NULL; defaults->passwd = passwd ? ber_strdup(passwd) : NULL; defaults->authzid = authzid ? ber_strdup(authzid) : NULL; if( defaults->mech == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech ); } if( defaults->realm == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm ); } if( defaults->authcid == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid ); } if( defaults->authzid == NULL ) { ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid ); } defaults->resps = NULL; defaults->nresps = 0; return defaults; } /*Connect and bind to a ldap server*/ int ldap_start(ldap_connection *conn) { int ldap_vers = LDAP_VERSION3; ldap_debug(conn, 2, "Connecting to %s", conn->servername); if (ldap_is_ldap_url(conn->servername) || ldap_is_ldaps_url(conn->servername)) { ldap_initialize(&conn->ld, conn->servername); if( conn->ld == NULL ) { ldap_debug(conn, 0, "Could not connect to %s", conn->servername); return 1; } } else { conn->ld = ldap_init(conn->servername, conn->serverport); if( conn->ld == NULL ) { ldap_debug(conn, 0, "Could not connect to %s on %i", conn->servername, conn->serverport); return 1; } } return 0; } int ldap_set_version(ldap_connection *conn) { int *ldap_version = 0; if (ldap_set_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION, &conn->ldap_version) != LDAP_SUCCESS) { ldap_get_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION, ldap_version); ldap_debug(conn, 1, "Could not set Ldap Version to %i using %i", conn->ldap_version, *ldap_version); conn->ldap_version = *ldap_version; return 1; } return 0; } int ldap_encrypt(ldap_connection *conn) { if (ldap_start_tls_s(conn->ld, NULL, NULL) != LDAP_SUCCESS) { ldap_debug(conn, 1, "Could not start encryption"); return 1; } return 0; } int ldap_makebind(ldap_connection *conn) { unsigned sasl_flags = LDAP_SASL_AUTOMATIC; struct berval passwd = { 0, NULL }; lutilSASLdefaults *defaults; char *authmech, *binddn, *pwd; if (!conn->anonymous) { binddn = conn->binddn; pwd = conn->pwd; authmech = conn->authmech; } else { authmech = "SIMPLE"; binddn = ""; pwd = ""; } if (!strcmp(authmech, "SIMPLE")) { ldap_debug(conn, 2, "Simple auth selected"); if (ldap_simple_bind_s(conn->ld, binddn, pwd)) { ldap_debug(conn, 0, "Unable to connect and bind to %s as %s", conn->servername, binddn); return 1; } } else { ldap_debug(conn, 2, "Sasl auth selected"); passwd.bv_val = ber_strdup(conn->pwd); passwd.bv_len = strlen( passwd.bv_val ); defaults = lutil_sasl_defaults(conn->ld, ber_strdup(conn->authmech), NULL, ber_strdup(conn->binddn), passwd.bv_val, NULL); if (ldap_sasl_interactive_bind_s(conn->ld, NULL, ber_strdup(conn->authmech), NULL, NULL, sasl_flags, (LDAP_SASL_INTERACT_PROC *)lutil_sasl_interact, (void *)defaults ) != LDAP_SUCCESS) { ldap_debug(conn, 0, "Unable to connect and sasl bind to %s as %s", conn->servername, conn->binddn); return 1; } } return 0; } int ldap_check_evolution(ldap_connection *conn) { LDAPMessage *res, *res2; int i = 0; char *attrs[] = {"objectClasses", NULL}; char **ldapvals = NULL; //Search all entries that apply to the filter. modifyTimestamp if (ldap_search_s(conn->ld, "cn=Subschema", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &res)) { ldap_debug(conn, 0, "Unable to search for evolution support"); return 1; } res2 = ldap_first_entry(conn->ld, res); if (!res2) { ldap_debug(conn, 0, "No objectclass entries found"); return 1; } ldapvals = ldap_get_values(conn->ld, res2, "objectClasses"); while (ldapvals[i]) { if (strstr(ldapvals[i], "evolutionPerson")) { ldap_value_free(ldapvals); return 0; } i++; } return 1; } /* struct data_entry *ldap_get_entry(ldap_connection *conn, char *uid) { LDAPMessage *res, *res2; struct data_entry *entry = NULL; char *attrs[] = {"modifyTimestamp", NULL}; entry = g_malloc0(sizeof(struct data_entry)); char filter[1024]; uid = quoted_decode(uid); ldap_debug(conn, 2, "Loading single head data for %s", ldap_explode_dn(uid, 0)[0]); //Search all entries that apply to the filter. get modifyTimestamp sprintf(filter, "(%s)", ldap_explode_dn(uid, 0)[0]); if (ldap_search_s(conn->ld, conn->searchbase, LDAP_SCOPE_ONELEVEL, filter, attrs, 0, &res)) { ldap_debug(conn, 0, "Unable to search on %s", conn->searchbase); return NULL; } res2 = ldap_first_entry(conn->ld, res); if (!res2) { ldap_debug(conn, 2, "No entries found"); return NULL; } do { if (!strcmp(ldap_get_dn(conn->ld, res2), uid)) { entry->modifyTimestamp = (ldap_get_values(conn->ld, res2, "modifyTimestamp"))[0]; entry->uid = quoted_encode(ldap_get_dn(conn->ld, res2)); ldap_debug(conn, 2, "Loaded entry: %s, %s", entry->modifyTimestamp, entry->uid); break; } res2 = ldap_next_entry(conn->ld, res2); } while (res2); ldap_debug(conn, 3, "done: ldap_get_entry"); return entry; }*/ /*load the head data from the ldap server*/ GList *load_ldap_entries(ldap_connection *conn) { LDAPMessage *res, *res2; GList *headlist = NULL; struct data_entry *entry = NULL; char *attrs[] = {"modifyTimestamp", NULL}; char **ldapvals = NULL; char filter[1024]; ldap_debug(conn, 2, "Loading head data from ldap"); //Search all entries that apply to the filter. get modifyTimestamp sprintf(filter, "(&(objectClass=*)%s)", conn->filter); if (ldap_search_s(conn->ld, conn->searchbase, conn->scope, filter, attrs, 0, &res)) { ldap_debug(conn, 0, "Unable to search on %s with filter %s", conn->searchbase, filter); return NULL; } res2 = ldap_first_entry(conn->ld, res); if (!res2) { ldap_debug(conn, 2, "No entries found"); return NULL; } do { //We have a new entry entry = g_malloc0(sizeof(struct data_entry)); ldapvals = ldap_get_values(conn->ld, res2, "modifyTimestamp"); if (ldapvals) { entry->modifyTimestamp = strdup(ldapvals[0]); ldap_value_free(ldapvals); entry->uid = quoted_encode(ldap_get_dn(conn->ld, res2)); ldap_debug(conn, 3, "Loaded entry: %s, %s", entry->modifyTimestamp, entry->uid); headlist = g_list_append(headlist, entry); } else { ldap_debug(conn, 0, "Loaded entry %s missing modifyTimestamp. Impossible to sync that. don't use slapadd, use ldapadd!", ldap_get_dn(conn->ld, res2)); } res2 = ldap_next_entry(conn->ld, res2); } while (res2); ldap_debug(conn, 3, "end: load_ldap_entries"); return headlist; } /*Get the complete data for the given head entry*/ /*returns them as LDAPMod*/ void get_ldap_data(ldap_connection *conn, struct data_entry *ldapentry) { char filter[1024]; LDAPMessage *res = NULL, *res2 = NULL, *res3 = NULL; char *attrs[] = {"*", NULL}; int count = 0, n = 0; char **ret = NULL; BerElement *berptr = NULL; char *attribute = NULL; ldap_debug(conn, 2, "Loading full data for: %s", ldapentry->uid); ldapentry->ldapdata = g_malloc0(1024 * sizeof(LDAPMod *)); sprintf(filter, "(&(objectClass=*)(%s))", ldap_explode_dn(quoted_decode(ldapentry->uid), 0)[0]); if (ldap_search_s(conn->ld, conn->searchbase, conn->scope, filter, attrs, 0, &res)) { ldap_debug(conn, 0, "Unable to search with filter %s", filter); return; } res2 = ldap_first_entry(conn->ld, res); if (!res2) { ldap_debug(conn, 0, "No ldap entry returned!: %s", ldapentry->uid); return; } attribute = ldap_first_attribute(conn->ld, res2, &berptr); count = 0; while (attribute) { //Found a new attribute ldapentry->ldapdata[count] = malloc(sizeof(LDAPMod)); ldapentry->ldapdata[count]->mod_values = ldap_get_values(conn->ld, res2, attribute); ldapentry->ldapdata[count]->mod_type = attribute; ldap_debug(conn, 4, "Attribute: %s=%s", attribute, ldapentry->ldapdata[count]->mod_values[0]); attribute = ldap_next_attribute(conn->ld, res2, berptr); count++; } ldap_debug(conn, 3, "end: get_ldap_data"); } /*Add a ldap_data struct to the ldap server*/ int ldap_add_entry(ldap_connection *conn, LDAPMod **data, char *uidret, int duplicate) { int i = 0, x = 0, n = 0, result = 0; char dn[1024]; ldap_debug(conn, 3, "start: ldap_add_entry"); for (i = 0; data[i]; i++) { //Add another attribute data[i]->mod_op = LDAP_MOD_ADD; if (!strcmp(data[i]->mod_type, "cn") && !duplicate) { sprintf(dn, "cn=3D%s,%s", quoted_encode(data[i]->mod_values[0]), quoted_encode(conn->searchbase)); strcpy(uidret, dn); } } if (duplicate) { sprintf(dn, "uid=3Dduplicate%d,%s", rand(), quoted_encode(conn->searchbase)); strcpy(uidret, dn); data[i] = g_malloc0(sizeof(LDAPMod)); data[i]->mod_values = g_malloc0(2 * sizeof(char *)); data[i]->mod_type = "uid"; data[i]->mod_values[0] = ldap_explode_dn(quoted_decode(dn), 1)[0]; data[i]->mod_values[1] = NULL; data[i]->mod_op = LDAP_MOD_ADD; data[i + 1] = NULL; } ldap_debug(conn, 2, "Adding: %s", quoted_decode(dn)); if (result = ldap_add_s(conn->ld, quoted_decode(dn), data)) { if (result == 68 && !duplicate) { //Multisync wants to duplicate item ldap_debug(conn, 2, "Duplicating Entries"); result = ldap_add_entry(conn, data, uidret, 1); return result; } ldap_debug(conn, 1, "Add result: %i: %s", result, ldap_err2string(result)); return -1; } ldap_debug(conn, 3, "end: ldap_add_entry"); return 0; } int ldap_modify_entry(ldap_connection *conn, LDAPMod **data) { int i = 0, x = 0; ldap_debug(conn, 3, "start: ldap modify entry"); for (i = 0; data[i]; i++) { for (x = 0; data[i]->mod_values[x]; x++) { ldap_debug(conn, 3, "%s=%s", data[i]->mod_type, data[i]->mod_values[x]); } } ldap_debug(conn, 3, "end: ldap modify entry"); return 0; } int ldap_delete_entry(ldap_connection *conn, char *cn) { int result = 0; ldap_debug(conn, 2, "Deleting %s", cn); if (result = ldap_delete_s(conn->ld, cn)) { ldap_debug(conn, 1, "Delete result: %s", ldap_err2string(result)); return -1; } ldap_debug(conn, 3, "end: ldap_delete_entry"); return 0; }