From b5ae9019b0a0ae9b3b6593a0571e7ba474aa5ed2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 17 May 2007 05:46:45 +0000 Subject: r22967: Move to the TCP packet interface for the krb5_send_to_kdc plugin. This replaces a lump of hand-crafted code with the generic packet system used in the rest of Samba4. (I started this while chasing down the epoll bug, which turned out to be seperate) (This used to be commit 2a7dec4e5dc453f509493f80fc1270416f30a36e) --- source4/auth/kerberos/krb5_init_context.c | 203 ++++++++++++++---------------- 1 file changed, 95 insertions(+), 108 deletions(-) (limited to 'source4/auth') diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c index 9760db4051..92de176e84 100644 --- a/source4/auth/kerberos/krb5_init_context.c +++ b/source4/auth/kerberos/krb5_init_context.c @@ -26,6 +26,7 @@ #include "heimdal/lib/krb5/krb5_locl.h" #include "auth/kerberos/kerberos.h" #include "lib/socket/socket.h" +#include "lib/stream/packet.h" #include "system/network.h" #include "lib/events/events.h" #include "roken.h" @@ -39,9 +40,10 @@ struct smb_krb5_socket { /* the fd event */ struct fd_event *fde; - BOOL timeout; NTSTATUS status; - DATA_BLOB request, reply, partial; + DATA_BLOB request, reply; + + struct packet_context *packet; size_t partial_read; @@ -82,98 +84,48 @@ static void smb_krb5_socket_recv(struct smb_krb5_socket *smb_krb5) DATA_BLOB blob; size_t nread, dsize; - switch (smb_krb5->hi->proto) { - case KRB5_KRBHST_UDP: - smb_krb5->status = socket_pending(smb_krb5->sock, &dsize); - if (!NT_STATUS_IS_OK(smb_krb5->status)) { - talloc_free(tmp_ctx); - return; - } - - blob = data_blob_talloc(tmp_ctx, NULL, dsize); - if (blob.data == NULL && dsize != 0) { - smb_krb5->status = NT_STATUS_NO_MEMORY; - talloc_free(tmp_ctx); - return; - } - - smb_krb5->status = socket_recv(smb_krb5->sock, blob.data, blob.length, &nread); - if (!NT_STATUS_IS_OK(smb_krb5->status)) { - talloc_free(tmp_ctx); - return; - } - blob.length = nread; - - if (nread == 0) { - smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; - talloc_free(tmp_ctx); - return; - } - - DEBUG(2,("Received smb_krb5 packet of length %d\n", - (int)blob.length)); - - talloc_steal(smb_krb5, blob.data); - smb_krb5->reply = blob; + smb_krb5->status = socket_pending(smb_krb5->sock, &dsize); + if (!NT_STATUS_IS_OK(smb_krb5->status)) { + talloc_free(tmp_ctx); + return; + } + + blob = data_blob_talloc(tmp_ctx, NULL, dsize); + if (blob.data == NULL && dsize != 0) { + smb_krb5->status = NT_STATUS_NO_MEMORY; + talloc_free(tmp_ctx); + return; + } + + smb_krb5->status = socket_recv(smb_krb5->sock, blob.data, blob.length, &nread); + if (!NT_STATUS_IS_OK(smb_krb5->status)) { + talloc_free(tmp_ctx); + return; + } + blob.length = nread; + + if (nread == 0) { + smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; talloc_free(tmp_ctx); - break; - case KRB5_KRBHST_TCP: - if (smb_krb5->partial.length == 0) { - smb_krb5->partial = data_blob_talloc(smb_krb5, NULL, 4); - if (!smb_krb5->partial.data) { - smb_krb5->status = NT_STATUS_NO_MEMORY; - return; - } - - smb_krb5->partial_read = 0; - } - - /* read in the packet length */ - if (smb_krb5->partial_read < 4) { - uint32_t packet_length; - - smb_krb5->status = socket_recv(smb_krb5->sock, - smb_krb5->partial.data + smb_krb5->partial_read, - 4 - smb_krb5->partial_read, - &nread); - /* todo: this should be converted to the packet_*() routines */ - if (!NT_STATUS_IS_OK(smb_krb5->status)) { - return; - } - - smb_krb5->partial_read += nread; - if (smb_krb5->partial_read != 4) { - return; - } - - packet_length = RIVAL(smb_krb5->partial.data, 0); - - smb_krb5->partial.data = talloc_realloc(smb_krb5, smb_krb5->partial.data, - uint8_t, packet_length + 4); - if (!smb_krb5->partial.data) { - smb_krb5->status = NT_STATUS_NO_MEMORY; - return; - } - - smb_krb5->partial.length = packet_length + 4; - } - - /* read in the body */ - smb_krb5->status = socket_recv(smb_krb5->sock, - smb_krb5->partial.data + smb_krb5->partial_read, - smb_krb5->partial.length - smb_krb5->partial_read, - &nread); - if (!NT_STATUS_IS_OK(smb_krb5->status)) return; - - smb_krb5->partial_read += nread; - - if (smb_krb5->partial_read != smb_krb5->partial.length) return; - - smb_krb5->reply = data_blob_talloc(smb_krb5, smb_krb5->partial.data + 4, smb_krb5->partial.length - 4); - break; - case KRB5_KRBHST_HTTP: return; } + + DEBUG(2,("Received smb_krb5 packet of length %d\n", + (int)blob.length)); + + talloc_steal(smb_krb5, blob.data); + smb_krb5->reply = blob; + talloc_free(tmp_ctx); +} + +static NTSTATUS smb_krb5_full_packet(void *private, DATA_BLOB data) +{ + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + talloc_steal(smb_krb5, data.data); + smb_krb5->reply = data; + smb_krb5->reply.length -= 4; + smb_krb5->reply.data += 4; + return NT_STATUS_OK; } /* @@ -185,7 +137,13 @@ static void smb_krb5_request_timeout(struct event_context *event_ctx, { struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); DEBUG(5,("Timed out smb_krb5 packet\n")); - smb_krb5->timeout = True; + smb_krb5->status = NT_STATUS_IO_TIMEOUT; +} + +static void smb_krb5_error_handler(void *private, NTSTATUS status) +{ + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + smb_krb5->status = status; } /* @@ -216,11 +174,26 @@ static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *f uint16_t flags, void *private) { struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); - if (flags & EVENT_FD_WRITE) { - smb_krb5_socket_send(smb_krb5); - } - if (flags & EVENT_FD_READ) { - smb_krb5_socket_recv(smb_krb5); + switch (smb_krb5->hi->proto) { + case KRB5_KRBHST_UDP: + if (flags & EVENT_FD_WRITE) { + smb_krb5_socket_send(smb_krb5); + } + if (flags & EVENT_FD_READ) { + smb_krb5_socket_recv(smb_krb5); + } + break; + case KRB5_KRBHST_TCP: + if (flags & EVENT_FD_READ) { + packet_recv(smb_krb5->packet); + } + if (flags & EVENT_FD_WRITE) { + packet_queue_run(smb_krb5->packet); + } + break; + case KRB5_KRBHST_HTTP: + /* can't happen */ + break; } } @@ -304,7 +277,7 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, } talloc_free(remote_addr); - smb_krb5->fde = event_add_fd(ev, smb_krb5, + smb_krb5->fde = event_add_fd(ev, smb_krb5->sock, socket_get_fd(smb_krb5->sock), EVENT_FD_AUTOCLOSE, smb_krb5_socket_handler, smb_krb5); @@ -315,39 +288,53 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, timeval_current_ofs(context->kdc_timeout, 0), smb_krb5_request_timeout, smb_krb5); - EVENT_FD_WRITEABLE(smb_krb5->fde); + smb_krb5->status = NT_STATUS_OK; + smb_krb5->reply = data_blob(NULL, 0); + switch (hi->proto) { case KRB5_KRBHST_UDP: + EVENT_FD_WRITEABLE(smb_krb5->fde); smb_krb5->request = send_blob; break; case KRB5_KRBHST_TCP: + + smb_krb5->packet = packet_init(smb_krb5); + if (smb_krb5->packet == NULL) { + talloc_free(smb_krb5); + return ENOMEM; + } + packet_set_private(smb_krb5->packet, smb_krb5); + packet_set_socket(smb_krb5->packet, smb_krb5->sock); + packet_set_callback(smb_krb5->packet, smb_krb5_full_packet); + packet_set_full_request(smb_krb5->packet, packet_full_request_u32); + packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler); + packet_set_event_context(smb_krb5->packet, ev); + packet_set_fde(smb_krb5->packet, smb_krb5->fde); + smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4); RSIVAL(smb_krb5->request.data, 0, send_blob.length); memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length); + packet_send(smb_krb5->packet, smb_krb5->request); + EVENT_FD_READABLE(smb_krb5->fde); break; case KRB5_KRBHST_HTTP: talloc_free(smb_krb5); return EINVAL; } - smb_krb5->timeout = False; - smb_krb5->status = NT_STATUS_OK; - smb_krb5->reply = data_blob(NULL, 0); - smb_krb5->partial = data_blob(NULL, 0); - - while (!smb_krb5->timeout && (NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { + while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { if (event_loop_once(ev) != 0) { talloc_free(smb_krb5); return EINVAL; } } - if (!NT_STATUS_IS_OK(smb_krb5->status)) { - DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status))); + if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) { talloc_free(smb_krb5); continue; } - if (smb_krb5->timeout) { + if (!NT_STATUS_IS_OK(smb_krb5->status)) { + DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status))); talloc_free(smb_krb5); continue; } -- cgit