void handler_send_cross(Handler c, unsigned int cross_type, const unsigned char *payload, size_t len) { unsigned char header[5]; SSH_PUT_32BIT(header, len + 1); header[4] = cross_type; ssh_buffer_append(&c->outgoing, header, 5); ssh_buffer_append(&c->outgoing, payload, len); }
int main(int ac, char **av) { int i, j; int pass; unsigned char buf[1024]; snprintf(lpath1, sizeof (lpath1), "/tmp/lstr1.%x", (unsigned)random()); snprintf(lpath2, sizeof (lpath2), "/tmp/lstr2.%x", (unsigned)random()); printf("Doing %d iterations of localstream test:", PASSES); for (pass = 0; pass < PASSES; pass++) { printf(" %d", pass); fflush(stdout); ssh_buffer_init(&send_buffer); ssh_buffer_init(&expect_buffer); for (i = 0; i < 100; i++) { for (j = 0; j < sizeof(buf); j++) buf[j] = random(); ssh_buffer_append(&send_buffer, buf, sizeof(buf)); ssh_buffer_append(&expect_buffer, buf, sizeof(buf)); send_count += sizeof(buf); } ssh_event_loop_initialize(); remove(lpath1); listener1 = ssh_local_make_listener(lpath1, listener1_callback, (void *)4); if (!listener1) { ssh_fatal("cannot create listener1"); } ssh_local_connect(lpath1, connect1_done, (void *)3); ssh_event_loop_run(); ssh_event_loop_uninitialize(); ssh_buffer_uninit(&send_buffer); ssh_buffer_uninit(&expect_buffer); } printf("\n"); return 0; }
void ssh_packet_wrapper_send_encode_va(SshPacketWrapper down, SshPacketType type, va_list va) { /* Format the packet in a separate buffer. */ ssh_buffer_clear(&down->outgoing_packet); ssh_packet_encode_va(&down->outgoing_packet, type, va); /* Check that we don't overflow maximum buffer size. Drop the packet if we would. */ if (ssh_buffer_len(&down->outgoing) + ssh_buffer_len(&down->outgoing_packet) >= BUFFER_MAX_SIZE) { ssh_debug("ssh_packet_wrapper_send_encode_va: flow control problems; " "outgoing packet dropped."); return; } /* Append the packet to the outgoing buffer. */ ssh_buffer_append(&down->outgoing, ssh_buffer_ptr(&down->outgoing_packet), ssh_buffer_len(&down->outgoing_packet)); /* Reset the callback to ensure that our callback gets called. */ ssh_stream_set_callback(down->stream, ssh_packet_wrapper_callback, (void *)down); }
void ssh_eap_build_and_send_request(SshEap eap, SshUInt8 type, const SshUInt8 *ptr, unsigned long len) { SshBuffer pkt; pkt = ssh_eap_create_request(eap, (SshUInt16)len, type); if (pkt == NULL) { ssh_eap_fatal(eap, NULL, "Out of memory. Can not send request."); return; } if (len != 0 && ptr != NULL) { if (ssh_buffer_append(pkt, ptr, len) != SSH_BUFFER_OK) { ssh_buffer_free(pkt); ssh_eap_fatal(eap, NULL, "Out of memory. Can not send request."); return; } } /* Send packet */ ssh_eap_protocol_send_request(NULL, eap, pkt); }
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); }
/* * Inserts specified event into log file specified in context. * event parameter specifies the audited event. Each element after event * must start with a SshAuditformat type followed by arguments of the * appropriate type, and the list must end with SSH_AUDIT_ARGUMENT_END. */ void ssh_audit_event(SshAuditContext context, SshAuditEvent event, ...) { size_t bytes; va_list ap; SshBuffer *audit_info, *formated_str; char *audit_time; if (context == NULL) return; if ((event < 0) || (event > SSH_AUDIT_MAX_VALUE)) return; /* Check if given event is allowed */ if (!context->ssh_audit_event_allowed[(int)event]) return; /* Initialize a buffer for output string */ audit_info = ssh_buffer_allocate(); /* Start constructing string which will be inserted into audit log.*/ /* Start with inserting the name of the event.*/ /* then date and time */ audit_time = ssh_time_string(ssh_time()); ssh_buffer_append_cstrs(audit_info, ssh_find_keyword_name(ssh_audit_event_title, (int)event), ": ", audit_time, ": ", NULL); ssh_xfree(audit_time); /* Handle the variable list*/ va_start(ap, event); formated_str = ssh_format_audit_string(ap); va_end(ap); /* Insert given parameters into string*/ ssh_buffer_append(audit_info, ssh_buffer_ptr(formated_str), ssh_buffer_len(formated_str)); ssh_buffer_append(audit_info, (unsigned char *) "\0", 1); /* Output the log message*/ ssh_send_log_message(context, ssh_buffer_ptr(audit_info)); ssh_buffer_free(formated_str); ssh_buffer_free(audit_info); }
static int ssh_appgw_http_marshal_int(SshBuffer buf, int i) { SshUInt32 hi; SSH_PUT_32BIT(&hi,i); if (ssh_buffer_append(buf,(unsigned char*)&hi,4) == SSH_BUFFER_ERROR) return 0; return 1; }
void ssh_buffer_append_cstrs(SshBuffer *buffer, ...) { va_list ap; char *str; va_start(ap, buffer); while ((str = va_arg(ap, char *)) != NULL) ssh_buffer_append(buffer, (unsigned char *) str, strlen(str)); va_end(ap); }
static int ssh_appgw_http_marshal_data(SshBuffer buf, const unsigned char *str, size_t len) { SshUInt32 i; if (str == NULL) { SSH_PUT_32BIT(&i,0); if (ssh_buffer_append(buf, (unsigned char *)&i, 4) == SSH_BUFFER_ERROR) return 0; } else { SSH_PUT_32BIT(&i,len); if (ssh_buffer_append(buf, (unsigned char*)&i, 4) == SSH_BUFFER_ERROR) return 0; if (ssh_buffer_append(buf, (unsigned char *)str,len) == SSH_BUFFER_ERROR) return 0; } return 1; }
void ssh_eap_build_and_send_reply(SshEap eap, SshUInt8 type, const SshUInt8 *ptr, SshUInt16 len) { SshBuffer pkt; /* Only send replies to requests */ SSH_ASSERT(eap->id_isinit == 1); pkt = ssh_buffer_allocate(); if (pkt == NULL) { ssh_eap_fatal(eap, NULL, "Out of memory. Can not send reply."); return; } if (!ssh_eap_packet_build_hdr_with_type(pkt, SSH_EAP_CODE_REPLY, eap->id, len, type)) { ssh_buffer_free(pkt); ssh_eap_fatal(eap, NULL, "Out of memory. Can not send reply."); return; } if (len != 0 && ptr != NULL) { if (ssh_buffer_append(pkt, ptr, len) != SSH_BUFFER_OK) { ssh_buffer_free(pkt); ssh_eap_fatal(eap, NULL, "Out of memory. Can not send reply."); return; } } /* Ok. let's transmit this packet */ ssh_eap_remember_packet(eap, pkt); ssh_eap_send_packet(eap, pkt); }
void create_testdata(void) { int len, i; unsigned char ch; if (testdata) ssh_buffer_clear(testdata); else testdata = ssh_buffer_allocate(); len = ssh_rand() % 100000; for (i = 0; i < len; i++) { ch = (unsigned char)(ssh_rand() % 256); ssh_buffer_append(testdata, &ch, 1); } }
void copy_reader(SshStreamNotification op, void *context) { unsigned char *buf; int len; if (op != SSH_STREAM_INPUT_AVAILABLE) return; buf = ssh_xmalloc(T_STREAMPAIR_BIG_BUF_LEN); for (;;) { len = ssh_stream_read(ts2, buf, T_STREAMPAIR_BIG_BUF_LEN); if (len == 0) { ssh_stream_destroy(ts2); ts2 = NULL; destroy_count++; ssh_xfree(buf); return; /* EOF received */ } if (len < 0) { ssh_xfree(buf); return; } ssh_buffer_append(received_data, buf, len); if (break_test && ssh_rand() % 10 == 0) { ssh_stream_destroy(ts2); ts2 = NULL; destroy_count++; ssh_xfree(buf); return; } if (!reader_sent_eof && ssh_rand() % 10 == 0) { ssh_stream_output_eof(ts2); reader_sent_eof = TRUE; } } /*NOTREACHED*/ }
void ssh_packet_impl_send_encode_va(SshStream up_stream, SshPacketType type, va_list va) { SshPacketImpl up; /* Verify that it is a SshPacketImpl stream. */ if (ssh_stream_get_methods(up_stream) != &ssh_packet_impl_methods) ssh_fatal("ssh_packet_impl_can_receive: not a SshPacketImpl stream"); /* Get the internal context. */ up = (SshPacketImpl)ssh_stream_get_context(up_stream); /* Format the packet in a separate buffer. */ ssh_buffer_clear(&up->outgoing_packet); ssh_packet_encode_va(&up->outgoing_packet, type, va); /* Check that we don't overflow maximum buffer size. Drop the packet if we would. */ if (ssh_buffer_len(&up->outgoing) + ssh_buffer_len(&up->outgoing_packet) >= BUFFER_MAX_SIZE) { ssh_debug("ssh_packet_impl_send_encode_va: " "flow control problems; outgoing packet dropped."); return; } /* Append the packet to the outgoing buffer. */ if (ssh_buffer_append(&up->outgoing, ssh_buffer_ptr(&up->outgoing_packet), ssh_buffer_len(&up->outgoing_packet)) != SSH_BUFFER_OK) { return; } /* Restart reads by upper level. */ ssh_packet_impl_restart_input(up); /* Sanity check that we didn't exceed max buffer size. */ if (ssh_buffer_len(&up->outgoing) > BUFFER_MAX_SIZE) ssh_debug("ssh_packet_impl_send: buffer max size exceeded: size %ld", (long)ssh_buffer_len(&up->outgoing)); }
void t_tcpc_timeout_callback(void *context) { t_tcpc_context pcontext = context; SSH_TRACE(SSH_D_MY, ("%s", "t_tcpc_timeout_callback")); if (! pcontext || !pcontext->pdata) return; ssh_buffer_append(pcontext->pbuffer, pcontext->pdata, strlen(pcontext->pdata)); t_tcpc_stream_callback(SSH_STREAM_CAN_OUTPUT, pcontext); ssh_xregister_timeout(pcontext->timeout, 0, t_tcpc_timeout_callback, pcontext); }
void ssh_audit_syslog_cb(SshAuditEvent event, SshUInt32 argc, SshAuditArgument argv, void *context) { SshAuditSyslogContext ctx = (SshAuditSyslogContext) context; ssh_buffer_clear(&ctx->buffer); if (!ssh_audit_format(&ctx->buffer, ctx->format, event, argc, argv)) { error: SSH_DEBUG(SSH_D_ERROR, ("Could not format event into a string")); return; } if (ssh_buffer_append(&ctx->buffer, (unsigned char *) "\0", 1) != SSH_BUFFER_OK) goto error; ssh_log_event(ctx->facility, ctx->severity, "%s", (char *) ssh_buffer_ptr(&ctx->buffer)); }
SshTlsTransStatus ssh_tls_trans_write_change_cipher(SshTlsProtocolState s) { ssh_tls_start_building(s, SSH_TLS_CTYPE_CHANGE_CIPHER); if (ssh_buffer_append(s->outgoing_raw_data, (unsigned char *)"\001", 1) == SSH_BUFFER_OK) s->built_len++; else return SSH_TLS_TRANS_FAILED; /* Must flush so that the coming change does not affect this packet. */ ssh_tls_flush(s); #ifdef SSH_IPSEC_HWACCEL_SUPPORT_TLS /* Wait outgoing crypto operations to complete */ if (s->conn.outgoing.ops_pending) { s->outgoing_all_complete_cb = ssh_tls_write_change_cipher_finish; s->kex.state = SSH_TLS_KEX_WAIT_OUT_CRYPTO_COMPLETION; s->kex.next_state = s->conf.is_server ? SSH_TLS_KEX_SEND_S_FINISHED:SSH_TLS_KEX_SEND_C_FINISHED; s->kex.alert = 0; s->kex.alert_text = NULL; ssh_tls_async_freeze(s); return SSH_TLS_TRANS_OK; } #endif /* SSH_IPSEC_HWACCEL_SUPPORT_TLS */ /* Now change cipher context. */ if (!ssh_tls_change_cipher_context(s, TRUE)) return SSH_TLS_TRANS_FAILED; if (s->conf.is_server) s->kex.state = SSH_TLS_KEX_SEND_S_FINISHED; else s->kex.state = SSH_TLS_KEX_SEND_C_FINISHED; return SSH_TLS_TRANS_OK; }
static void ssh_eap_md5_server_begin(SshEapProtocol protocol, SshEap eap) { unsigned long name_len; SshEapMd5State state; SshEapMd5Params params; SshUInt8 rndbyte; SshBuffer pkt; int i; state = ssh_eap_protocol_get_state(protocol); params = ssh_eap_protocol_get_params(protocol); if (state == NULL) { SSH_DEBUG(SSH_D_ERROR, ("eap md5 state not initialized. " "can not begin authentication")); return; } /* Parse parameters for defaults and free any "old" state */ if (params == NULL) { /* Do not leak too much information regarding the state of the PRNG, but make a sufficiently difficult (256 bits) challenge. */ state->challenge_length = 32; name_len = 0; } else { state->challenge_length = params->challenge_length; name_len = params->name_length; } if (state->challenge_length > 255) state->challenge_length = 255; SSH_ASSERT(state->challenge_length > 0); if (state->challenge_buffer != NULL) { ssh_free(state->challenge_buffer); state->challenge_buffer = NULL; } /* Build packet */ pkt = ssh_eap_create_request(eap, (SshUInt16)(1 + state->challenge_length + name_len), protocol->impl->id); if (pkt == NULL) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not create request"); return; } SSH_ASSERT(state->challenge_length < 256); rndbyte = (SshUInt8)state->challenge_length; if (ssh_buffer_append(pkt, &rndbyte, 1) != SSH_BUFFER_OK) { ssh_buffer_free(pkt); ssh_eap_fatal(eap, protocol, "Out of memory. Could not create request"); return; } state->challenge_buffer = ssh_malloc(state->challenge_length); if (state->challenge_buffer == NULL) { ssh_buffer_free(pkt); ssh_eap_fatal(eap, protocol, "Out of memory. Could not create challenge"); return; } for (i = 0; i < state->challenge_length; i++) { rndbyte = (SshUInt8)ssh_random_get_byte(); state->challenge_buffer[i] = rndbyte; if (ssh_buffer_append(pkt, &rndbyte, 1) != SSH_BUFFER_OK) { ssh_buffer_free(pkt); ssh_free(state->challenge_buffer); state->challenge_buffer = NULL; ssh_eap_fatal(eap, protocol, "Out of memory. Could not create request"); return; } } if (name_len > 0) { SSH_ASSERT(params != NULL && params->name_buffer != NULL); if (ssh_buffer_append(pkt, params->name_buffer, name_len)) { ssh_buffer_free(pkt); ssh_free(state->challenge_buffer); state->challenge_buffer = NULL; ssh_eap_fatal(eap, protocol, "Out of memory. Could not create request"); return; } } state->response_id = ssh_eap_packet_get_identifier(pkt); SSH_DEBUG(SSH_D_MIDOK,("sending eap md5 authentication request")); ssh_eap_protocol_send_request(protocol, eap, pkt); }
Boolean handler_output(Handler c) { SshBuffer buffer; unsigned int len; const unsigned char *cp; Boolean wake_up_input = FALSE; for (;; c->script++) { #ifdef DEBUG ssh_debug("%s: handler_output: %s", c->side, opnames[c->script->op]); #endif switch (c->script->op) { case OP_EXPECT_SERVICE_REQUEST: case OP_EXPECT_DISCONNECT: case OP_EXPECT_EOF: case OP_EXPECT_STARTUP: case OP_EXPECT_ALGORITHMS: case OP_EXPECT_PACKET: case OP_EXPECT_TEST_STREAM: wake_up_input = TRUE; goto out; case OP_SEND_SERVICE_ACCEPT: handler_send_cross(c, SSH_CROSS_SERVICE_ACCEPT, NULL, 0); break; case OP_SEND_REKEY_REQUEST: ssh_buffer_init(&buffer); store_delimited_strings(&buffer, c->script->arg); handler_send_cross(c, SSH_CROSS_REKEY_REQUEST, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)); ssh_buffer_uninit(&buffer); break; case OP_SEND_PACKET: ssh_buffer_init(&buffer); buffer_put_char(&buffer, atoi(c->script->arg)); handler_send_cross(c, SSH_CROSS_PACKET, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)); ssh_buffer_uninit(&buffer); break; case OP_SEND_TEST_STREAM: while (c->stream_offset < ssh_buffer_len(&testdata)) { if (ssh_buffer_len(&c->outgoing) > XMALLOC_MAX_SIZE - SSH_MAX_PAYLOAD_LENGTH - 5000 || ssh_buffer_len(&c->outgoing) > 50000 - SSH_MAX_PAYLOAD_LENGTH) if (!handler_output_outgoing(c)) goto out; len = random() % (SSH_MAX_PAYLOAD_LENGTH - 3); if (len > ssh_buffer_len(&testdata) - c->stream_offset) len = ssh_buffer_len(&testdata) - c->stream_offset; ssh_buffer_init(&buffer); buffer_put_char(&buffer, atoi(c->script->arg)); cp = ssh_buffer_ptr(&testdata); ssh_buffer_append(&buffer, cp + c->stream_offset, len); c->stream_offset += len; handler_send_cross(c, SSH_CROSS_PACKET, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)); ssh_buffer_uninit(&buffer); } c->stream_offset = 0; break; case OP_SEND_DISCONNECT: ssh_buffer_init(&buffer); buffer_put_boolean(&buffer, TRUE); buffer_put_int(&buffer, SSH_DISCONNECT_BY_APPLICATION); buffer_put_uint32_string(&buffer, c->script->arg, strlen(c->script->arg)); buffer_put_uint32_string(&buffer, "", 0); handler_send_cross(c, SSH_CROSS_DISCONNECT, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)); ssh_buffer_uninit(&buffer); break; case OP_SEND_EOF: c->outgoing_eof = TRUE; break; case OP_END: goto out; default: ssh_fatal("%s: handler_output: unknown op %d", c->side, (int)c->script->op); } } out: c->output_blocked = handler_output_outgoing(c); return wake_up_input; }
int ssh_packet_impl_write(void *context, const unsigned char *buf, size_t size) { SshPacketImpl up = (SshPacketImpl)context; size_t offset, payload_len, len; unsigned char *ucp; /* If shortcircuiting, direct the write down. */ if (up->shortcircuit_stream) { SSH_ASSERT(ssh_buffer_len(&up->incoming) == 0); return ssh_stream_write(up->shortcircuit_stream, buf, size); } offset = 0; normal: while (up->can_receive && !up->incoming_eof && offset < size && !up->shortcircuit_stream) { /* If already processing a partial packet, continue it now. */ if (ssh_buffer_len(&up->incoming) > 0) goto partial; /* If only partial packet available, do special proccessing. */ if (size - offset < 4) goto partial; /* Need partial packet processing. */ payload_len = SSH_GET_32BIT(buf + offset); if (payload_len < 1) goto partial; if (size - offset < 4 + payload_len) goto partial; /* Need partial packet processing. */ /* The entire packet is available; pass it to the callback. */ if (up->received_packet) (*up->received_packet)((SshPacketType)buf[offset + 4], buf + offset + 5, payload_len - 1, up->context); offset += 4 + payload_len; } /* We cannot take more data now. If we processed some data, return the number of bytes processed. */ if (offset > 0) return offset; /* We couldn't take any data. Remember that we have returned error to the writer and must call the callback later. */ up->up_write_blocked = TRUE; return -1; partial: /* Process partial packet. First we read its header. */ len = ssh_buffer_len(&up->incoming); if (len < 4) { len = 4 - len; if (size - offset < len) len = size - offset; if (ssh_buffer_append(&up->incoming, buf + offset, len) != SSH_BUFFER_OK) { (*up->received_eof)(up->context); return 0; } offset += len; } if (ssh_buffer_len(&up->incoming) < 4) return offset; /* Get the length of the packet. */ ucp = ssh_buffer_ptr(&up->incoming); payload_len = SSH_GET_32BIT(ucp); if (payload_len < 1) { /* Received an invalid packet with length = 0, even though we should always have at least the packet type. */ (*up->received_eof)(up->context); return 0; } /* Add remaining data in the packet to the buffer. */ len = 4 + payload_len - ssh_buffer_len(&up->incoming); if (len > size - offset) len = size - offset; if (ssh_buffer_append(&up->incoming, buf + offset, len) != SSH_BUFFER_OK) { (*up->received_eof)(up->context); return 0; } offset += len; /* If some data still not available, return. */ if (ssh_buffer_len(&up->incoming) < 4 + payload_len) return offset; /* The entire packet is now in buffer. */ ucp = ssh_buffer_ptr(&up->incoming); if (up->received_packet) (*up->received_packet)((SshPacketType)ucp[4], ucp + 5, payload_len - 1, up->context); /* Clear the incoming partial packet buffer and resume normal processing. */ ssh_buffer_clear(&up->incoming); goto normal; }
static void ssh_eap_md5_client_recv_token(SshEapProtocol protocol, SshEap eap, SshBuffer buf) { SshEapMd5State state; SshEapMd5Params params; SshBuffer pkt = NULL; SshUInt8 b; SshHash hash = NULL; SshCryptoStatus status; unsigned long len; unsigned long name_len; unsigned long secret_len; SshUInt8 *secret_ptr; SshEapToken t; SshUInt8 hashbuf[32]; if (ssh_eap_get_token_type_from_buf(buf) != SSH_EAP_TOKEN_SHARED_SECRET) { ssh_eap_discard_token(eap, protocol, buf, ("unexpected token type")); return; } t = (SshEapToken)ssh_buffer_ptr(buf); if (t == NULL) { ssh_eap_discard_token(eap, protocol, buf, ("invalid token")); return; } secret_ptr = ssh_eap_get_token_secret_ptr(t); secret_len = ssh_eap_get_token_secret_len(t); SSH_ASSERT(secret_ptr != NULL || secret_len == 0); state = ssh_eap_protocol_get_state(protocol); params = ssh_eap_protocol_get_params(protocol); status = SSH_CRYPTO_UNSUPPORTED; name_len = 0; if (params != NULL && params->name_buffer != NULL) { name_len = params->name_length; } if (state->challenge_buffer == NULL) { ssh_eap_discard_token(eap, protocol, buf, "EAP MD5 state lacks authenticator challenge"); goto fail_auth; } status = ssh_hash_allocate("md5", &hash); if (status != SSH_CRYPTO_OK) { ssh_eap_discard_token(eap, protocol, buf, "failed to initialize MD5 function"); goto fail_auth; } len = ssh_hash_digest_length(ssh_hash_name(hash)); if (len > 32) { ssh_eap_fatal(eap, protocol, "MD5 output of unexpected size"); goto fail_auth; } pkt = ssh_eap_create_reply(eap, (SshUInt16)(1 + len + name_len), protocol->impl->id); if (pkt == NULL) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not allocate reply packet."); goto fail_auth; } b = (SshUInt8)(len & 0xFF); if (ssh_buffer_append(pkt,&b,1) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } ssh_hash_reset(hash); ssh_hash_update(hash, &state->response_id, 1); ssh_hash_update(hash, secret_ptr, secret_len); ssh_hash_update(hash, state->challenge_buffer, state->challenge_length); ssh_hash_final(hash, hashbuf); if (ssh_buffer_append(pkt, hashbuf, len) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } if (name_len > 0) { if (ssh_buffer_append(pkt, params->name_buffer, name_len) != SSH_BUFFER_OK) { ssh_eap_fatal(eap, protocol, "Out of memory. Could not build reply packet."); goto fail_auth; } } ssh_eap_protocol_send_response(protocol, eap, pkt); pkt = NULL; ssh_eap_protocol_auth_ok(protocol, eap, SSH_EAP_SIGNAL_NONE, NULL); fail_auth: if (pkt != NULL) ssh_buffer_free(pkt); if (hash != NULL) ssh_hash_free(hash); ssh_eap_md5_reset(protocol,eap); }
int main(int ac, char **av) { unsigned int pass, i; SshBuffer buffer, buffer2; SocksInfo socksinfo, socksreturn; SocksError ret; ssh_buffer_init(&buffer); ssh_buffer_init(&buffer2); for(pass = 0; pass < 20000; pass++) { ssh_buffer_clear(&buffer); socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open fails"); if (pass & 1) { unsigned char *p; unsigned int len; ssh_buffer_clear(&buffer2); p = ssh_buffer_ptr(&buffer); len = ssh_buffer_len(&buffer); /* Give partial buffer */ for(i = 0; i + 1 < len; i++) { ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_server_parse_open(&buffer2, &socksreturn) != SSH_SOCKS_TRY_AGAIN) ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)"); } ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_server_parse_open(&buffer2, &socksreturn) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)"); if (ssh_buffer_len(&buffer2) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } else { if (ssh_socks_server_parse_open(&buffer, &socksreturn) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)"); if (ssh_buffer_len(&buffer) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } if (socksinfo->socks_version_number != socksreturn->socks_version_number) ssh_fatal("socks_version_numbers differ request"); if (socksinfo->command_code != socksreturn->command_code) ssh_fatal("command_codes differ request"); if (strcmp(socksinfo->ip, socksreturn->ip) != 0) ssh_fatal("ip numbers differ request"); if (strcmp(socksinfo->port, socksreturn->port) != 0) ssh_fatal("port numbers differ request"); if (strcmp(socksinfo->username, socksreturn->username) != 0) ssh_fatal("usernames differ request"); ssh_socks_free(&socksreturn); ssh_socks_free(&socksinfo); ssh_buffer_clear(&buffer); socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 0; socksinfo->command_code = (pass % 4) + 90; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_server_generate_reply(&buffer, socksinfo) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply fails"); if (pass & 1) { unsigned char *p; unsigned int len; ssh_buffer_clear(&buffer2); p = ssh_buffer_ptr(&buffer); len = ssh_buffer_len(&buffer); /* Give partial buffer */ for(i = 0; i + 1 < len; i++) { ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_client_parse_reply(&buffer2, &socksreturn) != SSH_SOCKS_TRY_AGAIN) ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)"); } ssh_buffer_append(&buffer2, p + i, 1); ret = ssh_socks_client_parse_reply(&buffer2, &socksreturn); if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) || ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) || ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) || ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME)) ssh_fatal("ssh_socks_client_parse_reply fails for partial data"); if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer2) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } else { ret = ssh_socks_client_parse_reply(&buffer, &socksreturn); if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) || ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) || ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) || ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME)) ssh_fatal("ssh_socks_client_parse_reply fails"); if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } if (ret == SSH_SOCKS_SUCCESS) { if (socksinfo->socks_version_number != socksreturn->socks_version_number) ssh_fatal("socks_version_numbers differ reply"); if (socksinfo->command_code != socksreturn->command_code) ssh_fatal("command_codes differ reply"); if (strcmp(socksinfo->ip, socksreturn->ip) != 0) ssh_fatal("ip numbers differ reply"); if (strcmp(socksinfo->port, socksreturn->port) != 0) ssh_fatal("port numbers differ reply"); ssh_socks_free(&socksreturn); } ssh_socks_free(&socksinfo); } ssh_buffer_clear(&buffer); for(pass = 0; pass < (sizeof(ip_invalid_numbers) / sizeof(ip_invalid_numbers[0])); pass++) { socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_invalid_numbers[pass % (sizeof(ip_invalid_numbers) / sizeof(ip_invalid_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open success (should fail, ip)"); socksinfo->socks_version_number = 0; socksinfo->command_code = (pass % 4) + 90; if (ssh_socks_server_generate_reply(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply success (should fail, ip)"); ssh_socks_free(&socksinfo); } for(pass = 0; pass < (sizeof(port_invalid_numbers) / sizeof(port_invalid_numbers[0])); pass++) { socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_invalid_numbers[pass % (sizeof(port_invalid_numbers) / sizeof(port_invalid_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open success (should fail, port)"); socksinfo->command_code = (pass % 4) + 90; socksinfo->socks_version_number = 0; if (ssh_socks_server_generate_reply(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply success (should fail, port)"); ssh_socks_free(&socksinfo); } if (ssh_buffer_len(&buffer) != 0) ssh_fatal("some of the failed ssh_socks_*_generate_* function wrote something to buffer, size != 0"); ssh_buffer_uninit(&buffer); ssh_buffer_uninit(&buffer2); return 0; }
/* This function reads complete payload from the HTTP stream described at the context argument (also the thread running this session is identified b the context's upper context), and calls the input processing thread when done. This gets called when the CA replies to the clients message or poll. */ static void pkix_http_stream_callback(SshStreamNotification not, void *context) { int i; size_t len; SshUInt8 type_or_version; unsigned char input[256], *data; PkixHttpReadContext c = (PkixHttpReadContext)context; SshFSMThread thread = (SshFSMThread) c->upper_context; SshPkiThreadData tdata = ssh_fsm_get_tdata(thread); SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread); while (TRUE) { i = ssh_stream_read(c->http_stream, input, sizeof(input)); if (i == 0) { if ((len = ssh_buffer_len(c->input)) > 5) { data = ssh_buffer_ptr(c->input); len = SSH_GET_32BIT(data); type_or_version = data[4]; if (type_or_version < 10) { tdata->input_version = SSH_PKI_VERSION_0; tdata->input_flags = 0; tdata->input_type = type_or_version; tdata->input_len = len - 1; tdata->input = ssh_memdup(data + 5, tdata->input_len); } else { if (type_or_version == 10) { data += 4; /* skip to end of length */ tdata->input_version = SSH_PKI_VERSION_1; tdata->input_len = len - 3; tdata->input_flags = data[1]; tdata->input_type = data[2]; data += 3; tdata->input = ssh_memdup(data, tdata->input_len); } else { tdata->input_version = type_or_version; tdata->input_type = SSH_PKI_MSG_ERRORREP; } } if (tdata->input == NULL) tdata->input_type = SSH_PKI_MSG_ERRORREP; ssh_buffer_free(c->input); ssh_stream_destroy(c->http_stream); ssh_fsm_continue(gdata->input_thread); ssh_free(c); return; } else { error: tdata->input_type = SSH_PKI_MSG_ERRORREP; ssh_fsm_set_next(thread, pkix_aborted); ssh_fsm_continue(gdata->input_thread); ssh_stream_destroy(c->http_stream); ssh_buffer_free(c->input); ssh_free(c); return; } } else if (i < 0) { return; } else { if (ssh_buffer_append(c->input, input, i) != SSH_BUFFER_OK) { goto error; } } } }
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); }
static void copy_data(SshBuffer to, SshBuffer from, Boolean eof_seen, void *context) { ssh_buffer_append(to, ssh_buffer_ptr(from), ssh_buffer_len(from)); ssh_buffer_clear(from); }
int ssh_tls_stream_write(void *context, const unsigned char *buf, size_t size) { int iv_len = 0; /*CBCATT, TLS1.1: need space for storing random IV*/ SshTlsProtocolState s = (SshTlsProtocolState)context; SSH_DEBUG(7, ("The upper layer wants to write max. %d bytes of data.", size)); /* If this assert fails it is an application error. */ SSH_ASSERT(!(s->flags & SSH_TLS_FLAG_OUTPUT_EOF)); if (SSH_TLS_IS_FAILED_STATUS(s->status)) { SSH_DEBUG(7, ("Do not accept more application data as the " "protocol is being shut down.")); return 0; } if (s->flags & SSH_TLS_FLAG_STREAM_WRITE_CLOSED) { SSH_DEBUG(7, ("The underlying stream does not accept data any more, " "thus return zero.")); return 0; } if (!(s->flags & SSH_TLS_FLAG_INITIAL_KEX_DONE)) { SSH_DEBUG(7, ("Do not accept application data yet as the initial " "key exchange has not been finished.")); /* We need to notify the application when the KEX has been finished. */ s->flags |= SSH_TLS_FLAG_GIVE_WRITE_NOTIFY; return -1; } if (s->kex.state != SSH_TLS_KEX_CLEAR) { SSH_DEBUG(7, ("Do not send application data now as a key exchange " "is in progress.")); /* We need to notify the application when the KEX has been finished. */ s->flags |= SSH_TLS_FLAG_GIVE_WRITE_NOTIFY; return -1; } if ((s->conn.outgoing.cipher) && !s->conn.outgoing.is_stream_cipher && SSH_TLS_VER_TLS1_1 == ssh_tls_version(s)) { iv_len = s->conn.outgoing.block_length; SSH_DEBUG(6, ("Adjusting for CBCATT random IV size %d", iv_len)); } /* Check that we do not create a too long packet. */ if (s->built_len == 0) { if (size > SSH_TLS_MAX_RECORD_LENGTH - iv_len) size = SSH_TLS_MAX_RECORD_LENGTH - iv_len; } else { if (size + s->built_len > SSH_TLS_MAX_RECORD_LENGTH + SSH_TLS_HEADER_SIZE - iv_len) size = (SSH_TLS_MAX_RECORD_LENGTH + SSH_TLS_HEADER_SIZE) - s->built_len - iv_len; } #ifdef SSH_IPSEC_HWACCEL_SUPPORT_TLS { int bytes = ssh_tls_appstream_can_write_bytes(s); if (bytes < size) size = bytes; #else { long l = ssh_buffer_len(s->outgoing_raw_data); if (size + l > s->conf.max_buffered_data) { if (l > s->conf.max_buffered_data) size = 0; else size = s->conf.max_buffered_data - l; } #endif /* SSH_IPSEC_HWACCEL_SUPPORT_TLS */ if (size == 0) { SSH_DEBUG(7, ("Cannot fit more data into the outgoing data buffer")); s->flags |= SSH_TLS_FLAG_GIVE_WRITE_NOTIFY; return -1; } } if (s->conf.flags & SSH_TLS_FIX_IV_LEAK) { ssh_tls_start_building(s, SSH_TLS_CTYPE_APPDATA); ssh_tls_flush(s); } ssh_tls_start_building(s, SSH_TLS_CTYPE_APPDATA); if (ssh_buffer_append(s->outgoing_raw_data, buf, size) == SSH_BUFFER_OK) { s->built_len += size; s->stats.app_bytes_got += size; } else { SSH_DEBUG(7, ("The send buffer can not fit any more data " "thus return zero.")); return 0; } trigger_rekey_if_needed(s); /* Check for a long packet that could be sent immediately. This covers also those maximum-length packets that have been `truncated' above. */ if (s->built_len > SSH_TLS_MAX_RECORD_LENGTH / 2) { SSH_DEBUG(6, ("Long packet, flush immediately.")); ssh_tls_flush(s); } return size; } void ssh_tls_stream_output_eof(void *context) { SshTlsProtocolState s = (SshTlsProtocolState)context; SSH_DEBUG(7, ("Got output eof from the upper layer.")); s->flags |= SSH_TLS_FLAG_OUTPUT_EOF; }
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; }
void ssh_decode_tty_flags(int fd, unsigned char *buf, size_t buf_len) { SshBuffer buffer; #ifdef USING_TERMIOS struct termios tio; #endif /* USING_TERMIOS */ #ifdef USING_SGTTY struct sgttyb tio; struct tchars tiotc; struct ltchars tioltc; int tiolm; #ifdef TIOCGSTAT struct tstatus tiots; #endif /* TIOCGSTAT */ #endif int opcode, baud; if (!isatty(fd)) { SSH_TRACE(2, ("Not a tty. (fd = %d)", fd)); return; } if (buf_len == 0) return; SSH_DEBUG_HEXDUMP(5, ("received tty-flags buffer"), buf, buf_len); ssh_buffer_init(&buffer); ssh_buffer_append(&buffer, buf, buf_len); /* Get old attributes for the terminal. We will modify these flags. I am hoping that if there are any machine-specific modes, they will initially have reasonable values. */ #ifdef USING_TERMIOS if (tcgetattr(fd, &tio) < 0) return; #endif /* USING_TERMIOS */ #ifdef USING_SGTTY if (ioctl(fd, TIOCGETP, &tio) < 0) return; if (ioctl(fd, TIOCGETC, &tiotc) < 0) return; if (ioctl(fd, TIOCLGET, &tiolm) < 0) return; if (ioctl(fd, TIOCGLTC, &tioltc) < 0) return; #ifdef TIOCGSTAT if (ioctl(fd, TIOCGSTAT, &tiots) < 0) return; #endif /* TIOCGSTAT */ #endif /* USING_SGTTY */ for (;;) { ssh_decode_buffer(&buffer, SSH_FORMAT_CHAR, &opcode, SSH_FORMAT_END); switch(opcode) { case TTY_OP_END: goto set; case TTY_OP_ISPEED: baud = GET_UINT32(); if (cfsetispeed(&tio, baud_to_speed(baud)) < 0) ssh_warning("cfsetispeed failed for %d", baud); break; case TTY_OP_OSPEED: baud = GET_UINT32(); if (cfsetospeed(&tio, baud_to_speed(baud)) < 0) ssh_warning("cfsetospeed failed for %d", baud); break; #ifdef USING_TERMIOS #define TTYCHAR(NAME, OP) \ case OP: \ tio.c_cc[NAME] = GET_UINT32(); \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ if (GET_UINT32()) \ tio.FIELD |= NAME; \ else \ tio.FIELD &= ~NAME; \ break; #define SGTTYCHAR(NAME, OP) #define SGTTYMODE(NAME, FIELD, OP) #define SGTTYMODEN(NAME, FIELD, OP) #endif /* USING_TERMIOS */ #ifdef USING_SGTTY #define TTYCHAR(NAME, OP) #define TTYMODE(NAME, FIELD, OP) #define SGTTYCHAR(NAME, OP) \ case OP: \ NAME = GET_UINT32(); \ break; #define SGTTYMODE(NAME, FIELD, OP) \ case OP: \ if (GET_UINT32()) \ FIELD |= NAME; \ else \ FIELD &= ~NAME; \ break; #define SGTTYMODEN(NAME, FIELD, OP) \ case OP: \ if (GET_UINT32()) \ FIELD &= ~NAME; \ else \ FIELD |= NAME; \ break; #endif /* USING_SGTTY */ #include "sshttyflagsi.h" #undef TTYCHAR #undef TTYMODE #undef SGTTYCHAR #undef SGTTYMODE #undef SGTTYMODEN default: SSH_TRACE(1, ("Ignoring unsupported tty mode opcode %d (0x%x)", opcode, opcode)); /* Opcodes 0 to 160 are defined to have a uint32 argument. */ if (opcode >= 0 && opcode < 160) { (void)GET_UINT32(); break; } /* It is a truly undefined opcode (160 to 255). We have no idea about its arguments. So we must stop parsing. Note that some data may be left in the packet; hopefully there is nothing more coming after the mode data. */ ssh_warning("ssh_decode_tty_flags: unknown opcode %d", opcode); goto set; } } set: /* Set the new modes for the terminal. */ #ifdef USING_TERMIOS if (tcsetattr(fd, TCSANOW, &tio) < 0) ssh_warning("Setting tty modes failed: %.100s", strerror(errno)); #endif /* USING_TERMIOS */ #ifdef USING_SGTTY /* termio's ECHOE is really both LCRTBS and LCRTERA - so wire them together */ if (tiolm & LCRTERA) tiolm |= LCRTBS; if (ioctl(fd, TIOCSETP, &tio) < 0 || ioctl(fd, TIOCSETC, &tiotc) < 0 || ioctl(fd, TIOCLSET, &tiolm) < 0 || ioctl(fd, TIOCSLTC, &tioltc) < 0 #ifdef TIOCSSTAT || ioctl(fd, TIOCSSTAT, &tiots) < 0 #endif /* TIOCSSTAT */ ) ssh_warning("Setting tty modes failed: %.100s", strerror(errno)); #endif /* USING_SGTTY */ }