void connect_callback(SshIpError status, SshStream stream, void *context) { Handler c; TestCase *testcase = context; SshTransportParams params; if (status != SSH_IP_OK) ssh_fatal("connect_callback: status %d", status); #ifdef DEBUG ssh_debug("connect successful"); #endif params = ssh_transport_create_params(); update_algs(params, testcase->c_to_s_algs); c = ssh_xcalloc(sizeof(*c), 1); c->stream = ssh_transport_client_wrap(stream, random_state, SSH_VERSION, testcase->service, params, SERVER_NAME, NULL, NULL, NULL, NULL); c->script = testcase->client_script; c->side = "client"; c->name = testcase->name; ssh_stream_set_callback(c->stream, handler_callback, (void *)c); client_handler = c; }
static void read_censor_list() { FILE *fp; char buf[1024]; fp = fopen(censor_file, "rb"); if (fp == NULL) { SSH_DEBUG(SSH_D_ERROR, ("could not open censor file `%s'", censor_file)); return; } while (fgets(buf, sizeof(buf), fp) != NULL) { char *cp; ProxyCensor *c = ssh_xcalloc(1, sizeof(*c)); cp = strchr(buf, '\n'); if (cp) *cp = '\0'; c->next = censor; censor = c; c->pattern = ssh_xstrdup(buf); } fclose(fp); }
Boolean ssh_channel_start_local_tcp_forward(SshCommon common, const char *address_to_bind, const char *port, const char *connect_to_host, const char *connect_to_port) { SshLocalTcpForward fwd; SshChannelTypeTcpDirect ct; long portnumber; SshUser user; SSH_DEBUG(5, ("requesting local forwarding for port %s to %s:%s", port, connect_to_host, connect_to_port)); portnumber = atol(port); user = ssh_user_initialize(NULL, FALSE); /* If user is not logged in as a privileged user, don't allow forwarding of privileged ports. */ if (portnumber < 1024) { if (ssh_user_uid(user)) { ssh_warning("Tried to forward " \ "privileged port %d as an ordinary user.", portnumber); return FALSE; } } if (portnumber >= 65536) { ssh_warning("Tried to forward " \ "port above 65535 (%d).", portnumber); return FALSE; } ct = ssh_channel_dtcp_ct(common); fwd = ssh_xcalloc(1, sizeof(*fwd)); fwd->common = common; fwd->listener = ssh_tcp_make_listener(address_to_bind, port, ssh_channel_dtcp_incoming_connection, (void *)fwd); if (!fwd->listener) { SSH_DEBUG(5, ("creating listener failed")); ssh_xfree(fwd); return FALSE; } fwd->port = ssh_xstrdup(port); fwd->connect_to_host = ssh_xstrdup(connect_to_host); fwd->connect_to_port = ssh_xstrdup(connect_to_port); fwd->next = ct->local_forwards; ct->local_forwards = fwd; return TRUE; }
void *ssh_channel_ftcp_create(SshCommon common) { SshChannelTypeTcpForward ct; ct = ssh_xcalloc(1, sizeof(*ct)); ct->common = common; return ct; }
void *ssh_channel_ssh1_agent_create(SshCommon common) { SshChannelTypeSsh1Agent ct; ct = ssh_xcalloc(1, sizeof(struct SshChannelTypeSsh1AgentRec)); ct->common = common; return ct; }
SshCondition ssh_xcondition_create (const char *name, SshUInt32 flags) { SshCondition cond; cond = ssh_xcalloc(1, sizeof(*cond)); if (name) cond->name = ssh_xstrdup(name); return cond; }
SshThread fork_thread(SshForkedFunc func, void *context) { SshThread thread; thread = ssh_xcalloc(1, sizeof(*thread)); if (pthread_create(&thread->thread, NULL, func, context) != 0) ssh_fatal("pthread_create failed : %s", strerror(errno)); return thread; }
void ssh_channel_ssh1_agent_session_create(SshCommon common, void **session_placeholder) { SshChannelSsh1AgentSession session; /* Allocate a session context. */ session = ssh_xcalloc(1, sizeof(*session)); session->common = common; *session_placeholder = (void *)session; }
void ssh_channel_ssh1_agent_open(const char *type, int channel_id, const unsigned char *data, size_t len, SshConnOpenCompletionProc completion, void *completion_context, void *context) { SshCommon common = (SshCommon)context; SshChannelTypeSsh1Agent ct; SshAgentConnection a; SSH_DEBUG(5, ("agent channel open request received")); ct = ssh_channel_ssh1_agent_ct(common); if (len != 0) { SSH_DEBUG(0, ("Bad agent channel open request")); (*completion)(SSH_OPEN_CONNECT_FAILED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } /* Do not allow agent opens at the server. */ if (!common->client) { ssh_warning("Refused attempted agent connection to server."); (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } /* Do not allow agent opens if we didn't request agent forwarding. */ if (!ct->agent_requested) { ssh_warning("Refused attempted agent connection when forwarding not requested."); (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } /* Create a context argument for connecting. */ a = ssh_xcalloc(1, sizeof(*a)); a->common = common; a->channel_id = channel_id; a->completion = completion; a->context = completion_context; /* Try to connect to the real agent. */ ssh_agenti_connect(ssh_channel_open_ssh1_agent_connected, TRUE, (void *)a); }
static SshInterceptorVirtualAdapterOp alloc_virtual_adapter_op(SshInterceptor interceptor) { SshInterceptorVirtualAdapterOp op = ssh_xcalloc(1, sizeof(*op)); ssh_mutex_lock(interceptor->mutex); op->id = interceptor->virtual_adapter_op_id++; op->next = interceptor->virtual_adapter_operations; interceptor->virtual_adapter_operations = op; ssh_mutex_unlock(interceptor->mutex); return op; }
void ssh_kernel_receive_virtual_adapter(SshPacketType type, const unsigned char *data, size_t len) { SshReceiveVaContext ctx; ctx = ssh_xcalloc(1, sizeof(*ctx)); ctx->type = type; ctx->data = data; ctx->len = len; ssh_threaded_mbox_send_to_thread(thread_mbox, wrapper_va_receive, ctx); }
void acc_encrypt_done(SshCryptoStatus status, const unsigned char *data, size_t length, void *context) { SshEKTestOp tc = context, ntc; SshExternalKeyTestCtx ctx = tc->test_ctx; SshPrivateKey key; SshUInt32 nanos; SshUInt64 secs; SshUInt32 s; ctx->operations_done++; ssh_time_measure_get_value(tc->timer, &secs, &nanos); s = (SshUInt32)secs; key = accelerator_test ? ctx->acc_prv_key : ctx->prv_key; ctx->accelerated_encrypts_pending--; SSH_DEBUG(2, ("Completed encrypt %d", tc->op_id)); SSH_DEBUG(3, ("Time %ds %dns", s, nanos)); ssh_time_measure_free(tc->timer); ssh_xfree(tc); SSH_DEBUG_HEXDUMP(7, ("Encrypted data of len %d:", length), data, length); if (status == SSH_CRYPTO_OK) { SSH_DEBUG(10, ("Got the data of len %d", length)); SSH_DEBUG(10, ("Accelerated encrypt succesfull")); ctx->accelerated_decrypts_pending++; ntc = ssh_xcalloc(1, sizeof(*ntc)); ntc->op_id = next_op_id++; ntc->test_ctx = ctx; ssh_private_key_decrypt_async(key, data, length, acc_decrypt_done, ntc); } else { SSH_DEBUG(1, ("Accelerated encrypt unsuccesfull")); ctx->operations_failed++; } }
/* separate (commandline)options from their parameters */ void ssh_split_arguments(int argc, char **argv, int *dest_ac, char ***dest_av) { int temp_ac = 0, i; char **temp_av; int alloc = argc + 1; temp_av = ssh_xcalloc(alloc, sizeof(char*)); /* count possible options and parameters */ for (i = 0; i < argc ; i++) { if ( alloc < temp_ac + 3) { alloc = temp_ac + 3; temp_av = ssh_xrealloc(temp_av, alloc*sizeof(char*)); } if (argv[i][0] == '-' || argv[i][0] == '+') { if(argv[i][1] && argv[i][2]) { temp_av[temp_ac] = ssh_xstrdup(argv[i]); temp_av[temp_ac][2] = '\0'; temp_av[++temp_ac] = ssh_xstrdup(argv[i] + 2); } else { temp_av[temp_ac] = ssh_xstrdup(argv[i]); } } else { temp_av[temp_ac] = ssh_xstrdup(argv[i]); } temp_ac++; } temp_av[ temp_ac ] = NULL; (*dest_ac) = temp_ac; (*dest_av) = temp_av; }
void ssh_channel_start_remote_tcp_forward(SshCommon common, const char *address_to_bind, const char *port, const char *connect_to_host, const char *connect_to_port, void (*completion)(Boolean ok, void *context), void *context) { SshRemoteTcpForward fwd; SshBuffer buffer; SshChannelTypeTcpForward ct; SSH_DEBUG(5, ("requesting remote forwarding for port %s", port)); ct = ssh_channel_ftcp_ct(common); /* Create a context for the forwarding. */ fwd = ssh_xcalloc(1, sizeof(*fwd)); fwd->common = common; fwd->address_to_bind = ssh_xstrdup(address_to_bind); fwd->port = ssh_xstrdup(port); fwd->connect_to_host = ssh_xstrdup(connect_to_host); fwd->connect_to_port = ssh_xstrdup(connect_to_port); /* Add it to the list of remote forwardings. */ fwd->next = ct->remote_forwards; ct->remote_forwards = fwd; /* Send a forwarding request to the remote side. */ ssh_buffer_init(&buffer); ssh_encode_buffer(&buffer, SSH_FORMAT_UINT32_STR, address_to_bind, strlen(address_to_bind), SSH_FORMAT_UINT32, (SshUInt32) atol(port), SSH_FORMAT_END); ssh_conn_send_global_request(common->conn, "tcpip-forward", ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer), completion, context); ssh_buffer_uninit(&buffer); }
void listener_callback(SshIpError status, SshStream stream, void *context) { SshPrivateKey private_host_key, private_server_key; unsigned char *blob; unsigned int blob_len = 0; Handler c; TestCase *testcase = context; SshTransportParams params; if (status != SSH_IP_NEW_CONNECTION) ssh_fatal("listener_callback: status %d", status); #ifdef DEBUG ssh_debug("listener: new connection"); #endif create_server_keys(&private_host_key, &private_server_key, &blob, &blob_len); params = ssh_transport_create_params(); update_algs(params, testcase->s_to_c_algs); c = ssh_xcalloc(sizeof(*c), 1); c->stream = ssh_transport_server_wrap(stream, random_state, SSH_VERSION, params, private_host_key, private_server_key, blob, blob_len, NULL, NULL); ssh_private_key_free(private_host_key); ssh_private_key_free(private_server_key); ssh_xfree(blob); c->script = testcase->server_script; c->side = "server"; c->name = testcase->name; ssh_stream_set_callback(c->stream, handler_callback, (void *)c); server_handler = c; ssh_tcp_destroy_listener(listener); }
/* Return application level compatibility flags. Note that this must not be called if tr has become invalid for some reason. The return struct should be freed by the caller, when it is no longer needed. */ void ssh_transport_get_compatibility_flags(SshStream stream, SshTransportCompat *compat_flags) { SshTransportCommon tr; SshTransportCompat rec; /* Verify that this is a transport stream. */ if (ssh_stream_get_methods(stream) != &ssh_tr_methods) { memset(compat_flags, 0, sizeof(*compat_flags)); return; } /* Get the real object. */ tr = (SshTransportCommon)ssh_stream_get_context(stream); rec = ssh_xcalloc(1, sizeof(*rec)); rec->publickey_draft_incompatility = &(tr->ssh_old_publickey_bug_compat); *compat_flags = rec; }
SshPacketWrapper ssh_packet_wrap(SshStream down_stream, SshPacketReceiveProc received_packet, SshPacketEofProc received_eof, SshPacketCanSendProc can_send, void *context) { SshPacketWrapper down; down = ssh_xcalloc(1, sizeof(*down)); down->stream = down_stream; ssh_buffer_init(&down->incoming); ssh_buffer_init(&down->outgoing); ssh_buffer_init(&down->outgoing_packet); down->incoming_eof = FALSE; down->outgoing_eof = FALSE; down->send_blocked = TRUE; down->can_receive = FALSE; down->destroy_pending = FALSE; down->cannot_destroy = FALSE; down->destroy_requested = FALSE; down->shortcircuited = FALSE; /* Save the callback functions. */ down->received_packet = received_packet; down->received_eof = received_eof; down->can_send = can_send; down->context = context; /* Set callback for the downward stream. Note that this will also cause can_send to be called from the output callback. */ ssh_stream_set_callback(down->stream, ssh_packet_wrapper_callback, (void *)down); /* Enable receives. */ ssh_packet_wrapper_can_receive(down, TRUE); return down; }
/* Test to encrypt with the accelerated public key */ void test_acc_public_key(void *context) { SshExternalKeyTestCtx ctx = context; SshEKTestOp test_ctx = ssh_xcalloc(1, sizeof(*test_ctx)); SshPublicKey key; unsigned char *data = ctx->big_buf; size_t data_len = ctx->big_buf_len; key = accelerator_test ? ctx->acc_pub_key : ctx->pub_key; test_ctx->op_id = next_op_id++; test_ctx->test_ctx = ctx; test_ctx->timer = ssh_time_measure_allocate(); ssh_time_measure_start(test_ctx->timer); ctx->accelerated_encrypts_pending++; ctx->accelerated_encrypts_left--; ssh_public_key_encrypt_async(key, data, data_len, acc_encrypt_done, test_ctx); SSH_DEBUG_HEXDUMP(7, ("Encrypting data of len %d:", data_len), data, data_len); if (ctx->accelerated_encrypts_left || continuous_test) { ssh_xregister_timeout(0, timeout_ms * 1000, test_acc_public_key, ctx); } else { SSH_DEBUG(2, ("All the encrypts send")); } SSH_DEBUG(2, ("Encrypts left %d, pending %d", ctx->accelerated_encrypts_left, ctx->accelerated_encrypts_pending)); }
int main(int argc, char **argv) { SshExternalKeyTestCtx test_ctx; int i; SshPrivateKey prv_key; SshPublicKey pub_key; SshMPInteger n; parse_arguments(argc, argv); ssh_pk_provider_register(&ssh_pk_if_modn_generator); /* Initialize the event loop and the test context. */ ssh_event_loop_initialize(); ssh_debug_set_level_string(debug_level_string); ssh_global_init(); /* Initialize the crypto library. */ if (ssh_crypto_library_initialize() != SSH_CRYPTO_OK) ssh_fatal("Cannot initialize the crypto library"); test_ctx = ssh_xcalloc(1, sizeof(*test_ctx)); test_ctx->accelerated_encrypts_left = default_accelerated_encrypts; test_ctx->timer = ssh_time_measure_allocate(); SSH_DEBUG(3, ("Reading the test key. Please wait....")); prv_key = get_prv_key("accelerator-test.prv"); if (ssh_private_key_select_scheme(prv_key, SSH_PKF_ENCRYPT, "rsa-none-none", SSH_PKF_END) != SSH_CRYPTO_OK) ssh_fatal("Could not select the scheme for private key"); if (ssh_private_key_derive_public_key(prv_key, &pub_key) != SSH_CRYPTO_OK) { ssh_fatal("Can not derive a public key from a " "stored private key"); } if (ssh_public_key_select_scheme(pub_key, SSH_PKF_ENCRYPT, "rsa-none-none", SSH_PKF_END) != SSH_CRYPTO_OK) ssh_fatal("Could not select the scheme for public key"); n = ssh_mprz_malloc(); /* Get information about the RSA key. E and N are needed for nFast. */ if (ssh_public_key_get_info(pub_key, SSH_PKF_MODULO_N, n, SSH_PKF_END) != SSH_CRYPTO_OK) { return FALSE; } #if 0 n_bytes = (ssh_mprz_get_size(n, 2) + 7) / 8; if (n_bytes == 0 || (n_bytes & 3) != 0) n_bytes += (4 - (n_bytes & 3)); test_ctx->big_buf = ssh_xmalloc(n_bytes); test_ctx->big_buf_len = n_bytes; ssh_mprz_get_buf(test_ctx->big_buf, test_ctx->big_buf_len, n); ssh_mprz_free(n); test_ctx->big_buf_len = 128; test_ctx->big_buf[0] = 1; #else #if 0 n_bytes = ssh_mprz_get_size(n, 8); test_ctx->big_buf = ssh_xmalloc(n_bytes); test_ctx->big_buf_len = n_bytes; ssh_mprz_init(&r); ssh_mprz_rand(&r, n_bytes * 8); ssh_mprz_mod(&r, &r, n); ssh_mprz_get_buf(test_ctx->big_buf, test_ctx->big_buf_len, &r); ssh_mprz_free(n); ssh_mprz_clear(&r); #else test_ctx->big_buf = ssh_xmalloc(129); test_ctx->big_buf_len = 129; memcpy(test_ctx->big_buf, "\x00\x50\xe7\x85\x86\x40\xf8\x9b" "\xb8\xeb\x19\x64\xd8\x51\x33\xd7" "\x4f\xac\x32\x5d\x03\x66\x3d\x0c" "\xbe\xfd\x40\x29\x82\xb7\x61\x09" "\x15\x37\x4f\xe1\xd0\x57\xb0\x6d" "\x16\x49\x73\x25\x20\x3d\xa8\xfa" "\xf6\xb4\x72\xec\x75\xc8\x42\xc7" "\x99\x64\x63\x23\x29\xe0\x65\xa1" "\x2a\xc2\xb7\xf1\x5b\xb4\x9b\x30" "\xdb\xc7\x22\xb9\xf9\xde\xb5\x09" "\xb5\xe0\x0a\xca\xc5\xf9\xaf\x8f" "\x54\xf2\x9a\x06\x2b\xc1\xc2\x65" "\x87\xb3\xd5\xec\xd3\x8a\x2f\xa7" "\x5f\x69\x34\xe7\x7f\xeb\xaf\x56" "\x3c\x3d\x71\x3f\x73\xba\x8b\xa7" "\xd3\xe5\x6d\x98\xc8\x01\x6b\x18" "\x14", 129); #endif #endif test_ctx->pub_key = pub_key; test_ctx->prv_key = prv_key; test_ek_add(test_ctx); #ifndef WIN32 ssh_register_signal(SIGUSR1, test_signal_handler, test_ctx); #endif ssh_event_loop_run(); /* Uninitialize. */ for (i = 0; i < test_ctx->num_prv_keys; i++) ssh_private_key_free(test_ctx->prv_keys[i]); for (i = 0; i < test_ctx->num_pub_keys; i++) ssh_public_key_free(test_ctx->pub_keys[i]); ssh_xfree(test_ctx->prv_keys); ssh_xfree(test_ctx->pub_keys); ssh_xfree(test_ctx); return 0; }
Boolean ssh_channel_remote_tcp_forward_request(const char *type, const unsigned char *data, size_t len, void *context) { SshCommon common = (SshCommon)context; char *address_to_bind; SshUInt32 port; char port_string[20]; SshRemoteTcpForward fwd; SshChannelTypeTcpForward ct; SSH_DEBUG(5, ("remote TCP/IP forwarding request received")); ssh_log_event(common->config->log_facility, SSH_LOG_INFORMATIONAL, "Remote TCP/IP forwarding request received from host \"%s\", "\ "by authenticated user \"%s\".", common->remote_host, ssh_user_name(common->user_data)); ct = ssh_channel_ftcp_ct(common); /* Don't allow a server to send remote forwarding requests to the client. */ if (common->client) { ssh_warning("Remote TCP/IP forwarding request from server denied."); return FALSE; } /* Parse the request. */ if (ssh_decode_array(data, len, SSH_FORMAT_UINT32_STR, &address_to_bind, NULL, SSH_FORMAT_UINT32, &port, SSH_FORMAT_END) != len) { SSH_DEBUG(0, ("bad data")); return FALSE; } /* Convert port number to a string. */ snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port); /* If user is not logged in as a privileged user, don't allow forwarding of privileged ports. */ if (port < 1024) { if (ssh_user_uid(common->user_data)) { SSH_TRACE(2, ("User \"%s\" not root, tried to forward " \ "privileged port %ld.", ssh_user_name(common->user_data), (unsigned long) port)); ssh_log_event(common->config->log_facility, SSH_LOG_WARNING, "User \"%s\" not root, tried to forward " \ "privileged port %ld.", ssh_user_name(common->user_data), (unsigned long) port); return FALSE; } else { ssh_log_event(common->config->log_facility, SSH_LOG_NOTICE, "Privileged user \"%s\" forwarding a privileged port.", ssh_user_name(common->user_data)); } } if (port >= 65536) { SSH_TRACE(2, ("User \"%s\" tried to forward " \ "port above 65535 (%ld).", ssh_user_name(common->user_data), (unsigned long) port)); ssh_log_event(common->config->log_facility, SSH_LOG_WARNING, "User \"%s\" tried to forward " \ "port above 65535 (%ld).", ssh_user_name(common->user_data), (unsigned long) port); return FALSE; } /* Create a socket listener. */ fwd = ssh_xcalloc(1, sizeof(*fwd)); fwd->listener = ssh_tcp_make_listener(address_to_bind, port_string, ssh_channel_ftcp_incoming_connection, (void *)fwd); if (fwd->listener == NULL) { ssh_debug("Creating remote listener for %s:%s failed.", address_to_bind, port_string); ssh_log_event(common->config->log_facility, SSH_LOG_NOTICE, "Creating remote listener for %s:%s failed.", address_to_bind, port_string); ssh_xfree(address_to_bind); ssh_xfree(fwd); return FALSE; } /* Fill the remaining fields. */ fwd->common = common; fwd->address_to_bind = address_to_bind; fwd->port = ssh_xstrdup(port_string); fwd->connect_to_host = NULL; fwd->connect_to_port = NULL; /* Add to list of forwardings. */ fwd->next = ct->remote_forwards; ct->remote_forwards = fwd; ssh_log_event(common->config->log_facility, SSH_LOG_INFORMATIONAL, "Port %ld set up for remote forwarding.", (unsigned long) port); return TRUE; }
void ssh_channel_dtcp_open_request(const char *type, int channel_id, const unsigned char *data, size_t len, SshConnOpenCompletionProc completion, void *completion_context, void *context) { SshCommon common = (SshCommon)context; char *connect_to_host, connect_to_port[20], *originator_ip; SshUInt32 port, originator_port; SshDirectTcp tcp; SSH_DEBUG(5, ("direct TCP/IP channel open request")); /* Parse packet data. */ if (ssh_decode_array(data, len, SSH_FORMAT_UINT32_STR, &connect_to_host, NULL, SSH_FORMAT_UINT32, &port, SSH_FORMAT_UINT32_STR, &originator_ip, NULL, SSH_FORMAT_UINT32, &originator_port, SSH_FORMAT_END) != len) { /* XXX disconnect? */ SSH_DEBUG(0, ("bad data")); (*completion)(SSH_OPEN_RESOURCE_SHORTAGE, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } /* We do not currently allow direct connections from server to client. */ if (common->client) { ssh_warning("Direct TCP/IP connection request from server " "to %s:%ld denied.", connect_to_host, (long)port); /* Free dynamically allocated data. */ ssh_xfree(originator_ip); ssh_xfree(connect_to_host); (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } /* Convert port number to string. */ snprintf(connect_to_port, sizeof(connect_to_port), "%ld", (long) port); ssh_debug("Direct TCP/IP connect to %s:%s from %s:%ld", connect_to_host, connect_to_port, originator_ip, (long)originator_port); /* Save data for callback. */ tcp = ssh_xcalloc(1, sizeof(*tcp)); tcp->common = common; tcp->channel_id = channel_id; tcp->completion = completion; tcp->completion_context = completion_context; /* Connect to the given host/port. */ ssh_tcp_connect_with_socks(connect_to_host, connect_to_port, NULL, 1, ssh_channel_dtcp_connected, (void *)tcp); /* Free dynamically allocated data. */ ssh_xfree(originator_ip); ssh_xfree(connect_to_host); }
void ssh_channel_ftcp_open_request(const char *type, int channel_id, const unsigned char *data, size_t len, SshConnOpenCompletionProc completion, void *completion_context, void *context) { SshCommon common = (SshCommon)context; SshUInt32 port, originator_port; char *address_to_bind, *originator_ip; char port_string[20]; SshRemoteTcpForward fwd; SshChannelTcpFwdConnect c; SshChannelTypeTcpForward ct; SSH_DEBUG(5, ("open request for remote forwarded TCP/IP channel")); ct = ssh_channel_ftcp_ct(common); if (ssh_decode_array(data, len, SSH_FORMAT_UINT32_STR, &address_to_bind, NULL, SSH_FORMAT_UINT32, &port, SSH_FORMAT_UINT32_STR, &originator_ip, NULL, SSH_FORMAT_UINT32, &originator_port, SSH_FORMAT_END) != len) { /* XXX should disconnect? */ SSH_DEBUG(0, ("bad data")); (*completion)(SSH_OPEN_RESOURCE_SHORTAGE, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); return; } snprintf(port_string, sizeof(port_string), "%ld", (long) port); ssh_debug("Received remote TCP/IP forward connect for port %s from %s:%ld", port_string, originator_ip, (long)originator_port); for (fwd = ct->remote_forwards; fwd; fwd = fwd->next) if (strcmp(fwd->address_to_bind, address_to_bind) == 0 && strcmp(fwd->port, port_string) == 0) { c = ssh_xcalloc(1, sizeof(*c)); c->fwd = fwd; c->channel_id = channel_id; c->completion = completion; c->completion_context = completion_context; ssh_tcp_connect_with_socks(fwd->connect_to_host, fwd->connect_to_port, NULL, 1, ssh_channel_ftcp_open_connected, (void *)c); ssh_xfree(address_to_bind); ssh_xfree(originator_ip); return; } ssh_warning("Received remote TCP/IP connect for non-forwarded port %s from %s:%ld", port_string, originator_ip, (long)originator_port); ssh_xfree(address_to_bind); ssh_xfree(originator_ip); (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, completion_context); }
SshPipeStatus ssh_pipe_create_and_fork(SshStream *stdio_return, SshStream *stderr_return) { int pin[2], pout[2], perr[2]; pid_t pid; SshPipeStream pipes; if (pipe(pin) < 0) return SSH_PIPE_ERROR; if (pipe(pout) < 0) { close(pin[0]); close(pin[1]); return SSH_PIPE_ERROR; } if (stderr_return != NULL && pipe(perr) < 0) { close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); return SSH_PIPE_ERROR; } /* Initialize SIGCHLD handling. This will ensure the SIGCHLD won't get delivered until we register the handler for the new process below. */ ssh_sigchld_initialize(); /* Fork a child process. */ pid = fork(); if (pid < 0) { ssh_warning("Fork failed: %s", strerror(errno)); close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); if (stderr_return != NULL) { close(perr[0]); close(perr[1]); } return SSH_PIPE_ERROR; } /* The remaining processing depends on whether we are the parent or the child. */ if (pid == 0) { /* Redirect stdin. */ close(pin[1]); if (dup2(pin[0], 0) < 0) perror("dup2 stdin"); close(pin[0]); /* Redirect stdout. */ close(pout[0]); if (dup2(pout[1], 1) < 0) perror("dup2 stdout"); close(pout[1]); if (stderr_return != NULL) { /* Redirect stderr. */ close(perr[0]); if (dup2(perr[1], 2) < 0) perror("dup2 stderr"); close(perr[1]); } *stdio_return = NULL; if (stderr_return != NULL) *stderr_return = NULL; return SSH_PIPE_CHILD_OK; } /* Parent */ pipes = ssh_xcalloc(sizeof(*pipes), 1); pipes->pid = pid; pipes->callback = NULL; pipes->callback_context = NULL; pipes->status_returned = FALSE; pipes->exit_status = -1; /* Close the child-side file descriptors. */ close(pin[0]); close(pout[1]); if (stderr_return != NULL) close(perr[1]); /* Register a handler for SIGCHLD for our new child. */ ssh_sigchld_register(pid, ssh_pipe_sigchld_handler, (void *)pipes); /* Wrap the master fd into a stream. */ pipes->stdio_stream = ssh_stream_fd_wrap2(pout[0], pin[1], TRUE); *stdio_return = ssh_stream_create(&ssh_pipe_methods, (void *) pipes); /* Create the stderr stream if requested. */ /* XXX should another context (errpipes?) be allocated for this, so that this, too, could be created as above?*/ if (stderr_return != NULL) *stderr_return = ssh_stream_fd_wrap(perr[0], TRUE); return SSH_PIPE_PARENT_OK; }
/* The URI handler. */ static Boolean proxy_handler(SshHttpServerContext ctx, SshHttpServerConnection conn, SshStream stream, void *context) { const char *method = ssh_http_server_get_method(conn); const char *uri = ssh_http_server_get_uri(conn); SshHttpClientParams params; ProxyRequest *req; SshBuffer error; ProxyCensor *c; SSH_DEBUG(SSH_D_HIGHSTART, ("method=%s, uri=%s", method, uri)); for (c = censor; c; c = c->next) if (ssh_match_pattern(uri, c->pattern)) { SSH_DEBUG(SSH_D_HIGHSTART, ("censored by pattern `%s'", c->pattern)); ssh_http_server_error(conn, 301, SSH_HTTP_HDR_LOCATION, "http://people.ssh.fi/mtr/censor.jpg", SSH_HTTP_HDR_FIELD, "Content-Type", "text/html", SSH_HTTP_HDR_END); ssh_stream_destroy(stream); return TRUE; } memset(¶ms, 0, sizeof(params)); params.http_proxy_url = proxy_url; params.num_redirections = 0; req = ssh_xcalloc(1, sizeof(*req)); req->server = ctx; req->conn = conn; req->server_stream = stream; req->client = ssh_http_client_init(¶ms); if (strcmp(method, "GET") == 0) ssh_http_get(req->client, uri, result_callback, req, SSH_HTTP_HDR_END); else if (strcmp(method, "HEAD") == 0) ssh_http_head(req->client, uri, result_callback, req, SSH_HTTP_HDR_END); else if (strcmp(method, "POST") == 0 || strcmp(method, "PUT") == 0) { SSH_DEBUG(SSH_D_ERROR, ("%s not implemented yet", method)); ssh_xfree(req); error = ssh_buffer_allocate(); ssh_buffer_append_cstrs(error, "<body><h1>Method `", method, "' not implemented yet</h1>\n", NULL); ssh_http_server_send_buffer(conn, error); } else { SSH_DEBUG(SSH_D_ERROR, ("unknown method `%s'", method)); ssh_xfree(req); error = ssh_buffer_allocate(); ssh_buffer_append_cstrs(error, "<body><h1>Unknown method `", method, "'</h1>\n", NULL); ssh_http_server_send_buffer(conn, error); } return TRUE; }
int main(int ac, char **av) { int opt, i; DIR *ssh2dir = NULL; char *ssh2dirname; Boolean dynamic_array = FALSE; struct dirent * cand; /* Save program name. */ if (strchr(av[0], '/')) av0 = strrchr(av[0], '/') + 1; else av0 = av[0]; user = ssh_user_initialize(NULL, FALSE); #ifdef WITH_PGP pgp_keyring = ssh_xstrdup(SSH_PGP_SECRET_KEY_FILE); #endif /* WITH_PGP */ action = ADD; while ((opt = ssh_getopt(ac, av, "ldDput:f:F:1LUNPI", NULL)) != EOF) { if (!ssh_optval) { usage(); exit(EXIT_STATUS_ERROR); } switch (opt) { case 'N': #ifdef WITH_PGP pgp_mode = PGP_KEY_NAME; #else /* WITH_PGP */ fprintf(stderr, "%s: PGP keys not supported.\n", av0); exit(EXIT_STATUS_ERROR); #endif /* WITH_PGP */ break; case 'P': #ifdef WITH_PGP pgp_mode = PGP_KEY_FINGERPRINT; #else /* WITH_PGP */ fprintf(stderr, "%s: PGP keys not supported.\n", av0); exit(EXIT_STATUS_ERROR); #endif /* WITH_PGP */ break; case 'I': #ifdef WITH_PGP pgp_mode = PGP_KEY_ID; #else /* WITH_PGP */ fprintf(stderr, "%s: PGP keys not supported.\n", av0); exit(EXIT_STATUS_ERROR); #endif /* WITH_PGP */ break; case 'R': #ifdef WITH_PGP ssh_xfree(pgp_keyring); pgp_keyring = ssh_xstrdup(ssh_optarg); #else /* WITH_PGP */ fprintf(stderr, "%s: PGP keys not supported.\n", av0); exit(EXIT_STATUS_ERROR); #endif /* WITH_PGP */ break; case 'l': action = LIST; break; case 'p': use_stdin = TRUE; break; case 'd': if (action == ADD_URL) action = DELETE_URL; else action = DELETE; break; case 'D': action = DELETE_ALL; break; case 't': if (ssh_optargnum) { key_timeout = (SshTime)(ssh_optargval * 60); } else { usage(); exit(EXIT_STATUS_ERROR); } have_attrs = TRUE; break; case 'f': if (ssh_optargnum) { path_limit = (SshUInt32)ssh_optargval; } else { usage(); exit(EXIT_STATUS_ERROR); } have_attrs = TRUE; break; case 'F': path_constraint = ssh_xstrdup(ssh_optarg); have_attrs = TRUE; break; case '1': forbid_compat = TRUE; have_attrs = TRUE; break; case 'u': if (action == DELETE) action = DELETE_URL; else action = ADD_URL; break; case 'L': action = LOCK; break; case 'U': action = UNLOCK; break; default: usage(); exit(EXIT_STATUS_ERROR); } } #ifdef WITH_PGP if (pgp_keyring[0] != '/') { char buf[1024]; snprintf(buf, sizeof (buf), "%s/%s/%s", ssh_user_dir(user), SSH_USER_DIR, pgp_keyring); ssh_xfree(pgp_keyring); pgp_keyring = ssh_xstrdup(buf); } #endif /* WITH_PGP */ files = &av[ssh_optind]; num_files = ac - ssh_optind; /* Fetch default from ~/.ssh2/id_* (the first that we happen to get) */ #define ID_PREFIX "id" if (num_files == 0 && action != LIST && action != DELETE_ALL && action != LOCK && action != UNLOCK) { #ifdef WITH_PGP if (pgp_mode != PGP_KEY_NONE) { fprintf(stderr, "%s: Nothing to do!\n", av0); exit(EXIT_STATUS_ERROR); } #endif /* WITH_PGP */ ssh_dsprintf(&ssh2dirname, "%s/%s", ssh_user_dir(user), SSH_USER_DIR); ssh2dir = opendir(ssh2dirname); if (!ssh2dir) { fprintf(stderr, "%s: Can't open directory \"%s\"", av0, ssh2dirname); exit(EXIT_STATUS_ERROR); } while ((cand = readdir(ssh2dir)) != NULL) { if ((strlen(cand->d_name) > strlen(ID_PREFIX)) && (strncmp(cand->d_name, ID_PREFIX, strlen(ID_PREFIX)) == 0) && ((strlen(cand->d_name) < 4) || (strcmp(cand->d_name + strlen(cand->d_name) - 4, ".pub") != 0)) && ((((cand->d_name)[strlen(ID_PREFIX)]) == '_') || (((cand->d_name)[strlen(ID_PREFIX)]) == '-') || (((cand->d_name)[strlen(ID_PREFIX)]) == '.') || (((cand->d_name)[strlen(ID_PREFIX)]) == '(') || (((cand->d_name)[strlen(ID_PREFIX)]) == '[') || (((cand->d_name)[strlen(ID_PREFIX)]) == '<') || (((cand->d_name)[strlen(ID_PREFIX)]) == '>'))) { files = ssh_xcalloc(2, sizeof(char *)); ssh_dsprintf(&files[0], "%s/%s", ssh2dirname, cand->d_name); ssh_xfree(ssh2dirname); num_files++; dynamic_array = TRUE; break; } } (void)closedir(ssh2dir); } signal(SIGPIPE, SIG_IGN); ssh_event_loop_initialize(); ssh_agent_open(agent_open_callback, NULL); ssh_event_loop_run(); ssh_event_loop_uninitialize(); if (dynamic_array) { for(i = 0; i < num_files ; i++) { ssh_xfree(files[i]); } ssh_xfree(files); } ssh_user_free(user, FALSE); exit(EXIT_STATUS_OK); }
SshServer ssh_server_wrap(SshStream stream, SshConfig config, SshRandomState random_state, SshPrivateKey private_server_key, SshServerDisconnectProc disconnect, SshServerDebugProc debug, SshVersionCallback version_check, SshAuthPolicyProc auth_policy_proc, SshCommonAuthenticatedNotify authenticated_notify, void *context) { SshServer server; SshStream trans, auth; SshTransportParams params; /* Create parameters. */ params = ssh_transport_create_params(); if (!ssh_server_update_transport_params(config, params)) { ssh_stream_destroy(stream); ssh_transport_destroy_params(params); return NULL; } /* Check the host key. */ if (config->private_host_key == NULL || config->public_host_key_blob == NULL) ssh_fatal("ssh_server_wrap: no host key !"); /* Create the server object. */ server = ssh_xcalloc(1, sizeof(*server)); server->config = config; /* Create a transport layer protocol object. */ ssh_debug("ssh_server_wrap: creating transport protocol"); trans = ssh_transport_server_wrap(stream, random_state, SSH2_PROTOCOL_VERSION_STRING, params, config->private_host_key, private_server_key, config->public_host_key_blob, config->public_host_key_blob_len, version_check, (void *)context); ssh_transport_get_compatibility_flags(trans, &server->compat_flags); /* Create the authentication methods array for the server. */ server->methods = ssh_server_authentication_initialize(); /* XXX config data */ /* Create an authentication protocol object. */ ssh_debug("ssh_server_wrap: creating userauth protocol"); /* XXX policy_proc */ auth = ssh_auth_server_wrap(trans, auth_policy_proc, (void *)server, server->methods, (void *)server); /* Create the common part of client/server objects. */ server->common = ssh_common_wrap(stream, auth, FALSE, config, random_state, NULL, disconnect, debug, authenticated_notify, context); if (server->common == NULL) { ssh_server_authentication_uninitialize(server->methods); ssh_xfree(server); return NULL; } return server; }
static void receive_virtual_adapter_attach_cb(SshInterceptor interceptor, SshVirtualAdapterError error, SshInterceptorIfnum adapter_ifnum, unsigned char *adapter_name, SshVirtualAdapterState adapter_state, SshInterceptorVirtualAdapterOp op) { SshInterceptorVirtualAdapter va; /* Is the operation aborted? */ if (op->aborted) { /* The operation was successful but aborted. Let's just destroy the created adapter. */ if (error == SSH_VIRTUAL_ADAPTER_ERROR_OK) ssh_virtual_adapter_detach(interceptor, adapter_ifnum, NULL_FNPTR, NULL); /* Destroy the adapter context */ if (op->detach_cb) (*op->detach_cb)(op->adapter_context); /* Free operation context. */ free_virtual_adapter_op(interceptor, op); return; } if (error == SSH_VIRTUAL_ADAPTER_ERROR_OK) { /* Register that we know this virtual adapter. */ va = ssh_xcalloc(1, sizeof(*va)); va->adapter_ifnum = adapter_ifnum; va->packet_cb = op->packet_cb; va->detach_cb = op->detach_cb; va->adapter_context = op->adapter_context; ssh_mutex_lock(interceptor->mutex); va->next = interceptor->virtual_adapters; interceptor->virtual_adapters = va; ssh_mutex_unlock(interceptor->mutex); } else { /* Destroy the context if not successful */ if (op->detach_cb) (*op->detach_cb)(op->adapter_context); op->adapter_context = NULL; } SSH_DEBUG(SSH_D_NICETOKNOW, ("received attach callback for virtual adapter %d from forwarder, " "error %d", (int) adapter_ifnum, (int) error)); /* Call the completion function. */ if (op->status_cb) (*op->status_cb)((SshVirtualAdapterError) error, (SshInterceptorIfnum) adapter_ifnum, adapter_name, (SshVirtualAdapterState) adapter_state, op->adapter_context, op->context); /* Unregister operation handle and free operation context. */ ssh_operation_unregister(op->handle); free_virtual_adapter_op(interceptor, op); }
void signer_received_packet(SshPacketType type, const unsigned char *data, size_t len, void *context) { /* Received. */ unsigned int msg_byte; /* This is unsigned int because SSH_FORMAT_CHAR expects uint; caused a rather nasty bug during development (I used SshUInt8, which wasn't long enough => ssh_decode_array blew the stack).*/ char *userauth_str, *hostbased_str, *recv_pubkey_alg, *recv_hostname; char *recv_username; unsigned char *recv_pubkeyblob; size_t recv_pubkeyblob_len; /* Dug up by us. */ char *pubkey_alg, *hostname, *username; unsigned char *pubkeyblob; size_t pubkeyblob_len; size_t hostname_len; /* Internal stuff*/ SshSigner signer = (SshSigner) context; char hostkeyfile[512]; char *comment; SshPrivateKey privkey; size_t sig_len, length_return; unsigned char *signature_buffer; SshCryptoStatus result; SshUser real_user; SSH_TRACE(2, ("Packet received.")); switch(type) { case SSH_AUTH_HOSTBASED_PACKET: /* Check packet out, and if it's ok, sign it and send signature to ssh2. */ #ifdef HEXDUMPS SSH_DEBUG_HEXDUMP(3, ("packet:"), \ data, len); #endif /* HEXDUMPS */ if (ssh_decode_array(data, len, /* session id */ SSH_FORMAT_UINT32_STR, NULL, NULL, /* SSH_MSG_USERAUTH_REQUEST (must be checked)*/ SSH_FORMAT_CHAR, &msg_byte, /* user name */ SSH_FORMAT_UINT32_STR, NULL, NULL, /* service "ssh-userauth" (must be checked)*/ SSH_FORMAT_UINT32_STR, &userauth_str, NULL, /* "hostbased" (must be checked)*/ SSH_FORMAT_UINT32_STR, &hostbased_str, NULL, /* public key algorithm for hostkey (must be checked)*/ SSH_FORMAT_UINT32_STR, &recv_pubkey_alg, NULL, /* public hostkey and certificates (must be checked)*/ SSH_FORMAT_UINT32_STR, &recv_pubkeyblob, &recv_pubkeyblob_len, /* client host name (must be checked)*/ SSH_FORMAT_UINT32_STR, &recv_hostname, NULL, /* user name on client host (must be checked) */ SSH_FORMAT_UINT32_STR, &recv_username, NULL, SSH_FORMAT_END) != len || len == 0) { /* There was an error. */ SSH_TRACE(0, ("Invalid packet.")); goto error; } /* Get pubkeyblob, pubkeyblob_len, pubkey_alg, hostname and username. */ /* Dig up hosts publickey. */ if(signer->config->public_host_key_file[0] != '/') { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR, signer->config->public_host_key_file); } else { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s", signer->config->public_host_key_file); } SSH_TRACE(2, ("place to look for public key: %s", hostkeyfile)); /* This pubkey*-stuff is for the client _host's_ public hostkey. */ /* Getting pubkeyblob, pubkeyblob_len */ SSH_DEBUG(4, ("Reading pubkey-blob from %s...", hostkeyfile)); if (ssh2_key_blob_read(signer->effective_user_data, hostkeyfile, NULL, &pubkeyblob, &pubkeyblob_len, NULL) != SSH_KEY_MAGIC_PUBLIC) { SSH_TRACE(1, ("Reading public key failed.")); goto error; } SSH_DEBUG(4, ("done.")); if ((pubkey_alg = ssh_pubkeyblob_type(pubkeyblob, pubkeyblob_len)) == NULL) { SSH_TRACE(1, ("Couldn't figure out public key algorithm.")); goto error; } /* Getting hostname. */ hostname = ssh_xmalloc(MAXHOSTNAMELEN + 1); ssh_tcp_get_host_name(hostname, MAXHOSTNAMELEN + 1); hostname_len = strlen(hostname); /* Sanity check */ SSH_ASSERT(hostname_len + 2 < MAXHOSTNAMELEN); /* We want FQDN. */ hostname[hostname_len] = '.'; hostname[hostname_len + 1] = '\0'; /* Getting username. */ real_user = ssh_user_initialize(NULL, FALSE); username = ssh_xstrdup(ssh_user_name(real_user)); ssh_user_free(real_user, FALSE); /* Check all parameters. */ if (msg_byte != SSH_MSG_USERAUTH_REQUEST) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("msg_byte != SSH_MSG_USERAUTH_REQUEST " \ "(msg_byte = %d)", msg_byte)); goto error; } if (strcmp(userauth_str, SSH_USERAUTH_SERVICE) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("userauth_str != \"ssh-userauth\" (it was '%s')", \ userauth_str)); goto error; } if (strcmp(hostbased_str, SSH_AUTH_HOSTBASED) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("hostbased_str != \"hostbased\" (it was '%s')", \ hostbased_str)); goto error; } /* XXX has to be change when adding support for multiple hostkeys */ if (strcmp(recv_pubkey_alg, pubkey_alg) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("Client gave us invalid pubkey-algorithms for our " \ "hostkey.")); goto error; } if (recv_pubkeyblob_len == pubkeyblob_len) { if (memcmp(recv_pubkeyblob, pubkeyblob, pubkeyblob_len) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("client gave us wrong (or corrupted) " \ "public key.")); #ifdef HEXDUMPS SSH_DEBUG_HEXDUMP(3, ("client gave us:"), \ recv_pubkeyblob, pubkeyblob_len); SSH_DEBUG_HEXDUMP(3, ("our pubkey:"), \ recv_pubkeyblob, pubkeyblob_len); #endif /* HEXDUMPS */ goto error; } } else { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("Client gave us wrong (or corrupted) public key. " \ "Lengths differ (received: %d ; ours: %d)", \ recv_pubkeyblob_len, pubkeyblob_len)); goto error; } if (strcmp(recv_hostname, hostname) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("Wethinks the client gave us the wrong hostname. " \ "(client's opinion: '%s' ours: '%s'", \ recv_hostname, hostname)); goto error; } if (strcmp(recv_username, username) != 0) { SSH_TRACE(1, ("Invalid packet.")); SSH_DEBUG(1, ("Client definitely gave us the wrong user name. " \ "(it says: '%s' we know: '%s')", recv_username, \ username)); goto error; } /* Sign the packet and send it to client. */ /* If we've gotten this far, the packet is ok, and it can be signed. */ SSH_TRACE(0, ("Received packet ok.")); if(signer->config->public_host_key_file[0] != '/') { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR, signer->config->host_key_file); } else { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s", signer->config->host_key_file); } SSH_TRACE(2, ("place to look for private key: %s", hostkeyfile)); if ((privkey = ssh_privkey_read(signer->effective_user_data, hostkeyfile, "", &comment, NULL)) == NULL) ssh_fatal("ssh_privkey_read from %s failed.", hostkeyfile); /* Check how big a chunk our private key can sign (this is purely a sanity check, as both of our signature schemas do their own hashing) */ sig_len = ssh_private_key_max_signature_input_len(privkey); SSH_TRACE(2, ("max input length for signing: %d", sig_len)); if (sig_len == 0) { SSH_TRACE(0, ("private key not capable of signing! " \ "(definitely an error)")); goto error; } else if (sig_len != -1 && sig_len < len) { SSH_TRACE(0, ("private key can't sign our data. (too much " \ "data (data_len %d, max input len for signing " \ "%d))", len, sig_len)); goto error; } /* Now check how much we much buffer we must allocate for the signature. */ sig_len = ssh_private_key_max_signature_output_len(privkey); SSH_TRACE(2, ("max output length for signature: %d", sig_len)); signature_buffer = ssh_xcalloc(sig_len, sizeof(unsigned char)); /* Do the actual signing. */ #ifdef HEXDUMPS SSH_DEBUG_HEXDUMP(5, ("Signing following data"), data + 4, len - 4); #endif /* HEXDUMPS */ if ((result = ssh_private_key_sign(privkey, data, len, signature_buffer, sig_len, &length_return, signer->random_state)) != SSH_CRYPTO_OK) { SSH_TRACE(0, ("ssh_private_key_sign() returned %d.", result)); goto error; } #ifdef HEXDUMPS SSH_DEBUG_HEXDUMP(5, ("Signature"), signature_buffer, length_return); #endif /* HEXDUMPS */ /* Send it to client. */ signer->packet_payload = signature_buffer; signer->packet_payload_len = length_return; signer->packet_waiting = TRUE; if (ssh_packet_wrapper_can_send(signer->wrapper)) signer_can_send(signer); /* XXX free dynamically allocated data. */ ssh_xfree(username); break; case SSH_AUTH_HOSTBASED_SIGNATURE: /* We shouldn't get this type of packet. This is an error.*/ SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE. This " \ "is an error.")); goto error; break; case SSH_AUTH_HOSTBASED_ERROR: /* We shouldn't be getting this either. This is an error. */ SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE_ERROR. " \ "This is an error. (This message can be sent by " \ "ssh-signer2 only)")); goto error; break; } return; /* We come here after errors. */ error: /* Send error message to ssh2, and wait for ssh2 to send EOF. */ ssh_packet_wrapper_send_encode(signer->wrapper, SSH_AUTH_HOSTBASED_ERROR, SSH_FORMAT_END); /* Init a 5 second timeout. If ssh2 hasn't disconnected at that time, close stream.*/ ssh_register_timeout(5L, 0L, signer_destroy_timeout, signer); return; }
int main(int argc, char **argv) { SshStream stdio_stream; SshSigner signer; char config_filename[512]; char *temp_name; #ifdef SLEEP_AFTER_STARTUP sleep(30); #endif /* SLEEP_AFTER_STARTUP */ /* Get program name (without path). */ if ((temp_name = strrchr(argv[0], '/')) != NULL) progname = ssh_xstrdup(temp_name + 1); else progname = ssh_xstrdup(argv[0]); /* XXX there should be a way to give command-line parameters to this program, but, they should only be used if the uid is the same as euid. */ ssh_event_loop_initialize(); signer = ssh_xcalloc(1, sizeof(*signer)); #ifdef SIGNER_QUIET signer->quiet = TRUE; #else /* SIGNER_QUIET */ signer->quiet = FALSE; #endif /* SIGNER_QUIET */ ssh_debug_register_callbacks(signer_ssh_fatal, signer_ssh_warning, signer_ssh_debug, (void *)signer); #ifdef SIGNER_DEBUG ssh_debug_set_global_level(5); #endif /* SIGNER_DEBUG */ /* Act as server. */ signer->config = ssh_server_create_config(); SSH_TRACE(2, ("public key file: %s", signer->config->public_host_key_file)); SSH_TRACE(2, ("private key file: %s", signer->config->host_key_file)); SSH_TRACE(2, ("randomseed file: %s", signer->config->random_seed_file)); /* Initialize user context with euid. This is used to dig up the hostkey and such. */ signer->effective_user_data = ssh_user_initialize_with_uid(geteuid(), FALSE); signer->random_state = ssh_randseed_open(signer->effective_user_data, signer->config); /* XXX what about alternative config files? This should be possible to configure somehow. An option for configure is probably a good idea. */ snprintf(config_filename, sizeof(config_filename), "%s/%s", SSH_SERVER_DIR, SSH_SERVER_CONFIG_FILE); if (!ssh_config_read_file(signer->effective_user_data, signer->config, NULL, config_filename, NULL)) ssh_warning("%s: Failed to read config file %s", argv[0], config_filename); stdio_stream = ssh_stream_fd_wrap2(fileno(stdin), fileno(stdout), TRUE); signer->wrapper = ssh_packet_wrap(stdio_stream, signer_received_packet, signer_received_eof, signer_can_send, signer); ssh_event_loop_run(); return 0; }
void ssh_client_auth_hostbased(SshAuthClientOperation op, const char *user, unsigned int packet_type, SshBuffer *packet_in, const unsigned char *session_id, size_t session_id_len, void **state_placeholder, SshAuthClientCompletionProc completion, void *completion_context, void *method_context) { SshClientHostbasedAuth state; SshClient client; SshStream stdio_stream; char hostkeyfile[512]; /* char *keytype; SshPublicKey pubkey;*/ char **signer_argv; char config_filename[512]; size_t hostname_len; SSH_DEBUG(6, ("auth_hostbased op = %d user = %s", op, user)); client = (SshClient)method_context; state = *state_placeholder; switch (op) { /* This operation is always non-interactive, as hostkeys shouldn't have passphrases. Check for it, though. XXX */ case SSH_AUTH_CLIENT_OP_START_NONINTERACTIVE: /* XXX There is a bug in sshauthc.c (or elsewhere). Authentication methods, that are not allowed, should not be tried. Now it calls SSH_AUTH_CLIENT_OP_START_NONINTERACTIVE for every authentication method before checking.*/ (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context); break; case SSH_AUTH_CLIENT_OP_START: /* This is the first operation for doing hostbased authentication. We should not have any previous saved state when we come here. */ SSH_ASSERT(*state_placeholder == NULL); /* Initialize a context. */ state = ssh_xcalloc(1, sizeof(*state)); state->session_id = session_id; state->session_id_len = session_id_len; state->user = ssh_xstrdup(user); /* We have to dig up the server configuration to get the place for the client host's publickey. This is a very kludgeish solution. XXX*/ state->server_conf = ssh_server_create_config(); /* Dig up hosts publickey. */ snprintf(config_filename, sizeof(config_filename), "%s/%s", SSH_SERVER_DIR, SSH_SERVER_CONFIG_FILE); if (!ssh_config_read_file(client->user_data, state->server_conf, NULL, config_filename, NULL)) SSH_TRACE(2, ("Failed to read config file %s", \ config_filename)); if(state->server_conf->public_host_key_file[0] != '/') { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR, state->server_conf->public_host_key_file); } else { snprintf(hostkeyfile, sizeof(hostkeyfile), "%s", state->server_conf->public_host_key_file); } /* This pubkey*-stuff is for the client _host's_ public hostkey. */ SSH_DEBUG(4, ("Reading pubkey-blob from %s...", hostkeyfile)); if (ssh2_key_blob_read(client->user_data, hostkeyfile, NULL, &state->pubkeyblob, &state->pubkeyblob_len, NULL) != SSH_KEY_MAGIC_PUBLIC) { goto error; } SSH_DEBUG(4, ("done.")); if ((state->pubkey_algorithm = ssh_pubkeyblob_type(state->pubkeyblob, state->pubkeyblob_len)) == NULL) { goto error; } state->local_user_name = ssh_user_name(client->user_data); state->local_host_name = ssh_xmalloc(MAXHOSTNAMELEN + 1); ssh_tcp_get_host_name(state->local_host_name, MAXHOSTNAMELEN + 1); hostname_len = strlen(state->local_host_name); /* Sanity check */ SSH_ASSERT(hostname_len + 2 < MAXHOSTNAMELEN); /* We want FQDN. */ state->local_host_name[hostname_len] = '.'; state->local_host_name[hostname_len + 1] = '\0'; state->completion = completion; state->completion_context = completion_context; state->state_placeholder = state_placeholder; /* Assign the state to the placeholder that survives across calls. (this is actually not needed, as hostbased authentication procedure is very simple. Just one packet from client to server, and server's response in one packet.) */ *state_placeholder = state; /* Open a pipestream connection to ssh-signer. */ switch (ssh_pipe_create_and_fork(&stdio_stream, NULL)) { case SSH_PIPE_ERROR: /* Something went wrong. */ ssh_warning("Couldn't create pipe to connect to %s.", client->config->signer_path); goto error; break; case SSH_PIPE_CHILD_OK: /* Exec ssh-signer */ SSH_TRACE(0, ("Child: Execing ssh-signer...(path: %s)", \ client->config->signer_path)); signer_argv = ssh_xcalloc(2, sizeof(char *)); signer_argv[0] = client->config->signer_path; signer_argv[1] = NULL; execvp(client->config->signer_path, signer_argv); fprintf(stderr, "Couldn't exec '%s' (System error message: %s)", client->config->signer_path, strerror(errno)); ssh_fatal("Executing ssh-signer failed."); break; case SSH_PIPE_PARENT_OK: state->wrapper = ssh_packet_wrap(stdio_stream, auth_hostbased_received_packet, auth_hostbased_received_eof, auth_hostbased_can_send, state); /* We don't check wrapper's validity, as ssh_packet_wrap should always succeed.*/ break; } /* Here we continue as parent. */ /* sign packet with ssh-signer (a suid-program). */ if (ssh_packet_wrapper_can_send(state->wrapper)) { ssh_client_auth_hostbased_send_to_signer(state); } /* If ssh_packet_wrapper_can_send returns FALSE, auth_hostbased_can_send will call the ...send_to_signer function above. */ /* Rest is done in callbacks. */ break; case SSH_AUTH_CLIENT_OP_CONTINUE: SSH_TRACE(2, ("Invalid message. We didn't return " \ "SSH_AUTH_CLIENT_SEND_AND_CONTINUE at any stage!")); /* Send failure message.*/ (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context); return; case SSH_AUTH_CLIENT_OP_ABORT: /* Abort the authentication operation immediately. */ /* XXX Destroy 'state'-object. */ *state_placeholder = NULL; break; default: /* something weird is going on.. */ ssh_fatal("ssh_client_auth_hostbased: unknown op %d", (int)op); } return; error: /* XXX Destroy state. */ /* Send failure message.*/ (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context); return; }