/* For a self-signed certificates the subject identifier should match the value in the authority key id, if present. */ void ssh_x509_cert_set_subject_key_id(SshX509Certificate c, const unsigned char *key_id, size_t key_id_len, Boolean critical) { SshX509ExtKeyId subject_id; /* Build the subject key id. */ if ((subject_id = ssh_malloc(sizeof(*subject_id))) != NULL) { ssh_x509_key_id_init(subject_id); if ((subject_id->key_id = ssh_memdup(key_id, key_id_len)) != NULL) { subject_id->key_id_len = key_id_len; if (c->extensions.subject_key_id != NULL) ssh_x509_key_id_free(c->extensions.subject_key_id); c->extensions.subject_key_id = subject_id; ssh_x509_ext_info_set(&c->extensions.ext_available, &c->extensions.ext_critical, SSH_X509_EXT_SUBJECT_KEY_ID, critical); } else ssh_free(subject_id); } }
/* Completion callback for SshPmAuthorizationCB. */ void ssh_pm_authorization_cb(SshUInt32 *group_ids, SshUInt32 num_group_ids, void *context) { SshFSMThread thread = (SshFSMThread) context; SshPm pm = (SshPm) ssh_fsm_get_gdata(thread); SshPmQm qm = (SshPmQm) ssh_fsm_get_tdata(thread); SshPmP1 p1 = qm->p1; /* Check qm->error in case qm->p1 has been freed */ if (p1 != NULL && qm->error == SSH_IKEV2_ERROR_OK) { ssh_free(p1->authorization_group_ids); p1->authorization_group_ids = NULL; p1->num_authorization_group_ids = 0; if (num_group_ids > 0) { p1->authorization_group_ids = ssh_memdup(group_ids, sizeof(group_ids[0]) * num_group_ids); p1->num_authorization_group_ids = num_group_ids; } p1->auth_group_ids_set = 1; /* The IKE SA is updated. */ ssh_pm_ike_sa_event_updated(pm, p1); } SSH_FSM_CONTINUE_AFTER_CALLBACK(thread); }
SshCMStatus ssh_cm_crl_set_ber(SshCMCrl crl, const unsigned char *ber, size_t ber_length) { SshBERFile bf; SSH_DEBUG(5, ("Set CRL in ber.")); if (crl->ber != NULL) return SSH_CM_STATUS_FAILURE; if (crl->cm && ber_length > crl->cm->config->max_crl_length) { SSH_DEBUG(SSH_D_FAIL, ("CRL (%zd bytes) too long (max %zd bytes)", ber_length, crl->cm->config->max_crl_length)); return SSH_CM_STATUS_FAILURE; } if (ssh_ber_file_create(ber, ber_length, &bf) != SSH_BER_FILE_ERR_OK) return SSH_CM_STATUS_FAILURE; ber_length -= ssh_ber_file_get_free_space(bf); ssh_ber_file_destroy(bf); if (ssh_x509_crl_decode(ber, ber_length, crl->crl) != SSH_X509_OK) return SSH_CM_STATUS_DECODE_FAILED; /* Copy the BER encoded part too. */ crl->ber_length = 0; if ((crl->ber = ssh_memdup(ber, ber_length)) != NULL) crl->ber_length = ber_length; return SSH_CM_STATUS_OK; }
static void pkix_tcp_receive_data(SshPacketType type, const unsigned char *data, size_t len, void *context) { SshFSMThread thread = (SshFSMThread)context; SshPkiThreadData tdata = ssh_fsm_get_tdata(thread); SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread); SSH_DEBUG(SSH_D_HIGHOK, ("thread %p %zd bytes from CA", thread, len)); if (type < 10) { tdata->input_version = SSH_PKI_VERSION_0; tdata->input_flags = 0; tdata->input_type = type; tdata->input_len = len; tdata->input = ssh_memdup(data, len); } else { switch (type) { case 10: tdata->input_version = SSH_PKI_VERSION_1; tdata->input_flags = data[0]; tdata->input_type = data[1]; tdata->input_len = len - 2; tdata->input = ssh_memdup(data + 2, tdata->input_len); break; default: return; } } if (tdata->input == NULL) tdata->input_type = SSH_PKI_MSG_ERRORREP; SSH_DEBUG_HEXDUMP(SSH_D_UNCOMMON, ("DATA %d bytes", tdata->input_len), tdata->input, tdata->input_len); ssh_fsm_continue(gdata->input_thread); }
void ssh_eap_protocol_master_session_key(SshEap eap, const unsigned char *session_key, size_t session_key_len) { SSH_PRECOND(eap->msk == NULL); eap->msk = ssh_memdup(session_key, session_key_len); eap->msk_len = session_key_len; }
/* shade{0.9} * ike_policy_reply_private_payload_out * Process policy managers reply to add private payloads. shade{1.0} */ void ike_policy_reply_private_payload_out(int private_payload_id, unsigned char *data, size_t data_len, void *context) { SshIkeNegotiation negotiation = (SshIkeNegotiation) context; SshIkePayload pl; SSH_DEBUG(5, ("Start")); if (ike_reply_check_deleted(negotiation)) return; if (private_payload_id == 0) { ike_reply_done(negotiation); return; } pl = ike_append_payload(negotiation->sa->server_context->isakmp_context, negotiation->ed->isakmp_packet_out, negotiation->sa, negotiation, SSH_IKE_PAYLOAD_TYPE_PRV); if (pl == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } /* Store the information to private payload */ pl->pl.prv.prv_payload_id = private_payload_id; pl->pl.prv.data = ssh_memdup(data, data_len); if (pl->pl.prv.data == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } pl->payload_length = data_len; /* Register allocated data */ if (!ike_register_item(negotiation->ed->isakmp_packet_out, pl->pl.prv.data)) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } return; }
/* REQUEST */ static void scep_encode_request_done(SshX509Status status, const unsigned char *der, size_t der_len, void *context) { SshScepEncode tdata = context; if (status == SSH_X509_OK) { tdata->request = ssh_memdup(der, der_len); tdata->request_len = der_len; } else { tdata->status = SSH_SCEP_FAILURE; ssh_fsm_set_next(tdata->thread, scep_encode_done); } SSH_FSM_CONTINUE_AFTER_CALLBACK(tdata->thread); }
SshIkev2PayloadID ssh_pm_ikev2_payload_id_dup(SshIkev2PayloadID id) { SshIkev2PayloadID dup = NULL; if (id == NULL) return NULL; if ((dup = ssh_calloc(1, sizeof(*dup))) == NULL) return NULL; if ((dup->id_data = ssh_memdup(id->id_data, id->id_data_size)) == NULL) { ssh_free(dup); return NULL; } dup->id_type = id->id_type; dup->id_data_size = id->id_data_size; return dup; }
SshIkev2PayloadID ssh_pm_decode_identity(SshPmIdentityType id_type, const unsigned char *identity, size_t identity_len, Boolean *malformed_id_return) { SshIkev2PayloadID id; SshIpAddrStruct ip; const unsigned char *cp; #ifdef SSHDIST_CERT SshDNStruct dn; #endif /* SSHDIST_CERT */ #ifdef WITH_MSCAPI SshIkev2PayloadID tmp_id; #endif /* WITH_MSCAPI */ *malformed_id_return = FALSE; if (identity == NULL) return NULL; id = NULL; switch (id_type) { case SSH_PM_IDENTITY_DN: case SSH_PM_IDENTITY_IP: case SSH_PM_IDENTITY_FQDN: case SSH_PM_IDENTITY_RFC822: case SSH_PM_IDENTITY_KEY_ID: #ifdef SSHDIST_IKE_ID_LIST case SSH_PM_IDENTITY_ID_LIST: #endif /* SSHDIST_IKE_ID_LIST */ id = ssh_calloc(1, sizeof(*id)); if (id == NULL) { SSH_DEBUG(SSH_D_ERROR, ("Could not allocate IKE ID")); return NULL; } break; case SSH_PM_IDENTITY_ANY: default: return NULL; } /* Decode identity. */ SSH_DEBUG_HEXDUMP(SSH_D_LOWSTART, ("Decoding identity of type %d", id_type), identity, identity_len); switch (id_type) { case SSH_PM_IDENTITY_DN: #ifdef SSHDIST_CERT id->id_type = SSH_IKEV2_ID_TYPE_ASN1_DN; ssh_dn_init(&dn); if (!ssh_dn_decode_ldap(identity, &dn)) { SSH_DEBUG(SSH_D_FAIL, ("Malformed DN identity `%s'", identity)); *malformed_id_return = TRUE; ssh_dn_clear(&dn); goto error; } if (!ssh_dn_encode_der(&dn, &id->id_data, &id->id_data_size, NULL)) { SSH_DEBUG(SSH_D_ERROR, ("Could not store ASN.1 data")); ssh_dn_clear(&dn); goto error; } ssh_dn_clear(&dn); break; #endif /* SSHDIST_CERT */ #ifdef SSHDIST_MSCAPI #ifdef WITH_MSCAPI if (!(tmp_id = ssh_pm_mscapi_str_to_dn(identity))) { SSH_DEBUG(SSH_D_FAIL, ("Malformed DN identity `%s'", identity)); *malformed_id_return = TRUE; goto error; } memcpy(id, tmp_id, sizeof *id); ssh_free(tmp_id); break; #endif /* WITH_MSCAPI */ #endif /* SSHDIST_MSCAPI */ goto error; break; case SSH_PM_IDENTITY_IP: if (!ssh_ipaddr_parse(&ip, identity)) { SSH_DEBUG(SSH_D_ERROR, ("Malformed IP address `%s'", identity)); *malformed_id_return = TRUE; goto error; } if (SSH_IP_IS4(&ip)) { id->id_type = SSH_IKEV2_ID_TYPE_IPV4_ADDR; id->id_data_size = 4; } else { id->id_type = SSH_IKEV2_ID_TYPE_IPV6_ADDR; id->id_data_size = 16; } if ((id->id_data = ssh_malloc(id->id_data_size)) == NULL) goto error; SSH_IP_ENCODE(&ip, id->id_data, id->id_data_size); break; case SSH_PM_IDENTITY_FQDN: id->id_type = SSH_IKEV2_ID_TYPE_FQDN; id->id_data_size = identity_len; if ((id->id_data = ssh_memdup(identity, identity_len)) == NULL) goto error; break; case SSH_PM_IDENTITY_RFC822: id->id_type = SSH_IKEV2_ID_TYPE_RFC822_ADDR; cp = ssh_ustrchr(identity, '@'); if (cp == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Malformed RFC822 identity `%s'", identity)); *malformed_id_return = TRUE; goto error; } id->id_data_size = identity_len; if ((id->id_data = ssh_memdup(identity, identity_len)) == NULL) goto error; break; case SSH_PM_IDENTITY_KEY_ID: id->id_type = SSH_IKEV2_ID_TYPE_KEY_ID; id->id_data_size = identity_len; if ((id->id_data = ssh_memdup(identity, identity_len)) == NULL) goto error; break; #ifdef SSHDIST_IKE_ID_LIST case SSH_PM_IDENTITY_ID_LIST: id->id_type = IPSEC_ID_LIST; id->id_data_size = identity_len; /* Just copy the input string repesentation of the ID. The fallback code will convert this to an IKEv1 ID data structure. */ if ((id->id_data = ssh_memdup(identity, identity_len)) == NULL) goto error; break; #endif /* SSHDIST_IKE_ID_LIST */ default: SSH_NOTREACHED; } SSH_DEBUG(SSH_D_LOWOK, ("IKE ID %@", ssh_pm_ike_id_render, id)); /* All done. */ return id; /* Error handling. */ error: ssh_pm_ikev2_payload_id_free(id); return NULL; }
/* shade{0.9} * ike_qm_sa_reply * Process policy managers reply to sa query. shade{1.0} */ void ike_qm_sa_reply(SshIkeIpsecSelectedSAIndexes return_value, void *context) { SshIkeNegotiation negotiation = (SshIkeNegotiation) context; int i, j; SshIkePayloadSA sa; SshIkePayloadPProtocol proto; SshIkePayloadT t; SshIkeIpsecSelectedSAIndexes sel; SshIkeIpsecSelectedProtocol sel_pro; SSH_DEBUG(5, ("Start")); negotiation->qm_ed->indexes = return_value; if (ike_reply_check_deleted(negotiation)) return; if (return_value == NULL) { negotiation->qm_ed->indexes = ssh_calloc(negotiation->qm_ed->number_of_sas, sizeof(struct SshIkeIpsecSelectedSAIndexesRec)); if (negotiation->qm_ed->indexes == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } ike_reply_done(negotiation); return; } /* Copy / read selected sa information from sa proposals to selected_sas table */ /* Allocate table */ negotiation->qm_ed->selected_sas = ssh_calloc(negotiation->qm_ed->number_of_sas, sizeof(struct SshIkeIpsecSelectedSARec)); if (negotiation->qm_ed->selected_sas == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } for (i = 0; i < negotiation->qm_ed->number_of_sas; i++) { sa = &(negotiation->qm_ed->sas_i[i]->pl.sa); sel = &(negotiation->qm_ed->indexes[i]); /* No proposal selected */ if (sel->proposal_index == -1) { negotiation->qm_ed->selected_sas[i].number_of_protocols = 0; negotiation->qm_ed->selected_sas[i].protocols = NULL; SSH_DEBUG(5, ("No proposal selected for sa %d", i)); continue; } negotiation->qm_ed->selected_sas[i].number_of_protocols = negotiation->qm_ed->indexes[i].number_of_protocols; negotiation->qm_ed->selected_sas[i].protocols = ssh_calloc(negotiation->qm_ed->selected_sas[i].number_of_protocols, sizeof(struct SshIkeIpsecSelectedProtocolRec)); if (negotiation->qm_ed->selected_sas[i].protocols == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } /* Loop through all protocols */ for (j = 0; j < negotiation->qm_ed->selected_sas[i].number_of_protocols; j++) { SSH_DEBUG(5, ("Selected proposal %d, and transform %d for protocol %d", sel->proposal_index, sel->transform_indexes[j], j)); proto = &(sa->proposals[sel->proposal_index].protocols[j]); sel_pro = &(negotiation->qm_ed->selected_sas[i].protocols[j]); sel_pro->protocol_id = proto->protocol_id; sel_pro->spi_size_out = proto->spi_size; sel_pro->spi_out = ssh_memdup(proto->spi, proto->spi_size); if (sel_pro->spi_out == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } sel_pro->spi_size_in = sel->spi_sizes[j]; sel_pro->spi_in = ssh_memdup(sel->spis[j], sel_pro->spi_size_in); if (sel_pro->spi_in == NULL) { ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_OUT_OF_MEMORY); return; } t = &(proto->transforms[sel->transform_indexes[j]]); sel_pro->transform_id.generic = t->transform_id.generic; ssh_ike_clear_ipsec_attrs(&(sel_pro->attributes)); if (!ssh_ike_read_ipsec_attrs(negotiation, t, &(sel_pro->attributes))) { SSH_IKE_DEBUG(3, negotiation, ("Internal policy manager error, " "policy manager selected proposal, " "that contains unsupported values")); for (i = 0; i < negotiation->qm_ed->number_of_sas; i++) { if (negotiation->qm_ed->selected_sas[i].protocols) { for (j = 0; j < negotiation->qm_ed-> selected_sas[i].number_of_protocols; j++) { ssh_free(negotiation->qm_ed-> selected_sas[i].protocols[j].spi_in); ssh_free(negotiation->qm_ed-> selected_sas[i].protocols[j].spi_out); } ssh_free(negotiation->qm_ed->selected_sas[i].protocols); } } ssh_free(negotiation->qm_ed->selected_sas); negotiation->qm_ed->selected_sas = NULL; ike_reply_return_error(negotiation, SSH_IKE_NOTIFY_MESSAGE_ATTRIBUTES_NOT_SUPPORTED); return; } } } ike_reply_done(negotiation); return; }
Boolean ssh_virtual_adapter_param_decode(SshVirtualAdapterParams params, const unsigned char *data, size_t len) { unsigned char *dns; size_t dns_len; unsigned char *wins; size_t wins_len; unsigned char *win_domain; size_t win_domain_len; SshUInt32 netbios_node_type; SshUInt32 i; size_t decode_len; SSH_ASSERT(params != NULL); SSH_ASSERT(data != NULL); SSH_ASSERT(len > 0); memset(params, 0, sizeof(*params)); if (ssh_decode_array(data, len, SSH_DECODE_UINT32(¶ms->mtu), SSH_DECODE_UINT32(¶ms->dns_ip_count), SSH_DECODE_UINT32_STR_NOCOPY(&dns, &dns_len), SSH_DECODE_UINT32(¶ms->wins_ip_count), SSH_DECODE_UINT32_STR_NOCOPY(&wins, &wins_len), SSH_DECODE_UINT32_STR_NOCOPY( &win_domain, &win_domain_len), SSH_DECODE_UINT32(&netbios_node_type), SSH_FORMAT_END) != len) return FALSE; /* DNS. */ if (params->dns_ip_count) { params->dns_ip = ssh_calloc(params->dns_ip_count, sizeof(*params->dns_ip)); if (params->dns_ip == NULL) goto error; for (i = 0; i < params->dns_ip_count; i++) { decode_len = ssh_decode_ipaddr_array(dns, dns_len, ¶ms->dns_ip[i]); if (decode_len == 0) goto error; dns += decode_len; dns_len -= decode_len; } } /* WINS. */ if (params->wins_ip_count) { params->wins_ip = ssh_calloc(params->wins_ip_count, sizeof(*params->wins_ip)); if (params->wins_ip == NULL) goto error; for (i = 0; i < params->wins_ip_count; i++) { decode_len = ssh_decode_ipaddr_array(wins, wins_len, ¶ms->wins_ip[i]); if (decode_len == 0) goto error; wins += decode_len; wins_len -= decode_len; } } if (win_domain_len) { params->win_domain = ssh_memdup(win_domain, win_domain_len); if (params->win_domain == NULL) goto error; } params->netbios_node_type = (SshUInt8) netbios_node_type; return TRUE; error: ssh_free(params->dns_ip); ssh_free(params->wins_ip); ssh_free(params->win_domain); memset(params, 0, sizeof(*params)); return FALSE; }
/* 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; } } } }
SshEapToken ssh_eap_dup_token(SshEapToken src) { SshEapToken dst; dst = ssh_calloc(1, sizeof(*dst)); if (dst == NULL) return NULL; dst->type = src->type; switch (src->type) { case SSH_EAP_TOKEN_PRIVATE_KEY: if (src->token.prvkey.private_key != NULL) { if (ssh_private_key_copy(src->token.prvkey.private_key, &dst->token.prvkey.private_key) != SSH_CRYPTO_OK) { ssh_free(dst); return NULL; } if (src->token.prvkey.id_data != NULL) { dst->token.prvkey.id_data = ssh_memdup(src->token.prvkey.id_data, src->token.prvkey.id_data_size); if (dst->token.prvkey.id_data == NULL) { ssh_private_key_free(dst->token.prvkey.private_key); ssh_free(dst); return NULL; } dst->token.prvkey.id_data_size = src->token.prvkey.id_data_size; } } break; case SSH_EAP_TOKEN_CERTIFICATE_AUTHORITY: { int cnt; int i; /* Count the ca count. */ for (cnt = 0; src->token.cas && src->token.cas[cnt]; cnt++) ; if (cnt == 0) { SSH_DEBUG(SSH_D_ERROR, ("Cannot duplicate token, no" " CA's to duplicate.")); ssh_free(dst); return NULL; } dst->token.cas = ssh_calloc(cnt + 1, sizeof(unsigned char *)); if (dst->token.cas == NULL) { ssh_free(dst); return NULL; } for (i = 0; i < cnt; i++) dst->token.cas[i] = src->token.cas[i]; break; } #ifdef SSHDIST_EAP_SIM case SSH_EAP_TOKEN_SIM_CHALLENGE: #endif /* SSHDIST_EAP_SIM */ #ifdef SSHDIST_EAP_AKA case SSH_EAP_TOKEN_AKA_CHALLENGE: case SSH_EAP_TOKEN_AKA_SYNCH_REQ: #endif /* SSHDIST_EAP_AKA */ case SSH_EAP_TOKEN_USERNAME: case SSH_EAP_TOKEN_SHARED_SECRET: case SSH_EAP_TOKEN_SALT: if (src->token.buffer.dptr != NULL) { dst->token.buffer.dptr = ssh_malloc(src->token.buffer.len); if (dst->token.buffer.dptr == NULL) { ssh_free(dst); return NULL; } dst->token.buffer.len = src->token.buffer.len; memcpy(dst->token.buffer.dptr, src->token.buffer.dptr, src->token.buffer.len); } else { dst->token.buffer.dptr = NULL; dst->token.buffer.len = 0; } break; case SSH_EAP_TOKEN_COUNTER32: dst->token.counter32 = src->token.counter32; break; #ifdef SSHDIST_EAP_AKA_DASH case SSH_EAP_TOKEN_AKA_DASH_KDF_INPUT: dst->token.success = src->token.success; break; #endif /* SSHDIST_EAP_AKA_DASH */ #ifdef SSHDIST_EAP_AKA case SSH_EAP_TOKEN_AKA_AUTH_REJECT: #endif /* SSHDIST_EAP_AKA */ case SSH_EAP_TOKEN_NONE: break; default: SSH_NOTREACHED; } SSH_DEBUG(SSH_D_MY, ("duplicated token at %p", dst)); return dst; }
/* * Parse incoming socks connection from buffer. Consume the request * packet data from buffer. If everything is ok it allocates SocksInfo * strcture and store the request fields in it (sets * socks_version_number, command_code, ip, port, username). Returns * SSH_SOCKS_SUCCESS, SSH_SOCKS_TRY_AGAIN, or SSH_SOCKS_ERROR_*. If * anything other than SSH_SOCKS_SUCCESS is returned the socksinfo is * set to NULL. Use ssh_socks_free to free socksinfo data. */ SocksError ssh_socks_server_parse_open(SshBuffer buffer, SocksInfo *socksinfo) { unsigned char *data, *ip; unsigned long i, port; unsigned int version, cmd, ip_addr_len, atyp; unsigned char *username = NULL; size_t ret, len, bytes = 0; *socksinfo = NULL; len = ssh_buffer_len(buffer); data = ssh_buffer_ptr(buffer); if (len < 1) return SSH_SOCKS_TRY_AGAIN; version = data[0]; bytes++; if (version != 4 && version != 5) { SSH_DEBUG(2, ("Server gave us version %d.", version)); return SSH_SOCKS_ERROR_UNSUPPORTED_SOCKS_VERSION; } if (version == 4) { /* Check if enough data for header and name */ if (len < SOCKS4_COMMAND_SIZE + 1) { return SSH_SOCKS_TRY_AGAIN; } /* Find the end of username */ for (i = SOCKS4_COMMAND_SIZE; i < len; i++) { if (data[i] == '\0') break; } /* End of username not found, return either error or try_again */ if (i == len || data[i] != '\0') { if (len > SOCKS4_COMMAND_SIZE + SOCKS4_MAX_NAME_LEN) { return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } return SSH_SOCKS_TRY_AGAIN; } cmd = data[1]; port = SSH_GET_16BIT(&data[2]); ip_addr_len = 4; ip = ssh_memdup(&data[4], ip_addr_len); atyp = SSH_SOCKS5_ATYP_IPV4; if (ip == NULL) { SSH_DEBUG(2, ("Failed to allocate IP-address buffer.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } username = ssh_strdup((char *)(data + SOCKS4_COMMAND_SIZE)); bytes = SOCKS4_COMMAND_SIZE + strlen((char *) data + SOCKS4_COMMAND_SIZE) + 1; } else { unsigned char port_buf[2]; if (len - bytes < 3) return SSH_SOCKS_TRY_AGAIN; ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_CHAR(&cmd), SSH_DECODE_CHAR(NULL), /* RSV */ SSH_DECODE_CHAR(&atyp), SSH_FORMAT_END); if (ret <= 0) { SSH_DEBUG(2, ("Failed to decode command packet.")); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } bytes += ret; if (atyp == SSH_SOCKS5_ATYP_IPV4) { SSH_DEBUG(4, ("SOCKS5 received address type IPV4.")); ip_addr_len = 4; } else if (atyp == SSH_SOCKS5_ATYP_IPV6) { SSH_DEBUG(4, ("SOCKS5 received address type IPV6.")); ip_addr_len = 16; } else if (atyp == SSH_SOCKS5_ATYP_FQDN) { if (len - bytes < 1) return SSH_SOCKS_TRY_AGAIN; ip_addr_len = *(data + bytes); if (ip_addr_len <= 0 || ip_addr_len >= 255) { SSH_DEBUG(2, ("Invalid FQDN address len %d.", ip_addr_len)); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } SSH_DEBUG(4, ("SOCKS5 received address type FQDN, len %d.", ip_addr_len)); bytes++; } else { SSH_DEBUG(2, ("Invalid address type %d.", atyp)); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } /* ip addr len + port */ if (len - bytes < ip_addr_len + 2) return SSH_SOCKS_TRY_AGAIN; ip = ssh_calloc(ip_addr_len + 1, sizeof(unsigned char)); if (ip == NULL) { SSH_DEBUG(2, ("Failed to allocate IP-address buffer.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } ret = ssh_decode_array(data + bytes, len - bytes, SSH_DECODE_DATA(ip, ip_addr_len), SSH_DECODE_DATA(port_buf, 2), SSH_FORMAT_END); if (ret <= 0) { SSH_DEBUG(2, ("Failed to decode command packet.")); ssh_free(ip); return SSH_SOCKS_ERROR_PROTOCOL_ERROR; } port = SSH_GET_16BIT(port_buf); bytes += ret; } if ((*socksinfo = ssh_calloc(1, sizeof(struct SocksInfoRec))) == NULL) { SSH_DEBUG(2, ("Failed to allocate SocksInfo.")); ssh_free(ip); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } if (atyp == SSH_SOCKS5_ATYP_FQDN) { (*socksinfo)->ip = ip; } else { SshIpAddrStruct ip_addr; unsigned char buf[SSH_IP_ADDR_STRING_SIZE]; SSH_IP_DECODE(&ip_addr, ip, ip_addr_len); ssh_ipaddr_print(&ip_addr, buf, sizeof(buf)); (*socksinfo)->ip = ssh_memdup(buf, ssh_ustrlen(buf)); ssh_free(ip); if ((*socksinfo)->ip == NULL) { SSH_DEBUG(2, ("Failed to allocate final IP-addr buf.")); return SSH_SOCKS_ERROR_INVALID_ARGUMENT; } } (*socksinfo)->socks_version_number = version; (*socksinfo)->command_code = cmd; ssh_dsprintf(&(*socksinfo)->port, "%lu", port); (*socksinfo)->username = username; ssh_buffer_consume(buffer, bytes); SSH_DEBUG(5, ("Decoded %zd bytes.", bytes)); return SSH_SOCKS_SUCCESS; }
void ikev2_fb_get_cas_kid_cb(SshIkev2Error error_code, int number_of_cas, SshIkev2CertEncoding *ca_encodings, const unsigned char **ca_authority_data, size_t *ca_authority_size, void *context) { SshIkev2FbNegotiation neg = (SshIkev2FbNegotiation) context; SshIkeCertificateEncodingType *ikev1_ca_encodings = NULL; unsigned char **ikev1_ca_names = NULL; size_t *ikev1_ca_name_lens = NULL; int i, j; SSH_IKEV2_FB_V2_COMPLETE_CALL(neg); if (error_code != SSH_IKEV2_ERROR_OK) { SSH_DEBUG(SSH_D_FAIL, ("CA lookup failed, error '%s'", ssh_ikev2_error_to_string(error_code))); goto error; } SSH_DEBUG(SSH_D_LOWOK, ("Got %d CA's from the policy manager", number_of_cas)); /* Allocate memory for IKEv1 CA names, name lengths and CA encodings. */ ikev1_ca_encodings = ssh_calloc(number_of_cas, sizeof(SshIkeCertificateEncodingType)); ikev1_ca_names = ssh_calloc(number_of_cas, sizeof(unsigned char *)); ikev1_ca_name_lens = ssh_calloc(number_of_cas, sizeof(size_t)); if (ikev1_ca_encodings == NULL || ikev1_ca_names == NULL || ikev1_ca_name_lens == NULL) { SSH_DEBUG(SSH_D_ERROR, ("Could not allocate memory to return CAs")); goto error; } /* Map the IKEv2 CA encoding to IKEv1 encoding. */ for (i = 0; i < number_of_cas; i++) { ikev1_ca_encodings[i] = ikev2_fb_v1_cert_encoding_to_v2(ca_encodings[i]); ikev1_ca_names[i] = ssh_memdup(ca_authority_data[i], ca_authority_size[i]); ikev1_ca_name_lens[i] = ca_authority_size[i]; if (ikev1_ca_names[i] == NULL) goto error; } (*neg->callbacks.u.get_cas)(number_of_cas, ikev1_ca_encodings, ikev1_ca_names, ikev1_ca_name_lens, neg->callbacks.callback_context); return; error: if (ikev1_ca_names) for (j = 0; j < number_of_cas; j++) ssh_free(ikev1_ca_names[j]); ssh_free(ikev1_ca_names); ssh_free(ikev1_ca_name_lens); ssh_free(ikev1_ca_encodings); (*neg->callbacks.u.get_cas)(0, NULL, NULL, NULL, neg->callbacks.callback_context); return; }
void ikev2_fb_request_certificates_cb(SshIkev2Error error_code, SshPrivateKey private_key_out, int number_of_certificates, SshIkev2CertEncoding *cert_encs, const unsigned char **certs, size_t *cert_lengths, void *context) { SshIkev2FbNegotiation neg = (SshIkev2FbNegotiation) context; SshIkeCertificateEncodingType *ikev1_cert_encodings = NULL; SshPrivateKey private_key_copy = NULL; unsigned char **ikev1_certs = NULL; size_t *ikev1_cert_lengths = NULL; int i; SSH_IKEV2_FB_V2_COMPLETE_CALL(neg); if (error_code != SSH_IKEV2_ERROR_OK) { SSH_DEBUG(SSH_D_FAIL, ("Private key/Certificate lookup failed, " "error '%s'", ssh_ikev2_error_to_string(error_code))); goto error; } if (number_of_certificates == 0) { SSH_DEBUG(SSH_D_FAIL, ("No certificates found")); goto error; } SSH_ASSERT(private_key_out != NULL); if (ssh_private_key_copy(private_key_out, &private_key_copy) != SSH_CRYPTO_OK) { SSH_DEBUG(SSH_D_FAIL, ("Private key copy failed")); goto error; } /* Copy the returned certificates */ ikev1_cert_encodings = ssh_calloc(number_of_certificates, sizeof(SshIkeCertificateEncodingType)); ikev1_certs = ssh_calloc(number_of_certificates, sizeof(unsigned char *)); ikev1_cert_lengths = ssh_calloc(number_of_certificates, sizeof(size_t)); if (ikev1_cert_encodings == NULL || ikev1_certs == NULL || ikev1_cert_lengths == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Memory allocation failure")); goto error; } for (i = 0; i < number_of_certificates; i++) { ikev1_cert_encodings[i] = ikev2_fb_v2_cert_encoding_to_v1(cert_encs[i]); ikev1_cert_lengths[i] = cert_lengths[i]; if (!(ikev1_certs[i] = ssh_memdup(certs[i], cert_lengths[i]))) { SSH_DEBUG(SSH_D_FAIL, ("Certificate copy failed")); goto error; } } /* Save the certificates and private key. */ neg->number_of_certificates = number_of_certificates; neg->cert_encodings = ikev1_cert_encodings; neg->certs = ikev1_certs; neg->cert_lengths = ikev1_cert_lengths; neg->private_key = private_key_copy; SSH_DEBUG(SSH_D_LOWOK, ("Found %d certificates", number_of_certificates)); SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); return; error: if (private_key_copy) ssh_private_key_free(private_key_copy); if (ikev1_certs) for (i = 0; i < number_of_certificates; i++) ssh_free(ikev1_certs[i]); ssh_free(ikev1_certs); ssh_free(ikev1_cert_encodings); ssh_free(ikev1_cert_lengths); SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread); }
/* Does the name server lookup using internal dns resolver. */ SshOperationHandle ssh_tcp_get_host_by_addr_dns(const unsigned char *name, SshLookupCallback callback, void *context) { SshNameServerOperation operation; unsigned char *dns_name, *p; unsigned char buffer[16]; size_t len; int i; len = 16; if (!ssh_inet_strtobin(name, buffer, &len)) { callback(SSH_TCP_FAILURE, NULL, context); return NULL; } operation = ssh_calloc(1, sizeof(*operation)); if (operation == NULL) { callback(SSH_TCP_FAILURE, NULL, context); return NULL; } operation->dns_name = ssh_memdup(buffer, len); if (operation->dns_name == NULL) { ssh_free(operation); callback(SSH_TCP_FAILURE, NULL, context); return NULL; } if (len == 4) { /* IPv4 address, convert a.b.c.d to d.c.b.a.in-addr.arpa. Buffer size needed is 15 + 13 + 1 = 29. */ dns_name = ssh_malloc(32); if (dns_name == NULL) { ssh_free(operation); callback(SSH_TCP_FAILURE, NULL, context); return NULL; } p = dns_name; for(i = 3; i >= 0; i--) { if (buffer[i] >= 100) *p = 3; else if (buffer[i] >= 10) *p = 2; else *p = 1; ssh_snprintf(p + 1, dns_name + 32 - p - 1, "%d", buffer[i]); p += (*p) + 1; } strcpy((char *)p, "\7in-addr\4arpa"); } else { /* IPv6 address, convert it to p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a. ip6.arpa. Buffer size needed is 32 * 2 + 9 = 73. */ dns_name = ssh_malloc(80); if (dns_name == NULL) { ssh_free(operation); callback(SSH_TCP_FAILURE, NULL, context); return NULL; } p = dns_name; for(i = 15; i >= 0; i--) { *p++ = 1; *p++ = "0123456789abcdef"[buffer[i] & 0xf]; *p++ = 1; *p++ = "0123456789abcdef"[buffer[i] >> 4]; } strcpy((char *)p, "\3ip6\4arpa"); } operation->callback = callback; operation->context = context; operation->length = len; operation->timed_out = FALSE; operation->flags = ssh_name_server_data->resolver_find_flags; ssh_operation_register_no_alloc(operation->operation_handle, ssh_name_server_result_abort, operation); /* Ok, the name is now ready, start query. */ operation->handle = ssh_dns_resolver_find(ssh_name_server_data->resolver, dns_name, SSH_DNS_RESOURCE_PTR, ssh_name_server_data->timeout, operation->flags, ssh_name_server_result_ptr, operation); ssh_free(dns_name); return operation->operation_handle; }
char *ssh_buffer_make_str(SshBuffer buffer) { return ssh_memdup(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer)); }
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; }
/* Find pre shared secret for local or remote host. When 'local' is FALSE the primary selector is the remote id field. Call reply_callback when the data is available (it can also be called immediately). If `local' is true then we search for the local pre-shared key. */ SshOperationHandle ssh_pm_ike_pre_shared_key(SshSADHandle sad_handle, SshIkev2ExchangeData ed, Boolean local, SshIkev2PadSharedKeyCB reply_callback, void *reply_callback_context) { SshPm pm = sad_handle->pm; SshPmP1 p1 = (SshPmP1)ed->ike_sa; unsigned char *key = NULL; size_t key_len = 0; SSH_PM_ASSERT_P1(p1); SSH_PM_ASSERT_P1N(p1); /* If policymanager is not in active state, we wan't to reject this. */ if (ssh_pm_get_status(pm) == SSH_PM_STATUS_SUSPENDED) { (*reply_callback)(SSH_IKEV2_ERROR_SUSPENDED, NULL, 0, reply_callback_context); return NULL; } if (!SSH_PM_P1_USABLE(p1)) { (*reply_callback)(SSH_IKEV2_ERROR_SA_UNUSABLE, NULL, 0, reply_callback_context); return NULL; } SSH_DEBUG(SSH_D_MIDSTART, ("Enter SA %p ED %p Asking for %s preshared key", ed->ike_sa, ed, local ? "local" : "remote")); /* Select a tunnel for the reponder if not already done */ if (!(p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) && !ssh_pm_select_ike_responder_tunnel(pm, p1, ed)) { (*reply_callback)(SSH_IKEV2_ERROR_NO_PROPOSAL_CHOSEN, NULL, 0, reply_callback_context); return NULL; } /* If the IKE initiator has used the "me Tarzan, you Jane" option, then check here that that responder has replied with an acceptable identity. */ if (!local && !ssh_pm_ike_check_requested_identity(pm, p1, ed->ike_ed->id_r)) { p1->n->failure_mask |= SSH_PM_E_REMOTE_ID_MISMATCH; (*reply_callback)(SSH_IKEV2_ERROR_AUTHENTICATION_FAILED, NULL, 0, reply_callback_context); return NULL; } if (p1->n->ed == NULL) p1->n->ed = ed; if (!ssh_pm_auth_domain_check_by_ed(pm, ed)) { (*reply_callback)(SSH_IKEV2_ERROR_AUTHENTICATION_FAILED, NULL, 0, reply_callback_context); return NULL; } #ifdef SSHDIST_IKE_EAP_AUTH /* Check if EAP is configured for the tunnels authentication domain and this is an IKEv2 SA */ if (p1->auth_domain->num_eap_protocols #ifdef SSHDIST_IKEV1 && ((ed->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1) == 0) #endif /* SSHDIST_IKEV1 */ ) { /* To use EAP, the initiator omits the AUTH payload by returning a NULL Pre Shared Key. */ if (local && (ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)) { (*reply_callback)(SSH_IKEV2_ERROR_OK, NULL, 0, reply_callback_context); return NULL; } /* RFC 4306 forbids EAP with pre shared key responder authentication. Fail authentication here, as we end up here only if configuration for certicate based responder authentication was missing. */ if (!local && (ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)) { SSH_DEBUG(SSH_D_FAIL, ("EAP authentication cannot be used with pre shared key " "based responder authentication.")); p1->n->failure_mask |= SSH_PM_E_AUTH_METHOD_MISMATCH; (*reply_callback)(SSH_IKEV2_ERROR_AUTHENTICATION_FAILED, NULL, 0, reply_callback_context); return NULL; } } #endif /* SSHDIST_IKE_EAP_AUTH */ #ifdef SSHDIST_IKEV1 if (p1->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1 && ed->ike_ed->exchange_type == SSH_IKE_XCHG_TYPE_AGGR) p1->ike_sa->flags |= SSH_IKEV2_FB_IKE_AGGRESSIVE_MODE; #endif /* SSHDIST_IKEV1 */ /* Take local secret from tunnel for IKEv2 and IKEv1 main mode. */ if (local #ifdef SSHDIST_IKEV1 /* In IKEv1 aggressive mode responder, we'll use the remote secret by requestor ID, and for initiator the one from tunnel local identity. */ && ((p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) || !(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1) || (ed->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1 && ed->ike_ed->exchange_type != SSH_IKE_XCHG_TYPE_AGGR)) #endif /* SSHDIST_IKEV1 */ ) { /* Always use the first available secret. */ if (p1->n->tunnel->u.ike.num_secrets) { key = p1->n->tunnel->u.ike.secrets->secret; key_len = p1->n->tunnel->u.ike.secrets->secret_len; /* Save the copy of the local secret to the Phase-1 object. */ p1->local_secret_len = key_len; p1->local_secret = ssh_memdup(key, key_len); if (!p1->local_secret) { p1->local_secret_len = 0; key = NULL; key_len = 0; } } /* If we have key, or if we are using IKEv1 (main mode return key or error). */ if (key != NULL #ifdef SSHDIST_IKEV1 || (ed->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1) #endif /* SSHDIST_IKEV1 */ ) { /* Record the local authentication method */ p1->local_auth_method = SSH_PM_AUTH_PSK; #ifdef SSHDIST_IKEV1 /* For IKEv1 negotiations this policy call is not called for 'local' equal to FALSE, so we set 'p1->remote_auth_method' here. */ if (p1->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1) p1->remote_auth_method = SSH_PM_AUTH_PSK; #endif /* SSHDIST_IKEV1 */ (*reply_callback)((key != NULL) ? SSH_IKEV2_ERROR_OK : SSH_IKEV2_ERROR_AUTHENTICATION_FAILED, key, key_len, reply_callback_context); return NULL; } } /* Store the reply callback and context */ p1->callbacks.aborted = FALSE; p1->callbacks.u.pre_shared_key_cb = reply_callback; p1->callbacks.callback_context = reply_callback_context; /* Record the remote authentication method */ p1->remote_auth_method = SSH_PM_AUTH_PSK; #ifdef SSHDIST_IKEV1 /* Set the local auth method for IKEv1 agressive mode responders */ if (p1->ike_sa->flags & SSH_IKEV2_IKE_SA_ALLOCATE_FLAGS_IKEV1) p1->local_auth_method = SSH_PM_AUTH_PSK; #endif /* SSHDIST_IKEV1 */ ssh_operation_register_no_alloc(p1->callbacks.operation, pm_ike_psk_abort, p1); ssh_fsm_thread_init(&pm->fsm, &p1->n->sub_thread, pm_ike_id_psk_lookup_start, NULL_FNPTR, NULL_FNPTR, p1); ssh_fsm_set_thread_name(&p1->n->sub_thread, "IKE PSK"); return p1->callbacks.operation; }