Boolean handler_output_outgoing(Handler c) { int len; #ifdef DEBUG ssh_debug("handler_output_outgoing"); #endif #ifdef DUMP_PACKETS buffer_dump(&c->outgoing); #endif while (ssh_buffer_len(&c->outgoing) > 0) { len = ssh_buffer_len(&c->outgoing); len = ssh_stream_write(c->stream, ssh_buffer_ptr(&c->outgoing), len); if (len == 0) ssh_fatal("%s: handler_output: error writing to stream", c->side); if (len < 0) return FALSE; ssh_buffer_consume(&c->outgoing, len); } if (c->outgoing_eof) ssh_stream_output_eof(c->stream); return TRUE; }
void server1_read(SshStream stream) { int ret; unsigned char buf[1024]; for (;;) { ret = ssh_stream_read(stream, buf, sizeof(buf)); if (ret < 0) return; if (ret == 0) { if (read_count != send_count) ssh_fatal("server1_read eof received, read_count %ld send_count %ld", read_count, send_count); break; } if (memcmp(buf, ssh_buffer_ptr(&expect_buffer), ret) != 0) ssh_fatal("server1_read data does not match"); ssh_buffer_consume(&expect_buffer, ret); read_count += ret; } /* All data has been received. */ ssh_stream_destroy(stream); exited1 = 1; }
void encode_case(const char *name, const char *expect, size_t expect_len, ...) { size_t len, i, bytes; unsigned char ch, *cp; va_list va; ssh_buffer_clear(buffer); len = rand() % 100; ch = rand(); for (i = 0; i < len; i++) ssh_buffer_append(buffer, &ch, 1); va_start(va, expect_len); bytes = ssh_encode_buffer_va(buffer, va); if (bytes != expect_len || ssh_buffer_len(buffer) != len + expect_len) ssh_fatal("test_encode: %s: unexpected length %d vs. %d", name, bytes, len + expect_len); cp = ssh_buffer_ptr(buffer); if (memcmp(expect, cp + len, expect_len) != 0) ssh_fatal("test_encode: %s: mismatch", name); for (i = 0; i < len; i++) if (cp[i] != ch) ssh_fatal("test_encode: %s: beginning corrupted", name); ssh_buffer_consume(buffer, len); }
static int ssh_appgw_http_unmarshal_string(SshBuffer buf, unsigned char **ptr) { int len; *ptr = NULL; if (ssh_appgw_http_unmarshal_int(buf, &len) == 0) return 0; if (len == 0) return 1; if (ssh_buffer_len(buf) < len) return 0; *ptr = ssh_malloc(len+1); if (ptr == NULL) return 0; memcpy(*ptr,ssh_buffer_ptr(buf),len); (*ptr)[len] = '\0'; ssh_buffer_consume(buf,len); return 1; }
static int ssh_appgw_http_unmarshal_int(SshBuffer buf, int *result) { if (ssh_buffer_len(buf) < 4) { *result = 0; return 0; } *result = (int)(SSH_GET_32BIT(ssh_buffer_ptr(buf))); ssh_buffer_consume(buf,4); return 1; }
/* * Parse methods array. This doesn't do anything with SOCKS4. */ SocksError ssh_socks_server_parse_methods(SshBuffer buffer, SocksInfo *socksinfo) { size_t ret = 0L, len; unsigned int version, num_methods; unsigned char *data; data = ssh_buffer_ptr(buffer); len = ssh_buffer_len(buffer); if (len < 1) return SSH_SOCKS_TRY_AGAIN; version = *data; if (version == 4) goto return_success; if (len < 2) return SSH_SOCKS_TRY_AGAIN; ret = ssh_decode_array(data, len, SSH_DECODE_CHAR(&version), SSH_DECODE_CHAR(&num_methods), SSH_FORMAT_END); if (ret == 0) { SSH_DEBUG(2, ("Decoding methods buffer failed.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } if (len < num_methods + 2) return SSH_SOCKS_TRY_AGAIN; ssh_buffer_consume(buffer, num_methods + 2); return_success: if (socksinfo) { *socksinfo = ssh_calloc(1, sizeof(**socksinfo)); if (*socksinfo == NULL) { SSH_DEBUG(2, ("Couldn't allocate SshSocksInfo.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } (*socksinfo)->socks_version_number = version; } return SSH_SOCKS_SUCCESS; }
void connect1_write(SshStream stream) { int len; while (ssh_buffer_len(&send_buffer) > 0) { len = ssh_buffer_len(&send_buffer); len = ssh_stream_write(stream, ssh_buffer_ptr(&send_buffer), len); if (len < 0) return; if (len == 0) ssh_fatal("connect1_write failed"); ssh_buffer_consume(&send_buffer, len); } ssh_stream_output_eof(stream); ssh_stream_destroy(stream); }
SshBuffer *handler_input_expect_cross(Handler c, unsigned int expect_type) { SshBuffer *packet; const unsigned char *cp; unsigned int packet_type; packet = handler_input_cross(c); if (!packet) return NULL; cp = ssh_buffer_ptr(packet); packet_type = (unsigned int) cp[4]; if (packet_type != expect_type) ssh_fatal("%s: handler_input_expect_cross: got %d expected %d", c->side, packet_type, expect_type); /* Remove cross-layer header and return the payload. */ ssh_buffer_consume(packet, 5); return packet; }
static int ssh_appgw_http_unmarshal_data(SshBuffer buf, unsigned char **ptr, int *len) { *ptr = NULL; *len = 0; if (ssh_appgw_http_unmarshal_int(buf, len) == 0) return 0; if (*len == 0) return 1; if (ssh_buffer_len(buf) < *len) return 0; *ptr = ssh_malloc(*len); if (ptr == NULL) return 0; memcpy(*ptr,ssh_buffer_ptr(buf),*len); ssh_buffer_consume(buf,*len); return 1; }
int ssh_packet_impl_read(void *context, unsigned char *buf, size_t size) { SshPacketImpl up = (SshPacketImpl)context; size_t len; /* Compute the number of bytes we can transmit. */ len = ssh_buffer_len(&up->outgoing); if (len > size) len = size; /* Return immediately if no data available. */ if (len == 0) { /* If shortcircuiting, pass it to the shortcircuit stream. */ if (up->shortcircuit_stream) return ssh_stream_read(up->shortcircuit_stream, buf, size); /* Return EOF or "no more data available yet". */ if (up->outgoing_eof) return 0; else { up->up_read_blocked = TRUE; return -1; } } /* Move data to the caller's buffer. */ memcpy(buf, ssh_buffer_ptr(&up->outgoing), len); ssh_buffer_consume(&up->outgoing, len); /* Wake up the sender if appropriate. */ if (ssh_buffer_len(&up->outgoing) == 0) ssh_packet_impl_restart_send(up); return len; }
/* * Parse socks reply packet. Consume the reply packet data from buffer. * If the request was not granted (returns SSH_SOCKS_FAILED_*) the socket can * be immediately closed down (there will not be any additional data from the * socks server. * If the request is granted allocate socksinfo structure and store information * from request packet to there (sets socks_version_number, command_code, ip, * and port fields). * Use ssh_socks_free to free socksinfo data. */ SocksError ssh_socks_client_parse_reply(SshBuffer buffer, SocksInfo *socksinfo) { unsigned char *data, *ip_ptr, *port_ptr; unsigned char *username =NULL; unsigned long len, port, version; size_t bytes = 0; unsigned int cmd, atyp, ip_addr_len; if (socksinfo) *socksinfo = NULL; len = ssh_buffer_len(buffer); data = ssh_buffer_ptr(buffer); /* Check if enough data for version. */ if (len < 1) return SSH_SOCKS_TRY_AGAIN; version = data[0]; /* SOCKS4 replys have version number '0'. Go figure. */ if (version == 0) version = 4; bytes++; if (version != 4 && version != 5) { SSH_DEBUG(2, ("Server gave us version %ld.", version)); return SSH_SOCKS_ERROR_UNSUPPORTED_SOCKS_VERSION; } if (version == 4) { /* A SOCKS4 command reply is exactly 8 bytes long. */ if (len < 8) return SSH_SOCKS_TRY_AGAIN; SSH_DEBUG(2, ("Doing SOCKS4.")); bytes = 8; if (data[1] != SSH_SOCKS4_REPLY_GRANTED) { SocksError error = SSH_SOCKS_ERROR_PROTOCOL_ERROR; switch (data[1]) { case SSH_SOCKS4_REPLY_FAILED_REQUEST: error = SSH_SOCKS_FAILED_REQUEST; break; case SSH_SOCKS4_REPLY_FAILED_IDENTD: error = SSH_SOCKS_FAILED_IDENTD; break; case SSH_SOCKS4_REPLY_FAILED_USERNAME: error = SSH_SOCKS_FAILED_USERNAME; break; default: error = SSH_SOCKS_ERROR_PROTOCOL_ERROR; break; } ssh_buffer_consume(buffer, bytes); return error; } cmd = data[1]; port_ptr = &data[2]; ip_ptr = &data[4]; ip_addr_len = 4; atyp = SSH_SOCKS5_ATYP_IPV4; username = (unsigned char *)&data[8]; } else { size_t ret = 0L; /* SOCKS5. */ if (len - bytes < 3) return SSH_SOCKS_TRY_AGAIN; ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_CHAR(&cmd), SSH_DECODE_CHAR(NULL), /* RSV */ SSH_DECODE_CHAR(&atyp), SSH_FORMAT_END); if (ret == 0) { SSH_DEBUG(2, ("Decoding reply packet failed.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } bytes += ret; if (atyp == SSH_SOCKS5_ATYP_IPV4) { ip_addr_len = 4; } else if (atyp == SSH_SOCKS5_ATYP_IPV6) { ip_addr_len = 16; } else if (atyp == SSH_SOCKS5_ATYP_FQDN) { if (len - bytes < 1) return SSH_SOCKS_TRY_AGAIN; ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_CHAR(&ip_addr_len), SSH_FORMAT_END); if (ret == 0) { SSH_DEBUG(2, ("Decoding FQDN hostname len failed.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } bytes += ret; } else { SSH_DEBUG(2, ("Invalid address type %d.", atyp)); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } /* ip addr len + port (2 bytes) */ if (len - bytes < ip_addr_len + 2) return SSH_SOCKS_TRY_AGAIN; ip_ptr = data + bytes; if (ret == 0) { SSH_DEBUG(2, ("Decoding reply packet failed.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } bytes += ip_addr_len; port_ptr = data + bytes; bytes += 2; SSH_DEBUG(2, ("Doing SOCKS5.")); if (cmd != SSH_SOCKS5_REPLY_SUCCESS) { SSH_DEBUG(2, ("Got reply %d from server.", cmd)); if (cmd < SSH_SOCKS5_REPLY_SUCCESS || cmd > SSH_SOCKS5_REPLY_ATYP_NOT_SUPPORTED) return SSH_SOCKS_ERROR_PROTOCOL_ERROR; return SSH_SOCKS_FAILED_REQUEST; } } if (socksinfo) { SshIpAddrStruct ip_addr; if ((*socksinfo = ssh_calloc(1, sizeof(SocksInfoStruct))) == NULL) { SSH_DEBUG(2, ("Couldn't allocate SocksInfo.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } memset(&ip_addr, 0, sizeof(ip_addr)); (*socksinfo)->socks_version_number = version; (*socksinfo)->command_code = cmd; port = SSH_GET_16BIT(port_ptr); ssh_dsprintf(&(*socksinfo)->port, "%lu", port); if (username) (*socksinfo)->username = ssh_strdup(username); else (*socksinfo)->username = NULL; if (atyp == SSH_SOCKS5_ATYP_FQDN) { (*socksinfo)->ip = ssh_calloc(ip_addr_len + 1, sizeof(char)); if ((*socksinfo)->ip) memmove((*socksinfo)->ip, ip_ptr, ip_addr_len); } else { unsigned char buf[SSH_IP_ADDR_STRING_SIZE]; SSH_IP_DECODE(&ip_addr, ip_ptr, ip_addr_len); ssh_ipaddr_print(&ip_addr, buf, sizeof(buf) - 1); (*socksinfo)->ip = ssh_strdup(buf); } } SSH_DEBUG(2, ("Decoded %zd bytes.", bytes)); ssh_buffer_consume(buffer, bytes); return SSH_SOCKS_SUCCESS; }
Boolean ssh_pgp_read_packet(SshFileBuffer *filebuf, SshPgpPacket *packet) { unsigned char type_id; int packet_type; int i; size_t l; Boolean fr; Boolean partial_body; SshPgpPacket newpacket; SshBuffer partial_buf; Boolean partial_buf_init; partial_buf_init = FALSE; do { fr = ssh_file_buffer_expand(filebuf, 1); if (fr == FALSE) goto failed; type_id = *(ssh_buffer_ptr(&(filebuf->buf))); ssh_buffer_consume(&(filebuf->buf), 1); SSH_DEBUG(5, ("type_id = %d\n", type_id)); if (type_id & 0x40) { /* New packet header format */ SSH_DEBUG(5, ("New packet header format\n")); if (partial_buf_init == FALSE) packet_type = type_id & 0x7f; fr = ssh_file_buffer_expand(filebuf, 1); if (fr == FALSE) goto failed; l = *(ssh_buffer_ptr(&(filebuf->buf))); ssh_buffer_consume(&(filebuf->buf), 1); if ((l >= 192) && (l <= 223)) { partial_body = FALSE; fr = ssh_file_buffer_expand(filebuf, 1); if (fr == FALSE) goto failed; l = (((l - 192) << 8) + ((size_t)(*(ssh_buffer_ptr(&(filebuf->buf))))) + 192); ssh_buffer_consume(&(filebuf->buf), 1); } else if ((l >= 224) && (l <= 254)) { partial_body = TRUE; fr = ssh_file_buffer_expand(filebuf, 1); if (fr == FALSE) goto failed; l = ((size_t)1) << ((*(ssh_buffer_ptr(&(filebuf->buf)))) & 0x1f); ssh_buffer_consume(&(filebuf->buf), 1); if (partial_buf_init == FALSE) { ssh_buffer_init(&partial_buf); partial_buf_init = TRUE; } } else if (l == 255) { partial_body = FALSE; l = 0; fr = ssh_file_buffer_expand(filebuf, 4); if (fr == FALSE) goto failed; for (i = 0; i < 4; i++) { l = (l << 8) + (*(ssh_buffer_ptr(&(filebuf->buf)))); ssh_buffer_consume(&(filebuf->buf), 1); } } else { partial_body = FALSE; } } else { size_t ll; /* Old packet header format */ SSH_DEBUG(5, ("Old packet header format\n")); partial_body = FALSE; if (partial_buf_init == FALSE) packet_type = (type_id & 0x7c) >> 2; ll = ((int)1) << (type_id & 0x03); fr = ssh_file_buffer_expand(filebuf, (int)ll); if (fr == FALSE) goto failed; l = 0; for (i = 0; i < ll; i++) { l = (l << 8) + (*(ssh_buffer_ptr(&(filebuf->buf)))); ssh_buffer_consume(&(filebuf->buf), 1); } } if ((l < 1) || (l > 0x4000)) /* XXX */ goto failed; fr = ssh_file_buffer_expand(filebuf, l); if (fr == FALSE) goto failed; if (partial_body == FALSE) { if (packet != NULL) { newpacket = ssh_xmalloc(sizeof (struct SshPgpPacketRec)); newpacket->type = packet_type; if (partial_buf_init) { newpacket->len = l + ssh_buffer_len(&partial_buf); newpacket->data = ssh_xmalloc(newpacket->len); memcpy(newpacket->data, ssh_buffer_ptr(&partial_buf), ssh_buffer_len(&partial_buf)); memcpy(&(newpacket->data[ssh_buffer_len(&partial_buf)]), ssh_buffer_ptr(&(filebuf->buf)), l); ssh_buffer_uninit(&partial_buf); partial_buf_init = FALSE; } else { newpacket->len = l; newpacket->data = ssh_xmalloc(l); memcpy(newpacket->data, ssh_buffer_ptr(&(filebuf->buf)), l); } *packet = newpacket; ssh_buffer_consume(&(filebuf->buf), l); } } else { ssh_buffer_append(&partial_buf, ssh_buffer_ptr(&(filebuf->buf)), l); ssh_buffer_consume(&(filebuf->buf), l); } } while (partial_body == TRUE); return TRUE; failed: if (partial_buf_init == TRUE) ssh_buffer_uninit(&partial_buf); return FALSE; }
/* * Parse incoming socks connection from buffer. Consume the request * packet data from buffer. If everything is ok it allocates SocksInfo * strcture and store the request fields in it (sets * socks_version_number, command_code, ip, port, username). Returns * SSH_SOCKS_SUCCESS, SSH_SOCKS_TRY_AGAIN, or SSH_SOCKS_ERROR_*. If * anything other than SSH_SOCKS_SUCCESS is returned the socksinfo is * set to NULL. Use ssh_socks_free to free socksinfo data. */ SocksError ssh_socks_server_parse_open(SshBuffer buffer, SocksInfo *socksinfo) { unsigned char *data, *ip; unsigned long i, port; unsigned int version, cmd, ip_addr_len, atyp; unsigned char *username = NULL; size_t ret, len, bytes = 0; *socksinfo = NULL; len = ssh_buffer_len(buffer); data = ssh_buffer_ptr(buffer); if (len < 1) return SSH_SOCKS_TRY_AGAIN; version = data[0]; bytes++; if (version != 4 && version != 5) { SSH_DEBUG(2, ("Server gave us version %d.", version)); return SSH_SOCKS_ERROR_UNSUPPORTED_SOCKS_VERSION; } if (version == 4) { /* Check if enough data for header and name */ if (len < SOCKS4_COMMAND_SIZE + 1) { return SSH_SOCKS_TRY_AGAIN; } /* Find the end of username */ for (i = SOCKS4_COMMAND_SIZE; i < len; i++) { if (data[i] == '\0') break; } /* End of username not found, return either error or try_again */ if (i == len || data[i] != '\0') { if (len > SOCKS4_COMMAND_SIZE + SOCKS4_MAX_NAME_LEN) { return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } return SSH_SOCKS_TRY_AGAIN; } cmd = data[1]; port = SSH_GET_16BIT(&data[2]); ip_addr_len = 4; ip = ssh_memdup(&data[4], ip_addr_len); atyp = SSH_SOCKS5_ATYP_IPV4; if (ip == NULL) { SSH_DEBUG(2, ("Failed to allocate IP-address buffer.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } username = ssh_strdup((char *)(data + SOCKS4_COMMAND_SIZE)); bytes = SOCKS4_COMMAND_SIZE + strlen((char *) data + SOCKS4_COMMAND_SIZE) + 1; } else { unsigned char port_buf[2]; if (len - bytes < 3) return SSH_SOCKS_TRY_AGAIN; ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_CHAR(&cmd), SSH_DECODE_CHAR(NULL), /* RSV */ SSH_DECODE_CHAR(&atyp), SSH_FORMAT_END); if (ret <= 0) { SSH_DEBUG(2, ("Failed to decode command packet.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } bytes += ret; if (atyp == SSH_SOCKS5_ATYP_IPV4) { SSH_DEBUG(4, ("SOCKS5 received address type IPV4.")); ip_addr_len = 4; } else if (atyp == SSH_SOCKS5_ATYP_IPV6) { SSH_DEBUG(4, ("SOCKS5 received address type IPV6.")); ip_addr_len = 16; } else if (atyp == SSH_SOCKS5_ATYP_FQDN) { if (len - bytes < 1) return SSH_SOCKS_TRY_AGAIN; ip_addr_len = *(data + bytes); if (ip_addr_len <= 0 || ip_addr_len >= 255) { SSH_DEBUG(2, ("Invalid FQDN address len %d.", ip_addr_len)); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } SSH_DEBUG(4, ("SOCKS5 received address type FQDN, len %d.", ip_addr_len)); bytes++; } else { SSH_DEBUG(2, ("Invalid address type %d.", atyp)); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } /* ip addr len + port */ if (len - bytes < ip_addr_len + 2) return SSH_SOCKS_TRY_AGAIN; ip = ssh_calloc(ip_addr_len + 1, sizeof(unsigned char)); if (ip == NULL) { SSH_DEBUG(2, ("Failed to allocate IP-address buffer.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_DATA(ip, ip_addr_len), SSH_DECODE_DATA(port_buf, 2), SSH_FORMAT_END); if (ret <= 0) { SSH_DEBUG(2, ("Failed to decode command packet.")); ssh_free(ip); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } port = SSH_GET_16BIT(port_buf); bytes += ret; } if ((*socksinfo = ssh_calloc(1, sizeof(struct SocksInfoRec))) == NULL) { SSH_DEBUG(2, ("Failed to allocate SocksInfo.")); ssh_free(ip); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } if (atyp == SSH_SOCKS5_ATYP_FQDN) { (*socksinfo)->ip = ip; } else { SshIpAddrStruct ip_addr; unsigned char buf[SSH_IP_ADDR_STRING_SIZE]; SSH_IP_DECODE(&ip_addr, ip, ip_addr_len); ssh_ipaddr_print(&ip_addr, buf, sizeof(buf)); (*socksinfo)->ip = ssh_memdup(buf, ssh_ustrlen(buf)); ssh_free(ip); if ((*socksinfo)->ip == NULL) { SSH_DEBUG(2, ("Failed to allocate final IP-addr buf.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } } (*socksinfo)->socks_version_number = version; (*socksinfo)->command_code = cmd; ssh_dsprintf(&(*socksinfo)->port, "%lu", port); (*socksinfo)->username = username; ssh_buffer_consume(buffer, bytes); SSH_DEBUG(5, ("Decoded %zd bytes.", bytes)); return SSH_SOCKS_SUCCESS; }
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; }
void t_tcpc_stream_callback(SshStreamNotification notification, void* context) { t_tcpc_context pcontext = context; char buf[4096]; int i; SSH_TRACE(SSH_D_MY, ("%s", "t_tcpc_stream_callback")); switch (notification) { case SSH_STREAM_INPUT_AVAILABLE: SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_INPUT_AVAILABLE")); while ((i = ssh_stream_read(pcontext->pstream, buf, 4096)) > 0) { buf[i] = 0; SSH_TRACE(SSH_D_MY, ("read: %s", buf)); if (pcontext->phost_name_or_address) { ssh_buffer_append(pcontext->pbuffer, buf, i); t_tcpc_stream_callback(SSH_STREAM_CAN_OUTPUT, pcontext); } else { SSH_TRACE(SSH_D_MY, ("output: %s", buf)); } } break; case SSH_STREAM_CAN_OUTPUT: SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_CAN_OUTPUT")); if (ssh_buffer_len(pcontext->pbuffer) > 0) { i = ssh_stream_write(pcontext->pstream, ssh_buffer_ptr(pcontext->pbuffer), ssh_buffer_len(pcontext->pbuffer)); if (i > 0) { ssh_buffer_consume(pcontext->pbuffer, i); } } break; case SSH_STREAM_DISCONNECTED: SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_DISCONNECTED")); #if 0 /* BUG BUG BUG */ ssh_stream_destroy(pcontext->pstream); #endif /* 0 */ ssh_event_loop_abort(); break; default: SSH_NOTREACHED; break; } }
static void filter_html(SshBuffer to, SshBuffer from, Boolean eof_seen, void *context) { ProxyRequest *req = context; unsigned char *cp; size_t len; size_t i; restart: cp = ssh_buffer_ptr(from); len = ssh_buffer_len(from); for (i = 0; i < len; i++) { switch (req->state) { case FILTER_TEXT: if (cp[i] == '<') { ssh_buffer_append(to, cp, i); ssh_buffer_consume(from, i); len = ssh_buffer_len(from); cp = ssh_buffer_ptr(from); /* Is the end of the tag seen? */ for (i = 0; i < len; i++) if (cp[i] == '>') { i++; break; } if (i >= len && !eof_seen) /* No, need more data. */ return; /* Yes, it is seen. */ if (i > 4 && strncasecmp(cp, "<img", 4) == 0) { char *url = parse_img_src(cp, i); ssh_buffer_append_cstrs(to, "<a href=\"http://amme.ssh.fi:8080", "/catch?url=", url, "\">*</a>", NULL); } ssh_buffer_append(to, cp, i); ssh_buffer_consume(from, i); goto restart; } else if (cp[i] == '&') req->state = FILTER_ENTITY; break; case FILTER_ENTITY: if (cp[i] == ';') req->state = FILTER_TEXT; break; } } ssh_buffer_append(to, ssh_buffer_ptr(from), ssh_buffer_len(from)); ssh_buffer_clear(from); }
int ssh_tls_stream_read(void *context, unsigned char *buf, size_t size) { SshTlsProtocolState s = (SshTlsProtocolState)context; SSH_ASSERT(size > 0); SSH_ASSERT(s->packet_feed_len >= 0); SSH_DEBUG(7, ("The upper layer wants to read max. %d bytes of data.", size)); reread_after_further_parsing: if (SSH_TLS_IS_FAILED_STATUS(s->status)) { SSH_DEBUG(7, ("Protocol is in error condition so give EOF.")); return 0; } if (s->packet_feed_len == 0) { SSH_DEBUG(7, ("Nothing to give (%d bytes in buffer).", ssh_buffer_len(s->incoming_raw_data))); if (s->flags & SSH_TLS_FLAG_GOT_CLOSE_NOTIFY) { SSH_DEBUG(7, ("The protocol stream has closed, thus send EOF.")); /* This is it. Now it is upto the application to kill us if it wants. Of course, data can be still sent. */ return 0; } SSH_DEBUG(7, ("App. data packet totally consumed, trailer %d bytes.", s->trailer_len)); if (s->trailer_len >= 0) { SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= s->trailer_len); ssh_buffer_consume(s->incoming_raw_data, s->trailer_len); s->trailer_len = -1; /* Now we need to call ssh_tls_parse_incoming because it is possible that there are more full packets in the incoming_raw_data buffer waiting for parsing. */ ssh_tls_parse_incoming(s); goto reread_after_further_parsing; } s->flags |= SSH_TLS_FLAG_GIVE_READ_NOTIFY; SSH_DEBUG(7, ("Set flags to %x.", (unsigned int) s->flags)); return -1; } if (size > s->packet_feed_len) size = s->packet_feed_len; memcpy(buf, ssh_buffer_ptr(s->incoming_raw_data), size); SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= size + s->trailer_len); ssh_buffer_consume(s->incoming_raw_data, size); s->packet_feed_len -= size; SSH_DEBUG(7, ("%d bytes written to the buffer, %d to feed.", size, s->packet_feed_len)); s->stats.app_bytes_given += size; trigger_rekey_if_needed(s); SSH_ASSERT(s->packet_feed_len >= 0); if (s->packet_feed_len == 0) { SSH_DEBUG(7, ("App. data packet totally consumed, trailer %d bytes.", s->trailer_len)); SSH_ASSERT(s->trailer_len >= 0); SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= s->trailer_len); ssh_buffer_consume(s->incoming_raw_data, s->trailer_len); s->trailer_len = -1; /* Now we need to call ssh_tls_parse_incoming because it is possible that there are more full packets in the incoming_raw_data buffer waiting for parsing. */ ssh_tls_parse_incoming(s); } /* Now that the incoming raw data buffer has been perhaps shrunk, try to read more data in. */ if ((s->flags & SSH_TLS_FLAG_READING_CEASED) && ssh_buffer_len(s->incoming_raw_data) < s->conf.max_buffered_data) { SSH_DEBUG(7, ("Try to read in more data as reading had been " "temporarily stopped and now there is more room.")); ssh_tls_try_read_in(s); } return size; }