void ssh_xfree(void *ptr) { #ifdef SSH_DEBUG_MALLOC if (ptr != NULL) { unsigned long size; if (SSH_GET_32BIT((unsigned char *) ptr - 4) != SSH_DEBUG_MALLOC_MAGIC_IN_USE) { if (SSH_GET_32BIT((unsigned char *) ptr - 4) == SSH_DEBUG_MALLOC_MAGIC_FREED) ssh_fatal("Freeing block that is already freed"); ssh_fatal("Freeing block that is either not mallocated, or whose magic number before the object was overwritten"); } size = SSH_GET_32BIT((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); if (SSH_GET_32BIT((unsigned char *) ptr + size) != SSH_DEBUG_MALLOC_MAGIC_AFTER) ssh_fatal("Freeing block whose magic number after the object was overwritten"); /* Mark the old block freed */ SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED); SSH_PUT_32BIT((unsigned char *) ptr + size, SSH_DEBUG_MALLOC_MAGIC_FREED); free((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); } #else /* SSH_DEBUG_MALLOC */ if (ptr != NULL) free(ptr); #endif /* SSH_DEBUG_MALLOC */ }
void *ssh_xmalloc(unsigned long size) { void *ptr; if (size > XMALLOC_MAX_SIZE) ssh_fatal("ssh_xmalloc: allocation too large (allocating %ld bytes)", size); if (size == 0) size = 1; #ifdef SSH_DEBUG_MALLOC ptr = (void *)malloc((size_t) size + SSH_DEBUG_MALLOC_SIZE_BEFORE + SSH_DEBUG_MALLOC_SIZE_AFTER); if (ptr == NULL) ssh_fatal("ssh_xmalloc: out of memory (allocating %ld bytes)", size); SSH_PUT_32BIT(ptr, size); SSH_PUT_32BIT((unsigned char *) ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE); SSH_PUT_32BIT((unsigned char *) ptr + size + SSH_DEBUG_MALLOC_SIZE_BEFORE, SSH_DEBUG_MALLOC_MAGIC_AFTER); ptr = (unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE; #else /* SSH_DEBUG_MALLOC */ ptr = (void *)malloc((size_t) size); if (ptr == NULL) ssh_fatal("ssh_xmalloc: out of memory (allocating %ld bytes)", size); #endif /* SSH_DEBUG_MALLOC */ return ptr; }
static SshCryptoStatus sha512_final(void *c, unsigned char *digest, int num_64bit_words ) { SshSHA512Context *context = c; int padding, i; unsigned char temp = 0x80; unsigned int in_buffer; SshUInt32 total_low, total_high; total_low = context->total_length[0]; total_high = context->total_length[1]; ssh_sha512_update(context, &temp, 1); in_buffer = context->total_length[0] % 128; padding = (128 - (in_buffer + 17) % 128) % 128; if (in_buffer > 112) { memset(&context->u.in[in_buffer], 0, 128 - in_buffer); padding -= (128 - in_buffer); sha512_transform(context, context->u.in); in_buffer = 0; } /* Change the byte count to bit count. */ total_high <<= 3; total_high += (total_low >> 29); total_low <<= 3; SSH_PUT_32BIT(context->u.in + 120, total_high); SSH_PUT_32BIT(context->u.in + 124, total_low); /* Highest bits of length are always zero */ SSH_PUT_32BIT(context->u.in + 116, 0); SSH_PUT_32BIT(context->u.in + 112, 0); if ((128 - in_buffer - 16) > 0) { memset(&context->u.in[in_buffer], 0, 128 - in_buffer - 16); } sha512_transform(context, context->u.in); /* Copy the internal state to the digest output. */ for (i = 0; i < num_64bit_words; i++) { SSH_XUINT64_PUT(context->H[i], digest + i*8); } memset(context, 0, sizeof(SshSHA512Context)); return SSH_CRYPTO_OK; }
size_t ssh_packet_encode_va(SshBuffer *buffer, SshPacketType type, va_list ap) { size_t payload_size, original_len; unsigned char *p; /* Save the original length so we can later find where the packet header starts. */ original_len = ssh_buffer_len(buffer); /* Construct the packet header with dummy length. */ ssh_encode_buffer(buffer, SSH_FORMAT_UINT32, (SshUInt32) 0, SSH_FORMAT_CHAR, (unsigned int)type, SSH_FORMAT_END); /* Encode the packet payload. */ payload_size = ssh_encode_va(buffer, ap); /* Update the packet header to contain the correct payload size. */ p = ssh_buffer_ptr(buffer); p += original_len; SSH_PUT_32BIT(p, payload_size + 1); /* Return the total number of bytes added to the buffer. */ return ssh_buffer_len(buffer) - original_len; }
void ssh_virtual_adapter_ip_ether_address(SshIpAddr ip, unsigned char *buffer) { memset(buffer, 0, SSH_ETHERH_ADDRLEN); if (SSH_IP_IS4(ip)) { buffer[1] = 2; SSH_IP4_ENCODE(ip, buffer + 2); } #if defined (WITH_IPV6) else { SshUInt32 value; value = SSH_IP6_WORD0_TO_INT(ip); value ^= SSH_IP6_WORD1_TO_INT(ip); value ^= SSH_IP6_WORD2_TO_INT(ip); value ^= SSH_IP6_WORD3_TO_INT(ip); buffer[1] = 2; SSH_PUT_32BIT(buffer + 2, value); } #endif /* WITH_IPV6 */ }
Boolean ssh_engine_send(SshEngine engine, Boolean locked, Boolean reliable, ...) { va_list ap; unsigned char *ucp; size_t len; if (!locked) ssh_kernel_mutex_lock(engine->lock); if (!engine->ipm_open) { if (!locked) ssh_kernel_mutex_unlock(engine->lock); return FALSE; } if (!locked) ssh_kernel_mutex_unlock(engine->lock); /* WARNING: this function is called from ssh_debug callback, which means that no debug functions can be called here or we'll end up with infinite recursion. */ /* Construct the final packet to send to ipm. */ va_start(ap, reliable); len = ssh_encode_array_alloc_va(&ucp, ap); va_end(ap); SSH_ASSERT(len >= 5); /* must have at least len+type */ /* Update the length of the packet. */ SSH_PUT_32BIT(ucp, len - 4); /* Send and/or queue the packet to the ipm. This will free the buffer. */ return (*engine->send)(ucp, len, reliable, engine->machine_context); }
void ssh_virtual_adapter_interface_ether_address(SshInterceptorIfnum adapter_ifnum, unsigned char *buffer) { memset(buffer, 0, SSH_ETHERH_ADDRLEN); buffer[1] = 1; SSH_PUT_32BIT(buffer + 2, (SshUInt32) adapter_ifnum + 1); }
void ssh_channel_open_ssh1_agent_connected(SshStream stream, void *context) { SshAgentConnection a = (SshAgentConnection)context; SshBuffer buffer; unsigned char *cp; if (stream == NULL) { SSH_DEBUG(1, ("Connecting to the real agent failed.")); (*a->completion)(SSH_OPEN_CONNECT_FAILED, NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL, a->context); ssh_xfree(a); return; } SSH_DEBUG(5, ("connection to real agent established")); /* Increment the number of channels. */ ssh_common_new_channel(a->common); if (a->common->config->ssh_agent_compat == SSH_AGENT_COMPAT_SSH2) { /* We are required to send a FORWARDING_NOTIFY to the agent to inform it that the connection is actually forwarded. Format that packet now. */ ssh_buffer_init(&buffer); ssh_encode_buffer(&buffer, SSH_FORMAT_DATA, "1234", (size_t)4, SSH_FORMAT_CHAR, (unsigned int) SSH_AGENT_FORWARDING_NOTICE, SSH_FORMAT_UINT32_STR, a->common->server_host_name, strlen(a->common->server_host_name), SSH_FORMAT_UINT32_STR, a->common->remote_ip, strlen(a->common->remote_ip), SSH_FORMAT_UINT32, (SshUInt32) atol(a->common->remote_port), SSH_FORMAT_END); cp = ssh_buffer_ptr(&buffer); SSH_PUT_32BIT(cp, ssh_buffer_len(&buffer) - 4); /* Write the buffer to the channel. This is a kludge; this assumes that we can always write this much to the internal buffers. */ if (ssh_stream_write(stream, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)) != ssh_buffer_len(&buffer)) ssh_fatal("ssh_channel_open_agent_connected: kludge failed"); ssh_buffer_uninit(&buffer); } /* Create the channel. */ (*a->completion)(SSH_OPEN_OK, stream, TRUE, TRUE, AGENT_WINDOW_SIZE, NULL, 0, NULL, ssh_channel_ssh1_agent_connection_destroy, (void *)a->common, a->context); ssh_xfree(a); }
static SshRadiusUrlStatus ssh_radius_url_add_avp_by_type(SshRadiusUrlAvpSet avp_set, const SshRadiusAvpInfoStruct *avp_info, unsigned char *value, size_t value_length) { long val; const SshKeywordStruct *keywords; SshUInt8 number_buf[4]; SSH_PRECOND(avp_set != NULL); SSH_PRECOND(avp_info != NULL); /* If value == NULL, then choose default value based on value type */ if (value == NULL) return SSH_RADIUS_URL_STATUS_NONE; if (avp_info->value_type != SSH_RADIUS_AVP_VALUE_INTEGER) return SSH_RADIUS_URL_STATUS_NONE; /* Special cases for some attributes */ switch (avp_info->type) { case SSH_RADIUS_AVP_FRAMED_PROTOCOL: keywords = ssh_radius_framed_protocols; break; case SSH_RADIUS_AVP_SERVICE_TYPE: keywords = ssh_radius_service_types; break; case SSH_RADIUS_AVP_NAS_PORT_TYPE: keywords = ssh_radius_nas_port_types; break; default: keywords = NULL; break; } if (keywords == NULL) return SSH_RADIUS_URL_STATUS_NONE; val = ssh_find_partial_keyword_number_case_insensitive(keywords, ssh_csstr(value), NULL); if (val == -1) return SSH_RADIUS_URL_INVALID_AVP_VALUE; SSH_PUT_32BIT(number_buf, val); if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, number_buf, 4) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; return SSH_RADIUS_URL_STATUS_SUCCESS; }
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 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); }
void *ssh_xcalloc(unsigned long nitems, unsigned long size) { void *ptr; if (nitems == 0) nitems = 1; if (size == 0) size = 1; if (size * nitems > XMALLOC_MAX_SIZE) ssh_fatal("ssh_xcalloc: allocation too large (allocating %ld*%ld bytes)", size, nitems); #ifdef SSH_DEBUG_MALLOC ptr = (void *)malloc(((size_t) nitems * (size_t) size) + SSH_DEBUG_MALLOC_SIZE_BEFORE + SSH_DEBUG_MALLOC_SIZE_AFTER); if (ptr == NULL) ssh_fatal("ssh_xcalloc: out of memory (allocating %ld*%ld bytes)", nitems, size); memset((unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE, 0, (nitems * size)); SSH_PUT_32BIT(ptr, (size * nitems)); SSH_PUT_32BIT((unsigned char *) ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE); SSH_PUT_32BIT((unsigned char *) ptr + (size * nitems) + SSH_DEBUG_MALLOC_SIZE_BEFORE, SSH_DEBUG_MALLOC_MAGIC_AFTER); ptr = (unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE; #else /* SSH_DEBUG_MALLOC */ ptr = (void *)calloc((size_t) nitems, (size_t) size); if (ptr == NULL) ssh_fatal("ssh_xcalloc: out of memory (allocating %ld*%ld bytes)", nitems, size); #endif /* SSH_DEBUG_MALLOC */ return ptr; }
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_sha_final(void *c, unsigned char *digest) { SshSHAContext *context = c; int padding; unsigned char temp = 0x80; unsigned int in_buffer; SshUInt32 total_low, total_high; total_low = context->total_length[0]; total_high = context->total_length[1]; ssh_sha_update(context, &temp, 1); in_buffer = context->total_length[0] % 64; padding = (64 - (in_buffer + 9) % 64) % 64; if (in_buffer > 56) { memset(&context->in[in_buffer], 0, 64 - in_buffer); padding -= (64 - in_buffer); sha_transform(context, context->in); in_buffer = 0; } /* change the byte count to bits count */ total_high <<= 3; total_high += (total_low >> 29); total_low <<= 3; SSH_PUT_32BIT(context->in + 56, total_high); SSH_PUT_32BIT(context->in + 60, total_low); if ((64 - in_buffer - 8) > 0) { memset(&context->in[in_buffer], 0, 64 - in_buffer - 8); } sha_transform(context, context->in); SSH_PUT_32BIT(digest, context->A); SSH_PUT_32BIT(digest + 4, context->B); SSH_PUT_32BIT(digest + 8, context->C); SSH_PUT_32BIT(digest + 12, context->D); SSH_PUT_32BIT(digest + 16, context->E); memset(context, 0, sizeof(SshSHAContext)); }
void mp_linearize_msb_first(unsigned char *buf, unsigned int len, SshInt *value) { unsigned int i; SshInt aux; ssh_mp_init_set(&aux, value); for (i = len; i >= 4; i -= 4) { unsigned long limb = ssh_mp_get_ui(&aux); SSH_PUT_32BIT(buf + i - 4, limb); ssh_mp_div_2exp(&aux, &aux, 32); } for (; i > 0; i--) { buf[i - 1] = ssh_mp_get_ui(&aux); ssh_mp_div_2exp(&aux, &aux, 8); } ssh_mp_clear(&aux); }
void ssh_mp_to_buf(unsigned char *cp, size_t len, const SshInt *x) { unsigned long limb; size_t i; SshInt aux; ssh_mp_init_set(&aux, x); for (i = len; i >= 4; i -= 4) { limb = ssh_mp_get_ui(&aux); SSH_PUT_32BIT(cp + i - 4, limb); ssh_mp_div_2exp(&aux, &aux, 32); } for (;i > 0; i--) { cp[i - 1] = (unsigned char)(ssh_mp_get_ui(&aux) & 0xff); ssh_mp_div_2exp(&aux, &aux, 8); } ssh_mp_clear(&aux); }
SshOperationHandle d_spd_notify_request(SshSADHandle sad_handle, SshIkev2ExchangeData ed, SshIkev2SpdNotifyCB reply_callback, void *reply_callback_context) { SshIkev2Error status = SSH_IKEV2_ERROR_OK; SshIkev2ProtocolIdentifiers protocol = SSH_IKEV2_PROTOCOL_ID_IKE; unsigned char *spi = NULL, *notify_data = NULL; size_t spi_size = 0, notify_data_size = 0; SshIkev2NotifyMessageType notify_type = SSH_IKEV2_NOTIFY_RESERVED; SSH_DEBUG(SSH_D_HIGHSTART, ("Enter SA %p ED %p", ed->ike_sa, ed)); #if 1 if (!opt_client && (ed->state == SSH_IKEV2_STATE_REKEY_IKE || ((ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && ed->state == SSH_IKEV2_STATE_IKE_AUTH_1ST) #ifdef SSH_IKEV2_MULTIPLE_AUTH || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && ed->ike_ed && !(ed->ike_ed->second_eap_auth) && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST) || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && ed->ike_ed && ed->ike_ed->second_eap_auth && ed->ike_ed->first_auth_done && ed->ike_ed->eap_state == SSH_IKEV2_EAP_DONE && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST) #else /* SSH_IKEV2_MULTIPLE_AUTH */ || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST) #endif /* SSH_IKEV2_MULTIPLE_AUTH */ ) ) { unsigned char buffer[4]; SSH_PUT_32BIT(buffer, 2); (*reply_callback)(SSH_IKEV2_ERROR_OK, 0, NULL, 0, SSH_IKEV2_NOTIFY_SET_WINDOW_SIZE, buffer, sizeof(buffer), reply_callback_context); } #endif #ifdef SSHDIST_IKE_MOBIKE /* Responder indicates MOBIKE supported in the IKE_AUTH exchange if MOBIKE is locally supported and a MOBIKE supported notify was received from the initiator. */ if (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && (ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST) && mobike_supported && peer_supports_mobike) { SSH_DEBUG(SSH_D_MIDOK, ("Indicating support for MOBIKE")); (*reply_callback)(SSH_IKEV2_ERROR_OK, 0, NULL, 0, SSH_IKEV2_NOTIFY_MOBIKE_SUPPORTED, NULL, 0, reply_callback_context); } #endif /* SSHDIST_IKE_MOBIKE */ #ifdef SSH_IKEV2_MULTIPLE_AUTH if (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && (ed->state == SSH_IKEV2_STATE_IKE_INIT_SA) && use_multiple_auth) { SSH_DEBUG(SSH_D_MIDOK, ("Indicating support for multiple " "authentications")); (*reply_callback)(SSH_IKEV2_ERROR_OK, 0, NULL, 0, SSH_IKEV2_NOTIFY_MULTIPLE_AUTH_SUPPORTED, NULL, 0, reply_callback_context); } #endif /* SSH_IKEV2_MULTIPLE_AUTH */ (*reply_callback)(status, protocol, spi, spi_size, notify_type, notify_data, notify_data_size, reply_callback_context); return NULL; }
void ikev2_fb_spd_select_qm_sa_cb(SshIkev2Error error_code, int ikev2_proposal_index, SshIkev2PayloadTransform selected_transforms[SSH_IKEV2_TRANSFORM_TYPE_MAX], void *context) { SshIkev2FbNegotiation neg = context; SshIkeIpsecSelectedSAIndexes selected = NULL; SshIkePayloadSA sa; int ikev1_proposal_index, ikev1_ipsec_transform_index; int ikev1_ipcomp_transform_index, i, iproto; SSH_IKEV2_FB_V2_COMPLETE_CALL(neg); sa = &neg->sa_table_in[0]->pl.sa; if (error_code != SSH_IKEV2_ERROR_OK) { SSH_DEBUG(SSH_D_FAIL, ("IKEv2 SA select failed with error %s", ssh_ikev2_error_to_string(error_code))); goto error; } /* Check if ISAKMP library has freed the qm negotiation. */ if (neg->qm_info == NULL) { SSH_DEBUG(SSH_D_FAIL, ("QM negotiation has disappeared")); neg->ike_error = SSH_IKEV2_ERROR_INVALID_ARGUMENT; goto error; } if (selected_transforms == NULL) { SSH_DEBUG(SSH_D_FAIL, ("No IPSec SA transforms selected")); goto error; } /* Store information on the selected SA to the IPSec exchange data. */ for (i = 0; i < SSH_IKEV2_TRANSFORM_TYPE_MAX; i++) { neg->ed->ipsec_ed->ipsec_sa_transforms[i] = selected_transforms[i]; } neg->ed->ipsec_ed->ipsec_sa_protocol = neg->sav2->protocol_id[ikev2_proposal_index]; /* Set the inbound SPI to the IPSec exchange data */ neg->ed->ipsec_ed->spi_inbound = neg->inbound_spi; SSH_DEBUG(SSH_D_LOWOK, ("Inbound SPI %lx", (unsigned long) neg->inbound_spi)); SSH_ASSERT(neg->number_of_sas_in == 1); selected = ssh_calloc(neg->number_of_sas_in, sizeof(*selected)); if (selected == NULL) goto error; /* Check to see which proposal and ESP/AH/IPComp transform index was selected. */ if (!ikev2_fb_select_ipsec_transform_index(selected_transforms, neg->qm_info->negotiation, sa, neg->ipcomp_proposals, neg->ipcomp_algs[0], &ikev1_proposal_index, &ikev1_ipsec_transform_index, &ikev1_ipcomp_transform_index)) { error: SSH_DEBUG(SSH_D_FAIL, ("SA selection failed, no matching proposal (neg %p)", neg)); ikev2_fb_free_sa_indexes(selected, neg->number_of_sas_in); neg->selected = NULL; SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); return; } selected[0].proposal_index = ikev1_proposal_index; SSH_DEBUG(SSH_D_LOWOK, ("Selected proposal indices are v2=%d, v1=%d num protocols is %d", ikev2_proposal_index, ikev1_proposal_index, sa->proposals[ikev1_proposal_index].number_of_protocols)); selected[0].number_of_protocols = sa->proposals[ikev1_proposal_index].number_of_protocols; selected[0].transform_indexes = ssh_calloc(selected[0].number_of_protocols, sizeof(int)); selected[0].spi_sizes = ssh_calloc(selected[0].number_of_protocols, sizeof(size_t)); selected[0].spis = ssh_calloc(selected[0].number_of_protocols, sizeof(unsigned char *)); if (selected[0].transform_indexes == NULL || selected[0].spi_sizes == NULL || selected[0].spis == NULL) goto error; for (iproto = 0; iproto < selected[0].number_of_protocols; iproto++) { SshIkePayloadPProtocol proto = &sa->proposals[ikev1_proposal_index].protocols[iproto]; if ((selected->spis[iproto] = ssh_malloc(4)) == NULL) goto error; switch (proto->protocol_id) { case SSH_IKE_PROTOCOL_IPCOMP: selected->spi_sizes[iproto] = 2; SSH_PUT_16BIT(selected->spis[iproto], neg->ipcomp_cpi_in); selected[0].transform_indexes[iproto] = ikev1_ipcomp_transform_index; break; default: selected->spi_sizes[iproto] = 4; SSH_PUT_32BIT(selected->spis[iproto], neg->inbound_spi); /* Check the proposed lifetimes against that of our policy to see whether we should send a responder lifetime notification */ if (ikev2_fb_check_ipsec_responder_lifetimes(neg->ed, neg->sa_life_seconds, neg->sa_life_kbytes)) { /* Let's send a responder lifetime notify. */ SSH_DEBUG(SSH_D_NICETOKNOW, ("Sending a responder lifetime notification: " "life_sec=%lu, life_kb=%lu", neg->ed->ipsec_ed->sa_life_seconds, neg->ed->ipsec_ed->sa_life_kbytes)); selected[0].expire_secs = neg->ed->ipsec_ed->sa_life_seconds; selected[0].expire_kb = neg->ed->ipsec_ed->sa_life_kbytes; } selected[0].transform_indexes[iproto] = ikev1_ipsec_transform_index; } } neg->selected = selected; SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); return; }
void *ssh_xrealloc(void *ptr, unsigned long new_size) { void *new_ptr; if (ptr == NULL) return ssh_xmalloc(new_size); if (new_size > XMALLOC_MAX_SIZE) ssh_fatal("ssh_xrealloc: allocation too large (allocating %ld bytes)", (long)new_size); if (new_size == 0) new_size = 1; #ifdef SSH_DEBUG_MALLOC if (SSH_GET_32BIT((unsigned char *) ptr - 4) != SSH_DEBUG_MALLOC_MAGIC_IN_USE) { if (SSH_GET_32BIT((unsigned char *) ptr - 4) == SSH_DEBUG_MALLOC_MAGIC_FREED) ssh_fatal("Reallocating block that is already freed"); ssh_fatal("Reallocating block that is either not mallocated, or whose magic number before the object was overwritten"); } else { unsigned long old_size; old_size = SSH_GET_32BIT((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE); if (SSH_GET_32BIT((unsigned char *) ptr + old_size) != SSH_DEBUG_MALLOC_MAGIC_AFTER) ssh_fatal("Reallocating block whose magic number after the object was overwritten"); /* Mark the old block freed */ SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED); SSH_PUT_32BIT((unsigned char *) ptr + old_size, SSH_DEBUG_MALLOC_MAGIC_FREED); new_ptr = (void *)realloc((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE, (size_t) new_size + SSH_DEBUG_MALLOC_SIZE_BEFORE + SSH_DEBUG_MALLOC_SIZE_AFTER); if (new_ptr == NULL) ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)", (long)new_size); SSH_PUT_32BIT(new_ptr, new_size); SSH_PUT_32BIT((unsigned char *) new_ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE); SSH_PUT_32BIT((unsigned char *) new_ptr + new_size + SSH_DEBUG_MALLOC_SIZE_BEFORE, SSH_DEBUG_MALLOC_MAGIC_AFTER); new_ptr = (unsigned char *) new_ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE; } #else /* SSH_DEBUG_MALLOC */ new_ptr = (void *)realloc(ptr, (size_t) new_size); if (new_ptr == NULL) ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)", (long)new_size); #endif /* SSH_DEBUG_MALLOC */ return new_ptr; }
static SshRadiusUrlStatus ssh_radius_url_add_avp(SshRadiusUrlAvpSet avp_set, const SshRadiusAvpInfoStruct *avp_info, unsigned char *value, size_t value_len) { unsigned long val; SshRadiusUrlStatus url_status; SSH_PRECOND(avp_set != NULL); SSH_PRECOND(avp_info != NULL); /* Try to allow for "magic keyword" substituion for selected parameter values. */ if (avp_info->value_type == SSH_RADIUS_AVP_VALUE_INTEGER) { url_status = ssh_radius_url_add_avp_by_type(avp_set, avp_info, value, value_len); if (url_status != SSH_RADIUS_URL_STATUS_NONE) return url_status; } /* Perform setting based on type */ switch (avp_info->value_type) { case SSH_RADIUS_AVP_VALUE_TEXT: if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, (SshUInt8 *) value, (SshUInt8)value_len) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; break; case SSH_RADIUS_AVP_VALUE_TAG_INTEGER: case SSH_RADIUS_AVP_VALUE_TAG_STRING: case SSH_RADIUS_AVP_VALUE_IPV6_ADDRESS: SSH_DEBUG(SSH_D_FAIL,("TAG and IPV6 attributes not yet supported")); return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE; break; case SSH_RADIUS_AVP_VALUE_TIME: case SSH_RADIUS_AVP_VALUE_INTEGER: { SshUInt8 number_buf[4]; val = (value != NULL ? ssh_ustrtol(value, NULL, 0) : 0); SSH_PUT_32BIT(number_buf, val); if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, number_buf, 4) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; } break; /* Convert IPv4 address to 32-bit integer */ case SSH_RADIUS_AVP_VALUE_ADDRESS: { SshIpAddrStruct ip_addr; SshUInt8 number_buf[4]; if (value == NULL) return SSH_RADIUS_URL_INVALID_AVP_VALUE; if (ssh_ipaddr_parse(&ip_addr, value) == FALSE) return SSH_RADIUS_URL_INVALID_AVP_VALUE; if (SSH_IP_IS4(&ip_addr) == FALSE) return SSH_RADIUS_URL_INVALID_AVP_VALUE; SSH_PUT_32BIT(number_buf, SSH_IP4_TO_INT(&ip_addr)); if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type, number_buf, 4) == FALSE) return SSH_RADIUS_URL_OUT_OF_MEMORY; } break; default: SSH_DEBUG(SSH_D_FAIL, ("Unknown RADIUS attribute value type %d!", avp_info->value_type)); return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE; } return SSH_RADIUS_URL_STATUS_SUCCESS; }
void test_variant(const char *postfix) { SshCipher cipher; SshCryptoStatus status; unsigned char *iv, *key, *src, *plain; unsigned char *aad, *ciph, *auth_tag, digest_len; size_t key_len, iv_len, aad_len, src_len, src_len_block, ciph_len, auth_tag_len, orig_len; unsigned char *orig; unsigned char iv_buf[16], *digest; unsigned char *ciph_name; size_t blocklen; int i; for (i = 0; combined_test_vectors[i].key != NULL; i++) { hex_string_to_buf(combined_test_vectors[i].key, &key, &key_len); hex_string_to_buf(combined_test_vectors[i].iv, &iv, &iv_len); hex_string_to_buf(combined_test_vectors[i].aad, &aad, &aad_len); hex_string_to_buf(combined_test_vectors[i].plaintext, &plain, &src_len); hex_string_to_buf(combined_test_vectors[i].plaintext, &src, &src_len); orig = ssh_xmemdup(src, src_len); orig_len = src_len; hex_string_to_buf(combined_test_vectors[i].ciphertext, &ciph, &ciph_len); hex_string_to_buf(combined_test_vectors[i].auth_tag, &auth_tag, &auth_tag_len); digest = NULL; ciph_name = ssh_string_concat_2(combined_test_vectors[i].name, postfix); SSH_ASSERT(ciph_name); status = ssh_cipher_allocate(ciph_name, key, key_len, TRUE, &cipher); if (status != SSH_CRYPTO_OK) { fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", ciph_name, ssh_crypto_status_message(status)); exit(1); } if (iv_len != 12) { SSH_DEBUG(1, ("Skipping test %d with IV not equal to 12 bytes", i)); goto dealloc_and_continue; } if (!ssh_cipher_is_auth_cipher(combined_test_vectors[i].name)) { SSH_DEBUG(1, ("Skipping test %d with non-auth cipher", i)); goto dealloc_and_continue; } digest_len = ssh_cipher_auth_digest_length(combined_test_vectors[i].name); digest = ssh_xmalloc(digest_len); ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); SSH_ASSERT(iv_len == 12); memcpy(iv_buf, iv, 12); SSH_PUT_32BIT(iv_buf + 12, 1); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); blocklen = ssh_cipher_get_block_length(combined_test_vectors[i].name); src_len_block = src_len - (src_len % blocklen); status = ssh_cipher_transform(cipher, src, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, src + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (src_len != ciph_len || memcmp(src, ciph, src_len)) { fprintf(stderr, "Test vectors ciphertext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("cipher computed"), src, src_len); SSH_DEBUG_HEXDUMP(1, ("cipher expected"), ciph, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } /* Redo operation, now decryption */ ssh_cipher_free(cipher); status = ssh_cipher_allocate(ciph_name, key, key_len, FALSE, &cipher); if (status != SSH_CRYPTO_OK) { fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", ciph_name, ssh_crypto_status_message(status)); exit(1); } SSH_ASSERT(digest_len == ssh_cipher_auth_digest_length(combined_test_vectors[i].name)); ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); SSH_ASSERT(iv_len == 12); memcpy(iv_buf, iv, 12); SSH_PUT_32BIT(iv_buf + 12, 1); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); src_len_block = src_len - (src_len % blocklen); status = ssh_cipher_transform(cipher, orig, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, orig + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (orig_len != ciph_len || memcmp(orig, plain, src_len)) { fprintf(stderr, "Test vectors plaintext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len); SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } /* Reset cipher and redo decryption */ ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); status = ssh_cipher_transform(cipher, orig, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, orig + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (orig_len != ciph_len || memcmp(orig, plain, src_len)) { fprintf(stderr, "Test vectors plaintext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len); SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } SSH_DEBUG(2, ("Test %d (cipher=`%s') successful", i, combined_test_vectors[i].name)); dealloc_and_continue: if (cipher) ssh_cipher_free(cipher); ssh_xfree(digest); ssh_xfree(key); ssh_xfree(iv); ssh_xfree(aad); ssh_xfree(src); ssh_xfree(orig); ssh_xfree(plain); ssh_xfree(ciph); ssh_xfree(auth_tag); ssh_xfree(ciph_name); } }
/* Generate stateless cookie based on the secret, nonce, spi_i and ip-address. */ SshIkev2Error ikev2_generate_cookie(SshIkev2Packet packet, SshIkev2Sa ike_sa, unsigned char *notify_data, size_t notify_len) { SshCryptoStatus status; unsigned char buffer[16]; SshMac mac; size_t len; SSH_DEBUG(SSH_D_LOWOK, ("Starting cookie generation for SA %p", ike_sa)); packet->ed->ike_ed->cookie_len = 4 + ssh_mac_length(IKEV2_COOKIE_MAC_ALGORITHM); packet->ed->ike_ed->cookie = ssh_obstack_alloc(packet->ed->obstack, packet->ed->ike_ed->cookie_len); if (packet->ed->ike_ed->cookie == NULL) { SSH_DEBUG(SSH_D_ERROR, ("Error: Out of memory allocating cookie")); return SSH_IKEV2_ERROR_OUT_OF_MEMORY; } if (notify_len > 4 && notify_data != NULL && SSH_GET_32BIT(notify_data) == ike_sa->server->context->cookie_version_number - 1) { ike_sa->server->context->cookie_secret_use_counter_prev++; SSH_PUT_32BIT(packet->ed->ike_ed->cookie, ike_sa->server->context->cookie_version_number - 1); status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM, ike_sa->server->context->cookie_secret_prev, IKEV2_COOKIE_SECRET_LEN, &mac); } else { ike_sa->server->context->cookie_secret_use_counter++; SSH_PUT_32BIT(packet->ed->ike_ed->cookie, ike_sa->server->context->cookie_version_number); status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM, ike_sa->server->context->cookie_secret, IKEV2_COOKIE_SECRET_LEN, &mac); } if (status != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_allocate(%s) failed: %s", IKEV2_COOKIE_MAC_ALGORITHM, ssh_crypto_status_message(status))); return SSH_IKEV2_ERROR_OUT_OF_MEMORY; } ssh_mac_reset(mac); ssh_mac_update(mac, packet->ed->nonce->nonce_data, packet->ed->nonce->nonce_size); SSH_IP_ENCODE(packet->remote_ip, buffer, len); ssh_mac_update(mac, buffer, len); ssh_mac_update(mac, packet->ike_spi_i, 8); status = ssh_mac_final(mac, packet->ed->ike_ed->cookie + 4); ssh_mac_free(mac); if (status != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_final(%s) failed: %s", IKEV2_COOKIE_MAC_ALGORITHM, ssh_crypto_status_message(status))); return SSH_IKEV2_ERROR_CRYPTO_FAIL; } #ifdef SSH_IKEV2_CRYPTO_KEY_DEBUG SSH_DEBUG_HEXDUMP(SSH_D_DATADUMP, ("Cookie generated"), packet->ed->ike_ed->cookie, packet->ed->ike_ed->cookie_len); #endif /* SSH_IKEV2_CRYPTO_KEY_DEBUG */ return SSH_IKEV2_ERROR_OK; }
SshTlsTransStatus ssh_tls_trans_write_client_hello(SshTlsProtocolState s) { SshTlsCipherSuite tab[SSH_TLS_NUM_CIPHERSUITES]; SshTlsCipherSuite *suites_to_send; SshTlsCipherSuiteDetailsStruct details; int number_suites; int contents_len; unsigned char tempbuf[2]; int i; s->kex.flags |= SSH_TLS_KEX_NEW_SESSION; /* Initially. */ if (s->conf.preferred_suites != NULL) { /* If a preference list has been given, check that the preferences are sound w.r.t. the protocol flags given in the configuration. */ SshTlsCipherSuite *tmp; SSH_DEBUG(6, ("Got a preference list.")); number_suites = 0; tmp = s->conf.preferred_suites; while (*tmp != SSH_TLS_NO_CIPHERSUITE) { ssh_tls_get_ciphersuite_details(*tmp, &details); if (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS))) { return SSH_TLS_TRANS_FAILED; } if (details.cipher == SSH_TLS_CIPH_NULL && (!(s->conf.flags & SSH_TLS_NULLCIPHER))) { return SSH_TLS_TRANS_FAILED; } tmp++; number_suites++; } suites_to_send = s->conf.preferred_suites; } else { /* Otherwise construct a list containing all those ciphersuites that are supported by our implementation and that can be used according to the protocol configuration flags. */ number_suites = 0; for (i = SSH_TLS_RSA_WITH_NULL_MD5; i < SSH_TLS_MAX_CIPHERSUITE; i++) { ssh_tls_get_ciphersuite_details(i, &details); SSH_DEBUG(7, ("Check if suite %d can be supported.", i)); if ((details.kex_method == SSH_TLS_UNKNOWN_SUITE) || !(ssh_tls_supported_suite(s->conf.flags, (SshTlsCipherSuite) i))) continue; SSH_DEBUG(7, ("Null? %d Crippled? %d RC2? %d RSA? %d " "Nosign? %d", (details.cipher == SSH_TLS_CIPH_NULL), (details.crippled), (details.cipher == SSH_TLS_CIPH_RC2), (details.kex_method == SSH_TLS_KEX_RSA), (details.signature_method == SSH_TLS_SIGN_NONE))); if ((details.cipher == SSH_TLS_CIPH_NULL && (!(s->conf.flags & SSH_TLS_NULLCIPHER))) || (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS))) || (details.cipher == SSH_TLS_CIPH_RC2) || (details.kex_method != SSH_TLS_KEX_RSA) || (details.signature_method != SSH_TLS_SIGN_NONE)) continue; SSH_DEBUG(7, ("Adding the cipher suite %d.", i)); tab[number_suites++] = i; } suites_to_send = tab; } /* Now we can calculate the length of the packet. */ /* Protocol version 2 bytes, random value 32 bytes, session ID 1 + N bytes, ciphersuites list 2 bytes (length) plus number_suites * 2 bytes, and 2 bytes for the single compression method (no compression) we support. */ contents_len = 2 + 32 + 1 + s->kex.id_len + 2 + number_suites * 2 + 2; /* Initialize the handshake history buffer now. */ SSH_ASSERT(s->kex.handshake_history == NULL); s->kex.handshake_history = ssh_buffer_allocate(); if (s->kex.handshake_history == NULL) return SSH_TLS_TRANS_FAILED; ssh_tls_make_hs_header(s, SSH_TLS_HS_CLIENT_HELLO, contents_len); /* Write the highest protocol version or that of a hopefully-resumed session. */ tempbuf[0] = s->kex.client_version.major; tempbuf[1] = s->kex.client_version.minor; ssh_tls_add_to_kex_packet(s, tempbuf, 2); /* Write unix time. */ SSH_PUT_32BIT(s->kex.client_random, (SshUInt32)ssh_time()); /* Write 28 random bytes. */ for (i = 4; i < 32; i++) { s->kex.client_random[i] = ssh_random_get_byte(); } ssh_tls_add_to_kex_packet(s, s->kex.client_random, 32); /* Write the requested session identifier. */ tempbuf[0] = s->kex.id_len; ssh_tls_add_to_kex_packet(s, &tempbuf[0], 1); if (s->kex.id_len > 0) { ssh_tls_add_to_kex_packet(s, s->kex.session_id, s->kex.id_len); } /* Write the cipher suites. */ SSH_PUT_16BIT(tempbuf, number_suites * 2); ssh_tls_add_to_kex_packet(s, tempbuf, 2); for (i = 0; i < number_suites; i++) { SSH_PUT_16BIT(tempbuf, suites_to_send[i]); ssh_tls_add_to_kex_packet(s, tempbuf, 2); } /* And the compression method. */ tempbuf[0] = 1; tempbuf[1] = 0; /* the null compression */ ssh_tls_add_to_kex_packet(s, tempbuf, 2); s->kex.state = SSH_TLS_KEX_WAIT_S_HELLO; return SSH_TLS_TRANS_OK; }
SshOperationHandle ssh_pm_cfgmode_client_store_register(SshPm pm, SshPmTunnel tunnel, SshPmActiveCfgModeClient client, SshIpAddr address, void *address_context, SshPmRemoteAccessAttrsFreeCB free_cb, void *free_cb_context, SshPmStatusCB status_cb, void *status_cb_context) { SSH_DEBUG(SSH_D_LOWOK, ("Registering address `%@'", ssh_ipaddr_render, address)); SSH_ASSERT(client->status_cb == NULL_FNPTR); if (client->flags & SSH_PM_CFGMODE_CLIENT_ADDING_ARP) goto error; if (!SSH_IP_DEFINED(address)) goto error; if (SSH_IP_IS4(address)) { SSH_ASSERT(client->ip4 == NULL); client->ip4 = ssh_memdup(address, sizeof(*address)); if (client->ip4 == NULL) goto error; client->ip4_address_context = address_context; } else { SSH_ASSERT(client->ip6 == NULL); client->ip6 = ssh_memdup(address, sizeof(*address)); if (client->ip6 == NULL) goto error; client->ip6_address_context = address_context; } client->free_cb = free_cb; client->free_cb_context = free_cb_context; /* Check if we should add a proxy ARP entry for the remote access client. */ if (tunnel->flags & SSH_PM_TR_PROXY_ARP) { unsigned char media_addr[SSH_ETHERH_ADDRLEN]; SshUInt32 flags; /* Create a fake ethernet address. */ memset(media_addr, 0, sizeof(media_addr)); if (SSH_IP_IS4(address)) { media_addr[1] = 2; SSH_IP4_ENCODE(address, media_addr + 2); client->flags |= SSH_PM_CFGMODE_CLIENT_IPV4_PROXY_ARP; } else { SshUInt32 value; value = SSH_IP6_WORD0_TO_INT(address); value ^= SSH_IP6_WORD1_TO_INT(address); value ^= SSH_IP6_WORD2_TO_INT(address); value ^= SSH_IP6_WORD3_TO_INT(address); media_addr[1] = 2; SSH_PUT_32BIT(media_addr + 2, value); client->flags |= SSH_PM_CFGMODE_CLIENT_IPV6_PROXY_ARP; } /* Flags for ARP entry. */ flags = SSH_PME_ARP_PERMANENT | SSH_PME_ARP_GLOBAL | SSH_PME_ARP_PROXY; /* Store status_cb. */ client->status_cb = status_cb; client->status_cb_context = status_cb_context; if (SSH_IP_IS4(address)) client->flags |= SSH_PM_CFGMODE_CLIENT_IPV4_REGISTERING; else client->flags |= SSH_PM_CFGMODE_CLIENT_IPV6_REGISTERING; /* Register an abort callback for the engine operation. */ ssh_operation_register_no_alloc(&client->operation, pm_cfgmode_client_store_arp_abort, client); /* Take a reference to the client and mark ARP ongoing. */ ssh_pm_cfgmode_client_store_take_reference(pm, client); client->flags |= SSH_PM_CFGMODE_CLIENT_ADDING_ARP; /* Add ARP entry. */ SSH_DEBUG(SSH_D_LOWSTART, ("Adding ARP entry")); ssh_pme_arp_add(pm->engine, address, 0, media_addr, sizeof(media_addr), flags, pm_cfgmode_client_store_arp_cb, client); return &client->operation; } if (status_cb) (*status_cb)(pm, TRUE, status_cb_context); return NULL; error: if (status_cb) (*status_cb)(pm, FALSE, status_cb_context); return NULL; }
/* HTTP/TCP transport independent send ***************************************/ static Boolean pkix_client_srv_send(SshPkiThreadData tdata, SshPkiTcpProtoVersion v, SshUInt32 flags, SshPkiTcpProtoMessage type, const unsigned char *data, size_t len) { SshFSMThread thread = (SshFSMThread)tdata->thread; SshFSM fsm = ssh_fsm_get_fsm(thread); SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread); size_t out_len; unsigned char *out; /* Start input processor now. */ if (!gdata->input_thread) gdata->input_thread = ssh_fsm_thread_create(fsm, pkix_process_input, NULL_FNPTR, NULL_FNPTR, NULL); /* If it is a TCP or HTTP... */ if (!tdata->http) { if (tdata->wrapper) { switch (v) { case SSH_PKI_VERSION_1: out_len = len + 2; out = ssh_malloc(out_len); if (out) { out[0] = (unsigned char) flags; out[1] = (unsigned char) type; memmove(out + 2, data, len); ssh_packet_wrapper_send(tdata->wrapper, v, out, out_len); ssh_free(out); } break; case SSH_PKI_VERSION_0: ssh_packet_wrapper_send(tdata->wrapper, type, data, len); default: return FALSE; } } else { /* Trying to send to closed; reopen. */ ssh_fsm_set_next(thread, pkix_connect); return TRUE; } } else { switch (v) { case SSH_PKI_VERSION_1: out_len = len + 7; out = ssh_malloc(out_len); if (out) { SSH_PUT_32BIT(out, out_len - 4); out[4] = v; out[5] = (unsigned char)flags; out[6] = (unsigned char)type; memmove(out + 7, data, len); } break; case SSH_PKI_VERSION_0: out_len = len + 5; out = ssh_malloc(out_len); if (out) { SSH_PUT_32BIT(out, out_len - 4); out[4] = (unsigned char)type; memmove(out + 5, data, len); } break; default: return FALSE; } if (out) { tdata->transport_op = ssh_http_post(tdata->http, gdata->session->access, out, out_len, pkix_http_receive_data, (void *)tdata->thread, SSH_HTTP_HDR_END); ssh_free(out); } } return TRUE; }