static void pkix_tcp_kill_input(SshFSMThread thread) { SshPkiThreadData tdata = ssh_fsm_get_tdata(thread); SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread); SSH_DEBUG(SSH_D_HIGHOK, ("Deleting wrapper and timeouts for thread %p conn=%p", thread, tdata->http)); ssh_cancel_timeouts(pkix_timeout_handler, (void *)thread); tdata->timeout_set = FALSE; if (tdata->wrapper) { ssh_packet_wrapper_destroy(tdata->wrapper); tdata->wrapper = NULL; } if (tdata->http) { ssh_http_client_uninit(tdata->http); tdata->http = NULL; } if (gdata->input_thread) { ssh_fsm_kill_thread(gdata->input_thread); gdata->input_thread = NULL; } }
static Boolean pkix_client_srv_close(SshPkiThreadData tdata) { if (tdata->wrapper) { ssh_packet_wrapper_destroy(tdata->wrapper); tdata->wrapper = NULL; } return TRUE; }
static void pkix_tcp_receive_eof(void *context) { SshFSMThread thread = (SshFSMThread)context; SshPkiThreadData tdata = ssh_fsm_get_tdata(thread); ssh_packet_wrapper_destroy(tdata->wrapper); tdata->wrapper = NULL; SSH_DEBUG(SSH_D_HIGHOK, ("Received EOF from CA for thread %p", thread)); }
/* Callback, which notifies that packetstream has received EOF from the other side. */ void auth_hostbased_received_eof(void *context) { SshClientHostbasedAuth state = (SshClientHostbasedAuth) context; SSH_TRACE(0, ("received EOF from ssh-signer2.")); ssh_packet_wrapper_send_eof(state->wrapper); ssh_packet_wrapper_destroy(state->wrapper); state->wrapper = NULL; *(state->state_placeholder) = NULL; /* Send failure message up, and return. */ (*state->completion)(SSH_AUTH_CLIENT_FAIL, state->user, NULL, state->completion_context); }
void signer_free_context(SshSigner signer) { static Boolean destroyed = FALSE; if (destroyed) return; destroyed = TRUE; SSH_DEBUG(3, ("Destroying SshSigner-struct...")); ssh_packet_wrapper_destroy(signer->wrapper); ssh_xfree(signer->packet_payload); ssh_random_free(signer->random_state); ssh_config_free(signer->config); ssh_user_free(signer->effective_user_data, FALSE); ssh_xfree(signer); SSH_DEBUG(3, ("done.")); }
Boolean ssh_packet_wrapper_input(SshPacketWrapper down) { size_t data_to_read, data_read; int ret; unsigned char *ptr; SshPacketType type; Boolean return_value = FALSE; for (;;) { /* If we cannot receive, return immediately. */ if (!down->can_receive || down->incoming_eof || down->destroy_pending || down->shortcircuit_up_stream != NULL) return return_value; /* Get length of data read so far. */ data_read = ssh_buffer_len(&down->incoming); /* Add enough space to buffer for reading either header or entire packet. This also sets `ptr' to point to the place where data should be read, and `data_to_read' to the number of bytes that should be there after reading (should read data_to_read - data_read bytes). */ if (data_read < 4) { /* Packet header not yet in buffer. Read only header. */ data_to_read = 4; ssh_buffer_append_space(&down->incoming, &ptr, 4 - data_read); } else { /* Packet header already in buffer. */ ptr = ssh_buffer_ptr(&down->incoming); data_to_read = 4 + SSH_GET_32BIT(ptr); if (data_to_read > 100000000L) ssh_fatal("ssh_packet_wrapper_input: " "invalid packet received: len %ld", (long)data_to_read); SSH_ASSERT(data_to_read > data_read); ssh_buffer_append_space(&down->incoming, &ptr, data_to_read - data_read); } /* Keep reading until entire packet read, or no more data available. */ while (data_read < data_to_read) { /* Try to read the remaining bytes. */ ptr = (unsigned char *)ssh_buffer_ptr(&down->incoming) + data_read; ret = ssh_stream_read(down->stream, ptr, data_to_read - data_read); if (ret < 0) { /* No more data available at this time. Remove allocated but unread space from end of buffer. */ ssh_buffer_consume_end(&down->incoming, data_to_read - data_read); return return_value; } if (ret == 0) { /* EOF received. */ ssh_buffer_consume_end(&down->incoming, data_to_read - data_read); down->incoming_eof = TRUE; /* Pass the EOF to the application callback. */ down->cannot_destroy = TRUE; if (down->received_eof) (*down->received_eof)(down->context); down->cannot_destroy = FALSE; if (down->destroy_requested) { ssh_packet_wrapper_destroy(down); return FALSE; } return TRUE; } if (data_read < 4 && data_read + ret >= 4) { /* Header has now been fully received. Prepare to receive rest of packet. */ data_read += ret; ptr = ssh_buffer_ptr(&down->incoming); data_to_read = 4 + SSH_GET_32BIT(ptr); if (data_to_read > 100000000L) ssh_fatal("ssh_packet_wrapper_input: " "invalid packet received: len %ld", (long)data_to_read); if (data_to_read > data_read) ssh_buffer_append_space(&down->incoming, &ptr, data_to_read - data_read); } else data_read += ret; } /* An entire packet has been received. */ SSH_ASSERT(ssh_buffer_len(&down->incoming) == data_to_read); /* Get packet type. */ ptr = ssh_buffer_ptr(&down->incoming); type = (SshPacketType)ptr[4]; /* Call the application callback if set. */ down->cannot_destroy = TRUE; if (down->received_packet) (*down->received_packet)(type, ptr + 5, data_to_read - 5, down->context); down->cannot_destroy = FALSE; if (down->destroy_requested) { ssh_packet_wrapper_destroy(down); return FALSE; } ssh_buffer_clear(&down->incoming); return_value = TRUE; } /*NOTREACHED*/ }
Boolean ssh_packet_wrapper_output(SshPacketWrapper down) { int len; Boolean return_value = FALSE; /* Loop while we have data to output. When all data has been sent, we check whether we need to send EOF. */ while (ssh_buffer_len(&down->outgoing) > 0) { /* Write as much data as possible. */ len = ssh_stream_write(down->stream, ssh_buffer_ptr(&down->outgoing), ssh_buffer_len(&down->outgoing)); if (len < 0) return return_value; /* Cannot write more now. */ if (len == 0) { /* EOF on output; will not be able to write any more. */ down->outgoing_eof = TRUE; ssh_buffer_clear(&down->outgoing); return TRUE; } /* Consume written data. */ ssh_buffer_consume(&down->outgoing, len); /* We've done something, so return TRUE. */ return_value = TRUE; } /* All output has drained. There is no more buffered data. */ if (down->send_blocked) { down->cannot_destroy = TRUE; if (down->can_send) (*down->can_send)(down->context); down->cannot_destroy = FALSE; if (down->destroy_requested) { ssh_packet_wrapper_destroy(down); return FALSE; } down->send_blocked = FALSE; } /* If we should send EOF after output has drained, do it now. */ if (down->outgoing_eof) ssh_stream_output_eof(down->stream); /* If we get here and the stream is shortcircuited, that means we had output data to drain before shortcircuiting. */ if (down->shortcircuit_up_stream && !down->shortcircuited) { down->shortcircuited = TRUE; ssh_packet_impl_shortcircuit_now(down->shortcircuit_up_stream, down->stream); } /* If there's a destroy pending (that is, waiting for buffers to drain), do the destroy now. */ if (down->destroy_pending) { /* Destroy the context now. This also closes the stream. */ ssh_packet_wrapper_destroy_now(down); /* Return FALSE to ensure that the loop in ssh_packet_wrapper_callback exits without looking at the context again. */ return FALSE; } return return_value; }
/* Callback, which is used to notify that our packetstream has a packet for us.*/ void auth_hostbased_received_packet(SshPacketType type, const unsigned char *packet, size_t packet_len, void *context) { SshBuffer *b; SshClientHostbasedAuth state = (SshClientHostbasedAuth) context; switch(type) { case SSH_AUTH_HOSTBASED_PACKET: SSH_TRACE(2, ("ssh-signer returned SSH_AUTH_HOSTBASED_PACKET "\ "(this is an error)")); /* signer shouldn't send this to us, so this is an error.*/ /* XXX */ break; case SSH_AUTH_HOSTBASED_SIGNATURE: SSH_TRACE(2, ("ssh-signer returned SSH_AUTH_HOSTBASED_SIGNATURE")); /* We've got a signature. */ b = ssh_buffer_allocate(); /* Destroy wrapper (and signer) */ ssh_packet_wrapper_send_eof(state->wrapper); ssh_packet_wrapper_destroy(state->wrapper); state->wrapper = NULL; ssh_encode_buffer(b, /* public key algorithm (string) */ SSH_FORMAT_UINT32_STR, state->pubkey_algorithm, strlen(state->pubkey_algorithm), /* public key (string) */ SSH_FORMAT_UINT32_STR, state->pubkeyblob, state->pubkeyblob_len, /* client host name (FQDN, string) */ SSH_FORMAT_UINT32_STR, state->local_host_name, strlen(state->local_host_name), /* user name at client side */ SSH_FORMAT_UINT32_STR, state->local_user_name, strlen(state->local_user_name), /* signature */ SSH_FORMAT_DATA, packet, packet_len, SSH_FORMAT_END); /* Detach the state structure from the state_placeholder. */ *state->state_placeholder = NULL; /* Call the authentication method completion procedure. */ (*state->completion)(SSH_AUTH_CLIENT_SEND, state->user, b, state->completion_context); /* Free the buffer */ ssh_buffer_free(b); /* XXX Free the state. */ break; case SSH_AUTH_HOSTBASED_ERROR: /* Destroy wrapper (and signer) */ ssh_packet_wrapper_send_eof(state->wrapper); ssh_packet_wrapper_destroy(state->wrapper); state->wrapper = NULL; SSH_TRACE(0, ("ssh-signer returned SSH_AUTH_HOSTBASED_ERROR")); /* Send failure message to server, and return. */ (*state->completion)(SSH_AUTH_CLIENT_FAIL, state->user, NULL, state->completion_context); break; } }