static krb5_error_code LDAP__connect(krb5_context context, HDB * db) { int rc, version = LDAP_VERSION3; /* * Empty credentials to do a SASL bind with LDAP. Note that empty * different from NULL credentials. If you provide NULL * credentials instead of empty credentials you will get a SASL * bind in progress message. */ struct berval bv = { 0, "" }; if (HDB2LDAP(db)) { /* connection has been opened. ping server. */ struct sockaddr_un addr; socklen_t len = sizeof(addr); int sd; if (ldap_get_option(HDB2LDAP(db), LDAP_OPT_DESC, &sd) == 0 && getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { /* the other end has died. reopen. */ LDAP_close(context, db); } } if (HDB2LDAP(db) != NULL) /* server is UP */ return 0; rc = ldap_initialize(&((struct hdbldapdb *)db->hdb_db)->h_lp, "ldapi:///"); if (rc != LDAP_SUCCESS) { krb5_set_error_string(context, "ldap_initialize: %s", ldap_err2string(rc)); return HDB_ERR_NOENTRY; } rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_PROTOCOL_VERSION, (const void *)&version); if (rc != LDAP_SUCCESS) { krb5_set_error_string(context, "ldap_set_option: %s", ldap_err2string(rc)); LDAP_close(context, db); return HDB_ERR_BADVERSION; } rc = ldap_sasl_bind_s(HDB2LDAP(db), NULL, "EXTERNAL", &bv, NULL, NULL, NULL); if (rc != LDAP_SUCCESS) { krb5_set_error_string(context, "ldap_sasl_bind_s: %s", ldap_err2string(rc)); LDAP_close(context, db); return HDB_ERR_BADVERSION; } return 0; }
static int check_ldap(krb5_context context, HDB *db, int ret) { switch (ret) { case LDAP_SUCCESS: return 0; case LDAP_SERVER_DOWN: LDAP_close(context, db); return 1; default: return 1; } }
static krb5_error_code LDAP_destroy(krb5_context context, HDB * db) { krb5_error_code ret; LDAP_close(context, db); ret = hdb_clear_master_key(context, db); if (HDB2BASE(db)) free(HDB2BASE(db)); if (HDB2CREATE(db)) free(HDB2CREATE(db)); if (db->hdb_name) free(db->hdb_name); free(db->hdb_db); free(db); return ret; }
static krb5_error_code LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry) { int msgid, rc, parserc; krb5_error_code ret; LDAPMessage *e; msgid = HDB2MSGID(db); if (msgid < 0) return HDB_ERR_NOENTRY; do { rc = ldap_result(HDB2LDAP(db), msgid, LDAP_MSG_ONE, NULL, &e); switch (rc) { case LDAP_RES_SEARCH_REFERENCE: ldap_msgfree(e); ret = 0; break; case LDAP_RES_SEARCH_ENTRY: /* We have an entry. Parse it. */ ret = LDAP_message2entry(context, db, e, entry); ldap_msgfree(e); break; case LDAP_RES_SEARCH_RESULT: /* We're probably at the end of the results. If not, abandon. */ parserc = ldap_parse_result(HDB2LDAP(db), e, NULL, NULL, NULL, NULL, NULL, 1); if (parserc != LDAP_SUCCESS && parserc != LDAP_MORE_RESULTS_TO_RETURN) { krb5_set_error_string(context, "ldap_parse_result: %s", ldap_err2string(parserc)); ldap_abandon(HDB2LDAP(db), msgid); } ret = HDB_ERR_NOENTRY; HDBSETMSGID(db, -1); break; case LDAP_SERVER_DOWN: ldap_msgfree(e); LDAP_close(context, db); HDBSETMSGID(db, -1); ret = ENETDOWN; break; default: /* Some unspecified error (timeout?). Abandon. */ ldap_msgfree(e); ldap_abandon(HDB2LDAP(db), msgid); ret = HDB_ERR_NOENTRY; HDBSETMSGID(db, -1); break; } } while (rc == LDAP_RES_SEARCH_REFERENCE); if (ret == 0) { if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { ret = hdb_unseal_keys(context, db, entry); if (ret) hdb_free_entry(context,entry); } } return ret; }