diff options
Diffstat (limited to 'source4/libcli/ldap/ldap.c')
-rw-r--r-- | source4/libcli/ldap/ldap.c | 655 |
1 files changed, 3 insertions, 652 deletions
diff --git a/source4/libcli/ldap/ldap.c b/source4/libcli/ldap/ldap.c index 6d2cef8bdb..315241e5b1 100644 --- a/source4/libcli/ldap/ldap.c +++ b/source4/libcli/ldap/ldap.c @@ -24,11 +24,8 @@ */ #include "includes.h" -#include "system/network.h" #include "system/iconv.h" -#include "auth/auth.h" #include "asn_1.h" -#include "dlinklist.h" /**************************************************************************** * @@ -1218,8 +1215,8 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url, char **host, uint16 *port, BOOL *ldaps) { int tmp_port = 0; - fstring protocol; - fstring tmp_host; + char protocol[11]; + char tmp_host[255]; const char *p = url; /* skip leading "URL:" (if any) */ @@ -1245,654 +1242,8 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url, if (tmp_port != 0) *port = tmp_port; - + *host = talloc_strdup(mem_ctx, tmp_host); return (*host != NULL); } - -struct ldap_connection *new_ldap_connection(void) -{ - TALLOC_CTX *mem_ctx = talloc_init("ldap_connection"); - struct ldap_connection *result; - - if (mem_ctx == NULL) - return NULL; - - result = talloc(mem_ctx, sizeof(*result)); - - if (result == NULL) - return NULL; - - result->mem_ctx = mem_ctx; - result->next_msgid = 1; - result->outstanding = NULL; - result->searchid = 0; - result->search_entries = NULL; - result->auth_dn = NULL; - result->simple_pw = NULL; - result->gensec = NULL; - - return result; -} - -BOOL ldap_connect(struct ldap_connection *conn, const char *url) -{ - struct hostent *hp; - struct ipv4_addr ip; - - if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host, - &conn->port, &conn->ldaps)) - return False; - - hp = sys_gethostbyname(conn->host); - - if ((hp == NULL) || (hp->h_addr == NULL)) - return False; - - putip((char *)&ip, (char *)hp->h_addr); - - conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT); - - return (conn->sock >= 0); -} - -BOOL ldap_set_simple_creds(struct ldap_connection *conn, - const char *dn, const char *password) -{ - conn->auth_dn = talloc_strdup(conn->mem_ctx, dn); - conn->simple_pw = talloc_strdup(conn->mem_ctx, password); - - return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL)); -} - -struct ldap_message *new_ldap_message(void) -{ - TALLOC_CTX *mem_ctx = talloc_init("ldap_message"); - struct ldap_message *result; - - if (mem_ctx == NULL) - return NULL; - - result = talloc(mem_ctx, sizeof(*result)); - - if (result == NULL) - return NULL; - - result->mem_ctx = mem_ctx; - return result; -} - -void destroy_ldap_message(struct ldap_message *msg) -{ - if (msg != NULL) - talloc_destroy(msg->mem_ctx); -} - -BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg, - const struct timeval *endtime) -{ - DATA_BLOB request; - BOOL result; - struct ldap_queue_entry *entry; - - msg->messageid = conn->next_msgid++; - - if (!ldap_encode(msg, &request)) - return False; - - result = (write_data_until(conn->sock, request.data, request.length, - endtime) == request.length); - - data_blob_free(&request); - - if (!result) - return result; - - /* abandon and unbind don't expect results */ - - if ((msg->type == LDAP_TAG_AbandonRequest) || - (msg->type == LDAP_TAG_UnbindRequest)) - return True; - - entry = malloc(sizeof(*entry)); - - if (entry == NULL) - return False; - - entry->msgid = msg->messageid; - entry->msg = NULL; - DLIST_ADD(conn->outstanding, entry); - - return True; -} - -BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg, - const struct timeval *endtime) -{ - struct asn1_data data; - BOOL result; - - if (!asn1_read_sequence_until(conn->sock, &data, endtime)) - return False; - - result = ldap_decode(&data, msg); - - asn1_free(&data); - return result; -} - -static struct ldap_message *recv_from_queue(struct ldap_connection *conn, - int msgid) -{ - struct ldap_queue_entry *e; - - for (e = conn->outstanding; e != NULL; e = e->next) { - - if (e->msgid == msgid) { - struct ldap_message *result = e->msg; - DLIST_REMOVE(conn->outstanding, e); - SAFE_FREE(e); - return result; - } - } - - return NULL; -} - -static void add_search_entry(struct ldap_connection *conn, - struct ldap_message *msg) -{ - struct ldap_queue_entry *e = malloc(sizeof *e); - - if (e == NULL) - return; - - e->msg = msg; - DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *); - return; -} - -static void fill_outstanding_request(struct ldap_connection *conn, - struct ldap_message *msg) -{ - struct ldap_queue_entry *e; - - for (e = conn->outstanding; e != NULL; e = e->next) { - if (e->msgid == msg->messageid) { - e->msg = msg; - return; - } - } - - /* This reply has not been expected, destroy the incoming msg */ - destroy_ldap_message(msg); - return; -} - -struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid, - const struct timeval *endtime) -{ - struct ldap_message *result = recv_from_queue(conn, msgid); - - if (result != NULL) - return result; - - while (True) { - struct asn1_data data; - BOOL res; - - result = new_ldap_message(); - - if (!asn1_read_sequence_until(conn->sock, &data, endtime)) - return NULL; - - res = ldap_decode(&data, result); - asn1_free(&data); - - if (!res) - return NULL; - - if (result->messageid == msgid) - return result; - - if (result->type == LDAP_TAG_SearchResultEntry) { - add_search_entry(conn, result); - } else { - fill_outstanding_request(conn, result); - } - } - - return NULL; -} - -struct ldap_message *ldap_transaction(struct ldap_connection *conn, - struct ldap_message *request) -{ - if (!ldap_send_msg(conn, request, NULL)) - return False; - - return ldap_receive(conn, request->messageid, NULL); -} - -int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password) -{ - struct ldap_message *response; - struct ldap_message *msg; - const char *dn, *pw; - int result = LDAP_OTHER; - - if (conn == NULL) - return result; - - if (userdn) { - dn = userdn; - } else { - if (conn->auth_dn) { - dn = conn->auth_dn; - } else { - dn = ""; - } - } - - if (password) { - pw = password; - } else { - if (conn->simple_pw) { - pw = conn->simple_pw; - } else { - pw = ""; - } - } - - msg = new_ldap_simple_bind_msg(dn, pw); - if (!msg) - return result; - - response = ldap_transaction(conn, msg); - if (!response) { - destroy_ldap_message(msg); - return result; - } - - result = response->r.BindResponse.response.resultcode; - - destroy_ldap_message(msg); - destroy_ldap_message(response); - - return result; -} - -int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password) -{ - NTSTATUS status; - TALLOC_CTX *mem_ctx = NULL; - struct ldap_message *response; - struct ldap_message *msg; - DATA_BLOB input = data_blob(NULL, 0); - DATA_BLOB output = data_blob(NULL, 0); - int result = LDAP_OTHER; - - if (conn == NULL) - return result; - - status = gensec_client_start(conn, &conn->gensec); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status))); - return result; - } - - gensec_want_feature(conn->gensec, GENSEC_WANT_SIGN | GENSEC_WANT_SEAL); - - status = gensec_set_domain(conn->gensec, domain); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", - domain, nt_errstr(status))); - goto done; - } - - status = gensec_set_username(conn->gensec, username); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", - username, nt_errstr(status))); - goto done; - } - - status = gensec_set_password(conn->gensec, password); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client password: %s\n", - nt_errstr(status))); - goto done; - } - - status = gensec_set_target_hostname(conn->gensec, conn->host); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", - nt_errstr(status))); - goto done; - } - - status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO"); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n", - nt_errstr(status))); - goto done; - } - - mem_ctx = talloc_init("ldap_bind_sasl"); - if (!mem_ctx) - goto done; - - status = gensec_update(conn->gensec, mem_ctx, - input, - &output); - - while(1) { - if (NT_STATUS_IS_OK(status) && output.length == 0) { - break; - } - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { - break; - } - - msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output); - if (!msg) - goto done; - - response = ldap_transaction(conn, msg); - destroy_ldap_message(msg); - - if (!response) { - goto done; - } - - result = response->r.BindResponse.response.resultcode; - - if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) { - break; - } - - status = gensec_update(conn->gensec, mem_ctx, - response->r.BindResponse.SASL.secblob, - &output); - - destroy_ldap_message(response); - } - -done: - if (mem_ctx) - talloc_destroy(mem_ctx); - - return result; -} - -BOOL ldap_setup_connection(struct ldap_connection *conn, - const char *url, const char *userdn, const char *password) -{ - int result; - - if (!ldap_connect(conn, url)) { - return False; - } - - result = ldap_bind_simple(conn, userdn, password); - if (result == LDAP_SUCCESS) { - return True; - } - - return False; -} - -BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password) -{ - int result; - - if (!ldap_connect(conn, url)) { - return False; - } - - result = ldap_bind_sasl(conn, username, domain, password); - if (result == LDAP_SUCCESS) { - return True; - } - - return False; -} - -static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid, - const struct timeval *endtime) -{ - struct ldap_message *msg = new_ldap_message(); - BOOL result; - - if (msg == NULL) - return False; - - msg->type = LDAP_TAG_AbandonRequest; - msg->r.AbandonRequest.messageid = msgid; - - result = ldap_send_msg(conn, msg, endtime); - destroy_ldap_message(msg); - return result; -} - -struct ldap_message *new_ldap_search_message(const char *base, - enum ldap_scope scope, - char *filter, - int num_attributes, - const char **attributes) -{ - struct ldap_message *res = new_ldap_message(); - - if (res == NULL) - return NULL; - - res->type = LDAP_TAG_SearchRequest; - res->r.SearchRequest.basedn = base; - res->r.SearchRequest.scope = scope; - res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER; - res->r.SearchRequest.timelimit = 0; - res->r.SearchRequest.sizelimit = 0; - res->r.SearchRequest.attributesonly = False; - res->r.SearchRequest.filter = filter; - res->r.SearchRequest.num_attributes = num_attributes; - res->r.SearchRequest.attributes = attributes; - return res; -} - -struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw) -{ - struct ldap_message *res = new_ldap_message(); - - if (res == NULL) - return NULL; - - res->type = LDAP_TAG_BindRequest; - res->r.BindRequest.version = 3; - res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn); - res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE; - res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw); - return res; -} - -struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob) -{ - struct ldap_message *res = new_ldap_message(); - - if (res == NULL) - return NULL; - - res->type = LDAP_TAG_BindRequest; - res->r.BindRequest.version = 3; - res->r.BindRequest.dn = ""; - res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL; - res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism); - res->r.BindRequest.creds.SASL.secblob = *secblob; - return res; -} - -BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg, - const struct timeval *endtime) -{ - if ((conn->searchid != 0) && - (!ldap_abandon_message(conn, conn->searchid, endtime))) - return False; - - conn->searchid = conn->next_msgid; - return ldap_send_msg(conn, msg, endtime); -} - -struct ldap_message *ldap_getsearchent(struct ldap_connection *conn, - const struct timeval *endtime) -{ - struct ldap_message *result; - - if (conn->search_entries != NULL) { - struct ldap_queue_entry *e = conn->search_entries; - - result = e->msg; - DLIST_REMOVE(conn->search_entries, e); - SAFE_FREE(e); - return result; - } - - result = ldap_receive(conn, conn->searchid, endtime); - if (!result) { - return NULL; - } - - if (result->type == LDAP_TAG_SearchResultEntry) - return result; - - if (result->type == LDAP_TAG_SearchResultDone) { - /* TODO: Handle Paged Results */ - destroy_ldap_message(result); - return NULL; - } - - /* TODO: Handle Search References here */ - return NULL; -} - -void ldap_endsearchent(struct ldap_connection *conn, - const struct timeval *endtime) -{ - struct ldap_queue_entry *e; - - e = conn->search_entries; - - while (e != NULL) { - struct ldap_queue_entry *next = e->next; - DLIST_REMOVE(conn->search_entries, e); - SAFE_FREE(e); - e = next; - } -} - -struct ldap_message *ldap_searchone(struct ldap_connection *conn, - struct ldap_message *msg, - const struct timeval *endtime) -{ - struct ldap_message *res1, *res2 = NULL; - if (!ldap_setsearchent(conn, msg, endtime)) - return NULL; - - res1 = ldap_getsearchent(conn, endtime); - - if (res1 != NULL) - res2 = ldap_getsearchent(conn, endtime); - - ldap_endsearchent(conn, endtime); - - if (res1 == NULL) - return NULL; - - if (res2 != NULL) { - /* More than one entry */ - destroy_ldap_message(res1); - destroy_ldap_message(res2); - return NULL; - } - - return res1; -} - -BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr, - DATA_BLOB *value) -{ - int i; - struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry; - - if (msg->type != LDAP_TAG_SearchResultEntry) - return False; - - for (i=0; i<r->num_attributes; i++) { - if (strequal(attr, r->attributes[i].name)) { - if (r->attributes[i].num_values != 1) - return False; - - *value = r->attributes[i].values[0]; - return True; - } - } - return False; -} - -BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr, - TALLOC_CTX *mem_ctx, char **value) -{ - DATA_BLOB blob; - - if (!ldap_find_single_value(msg, attr, &blob)) - return False; - - *value = talloc(mem_ctx, blob.length+1); - - if (*value == NULL) - return False; - - memcpy(*value, blob.data, blob.length); - (*value)[blob.length] = '\0'; - return True; -} - -BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr, - int *value) -{ - DATA_BLOB blob; - char *val; - int errno_save; - BOOL res; - - if (!ldap_find_single_value(msg, attr, &blob)) - return False; - - val = malloc(blob.length+1); - if (val == NULL) - return False; - - memcpy(val, blob.data, blob.length); - val[blob.length] = '\0'; - - errno_save = errno; - errno = 0; - - *value = strtol(val, NULL, 10); - - res = (errno == 0); - - free(val); - errno = errno_save; - - return res; -} - -int ldap_error(struct ldap_connection *conn) -{ - return 0; -} - -NTSTATUS ldap2nterror(int ldaperror) -{ - return NT_STATUS_OK; -} |