/** * Change the state of hadb state cache in the firewall * * @param msg the message containing hadb cache information * * @return zero on success, non-zero on error */ static int hip_handle_bex_state_update(struct hip_common *msg) { const struct in6_addr *src_hit = NULL, *dst_hit = NULL; const struct hip_tlv_common *param = NULL; int err = 0, msg_type = 0; msg_type = hip_get_msg_type(msg); /* src_hit */ param = hip_get_param(msg, HIP_PARAM_HIT); src_hit = hip_get_param_contents_direct(param); HIP_DEBUG_HIT("Source HIT: ", src_hit); /* dst_hit */ param = hip_get_next_param(msg, param); dst_hit = hip_get_param_contents_direct(param); HIP_DEBUG_HIT("Destination HIT: ", dst_hit); /* update bex_state in firewalldb */ switch (msg_type) { case HIP_MSG_FW_BEX_DONE: err = hip_firewall_cache_set_bex_state(src_hit, dst_hit, HIP_STATE_ESTABLISHED); break; case HIP_MSG_FW_UPDATE_DB: err = hip_firewall_cache_set_bex_state(src_hit, dst_hit, HIP_STATE_NONE); break; default: break; } return err; }
int main_server_tcp(int serversock) { int peerfd = 0, err = 0; socklen_t locallen; unsigned int peerlen; struct sockaddr_in6 localaddr, peeraddr; char mylovemostdata[IP_MAXPACKET]; int recvnum, sendnum; char addrstr[INET6_ADDRSTRLEN]; peerlen = sizeof(struct sockaddr_in6); peerfd = accept(serversock, (struct sockaddr *)&peeraddr, &peerlen); if (peerfd < 0) { perror("accept"); err = -1; goto out_err; } locallen = sizeof(localaddr); if (!getsockname(serversock, (struct sockaddr *)&localaddr, &locallen)) HIP_DEBUG_HIT("local addr", &localaddr.sin6_addr); HIP_DEBUG_HIT("peer addr", &peeraddr.sin6_addr); while((recvnum = recv(peerfd, mylovemostdata, sizeof(mylovemostdata), 0)) > 0 ) { mylovemostdata[recvnum] = '\0'; printf("Client sends:\n%s", mylovemostdata); fflush(stdout); if (recvnum == 0) { close(peerfd); err = -1; break; } /* send reply */ sendnum = send(peerfd, mylovemostdata, recvnum, 0); if (sendnum < 0) { perror("send"); err = -1; break; } printf("Client has been replied.\n"); } if (peerfd) close(peerfd); out_err: return err; }
/** * display a LOCATOR parameter contents in a HIP control message * * @param in_msg the message where the LOCATOR parameter is located */ void hip_print_locator_addresses(const struct hip_common *in_msg) { const struct hip_locator *locator; const struct hip_locator_info_addr_item *ptr = NULL; const struct hip_locator_info_addr_item *item = NULL; const struct hip_locator_info_addr_item2 *item2 = NULL; const char *address_pointer; locator = hip_get_param(in_msg, HIP_PARAM_LOCATOR); if (locator) { address_pointer = (const char *) (locator + 1); for (; address_pointer < ((const char *) locator) + hip_get_param_contents_len(locator); ) { ptr = (const struct hip_locator_info_addr_item *) address_pointer; if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_UDP) { item2 = (const struct hip_locator_info_addr_item2 *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item2->address); HIP_DEBUG("Locator address offset is %d\n", address_pointer - (const char *) (locator + 1)); address_pointer += sizeof(struct hip_locator_info_addr_item2); } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_ESP_SPI) { item = (const struct hip_locator_info_addr_item *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item->address); address_pointer += sizeof(struct hip_locator_info_addr_item); } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) { item = (const struct hip_locator_info_addr_item *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item->address); address_pointer += sizeof(struct hip_locator_info_addr_item); } else { address_pointer += sizeof(struct hip_locator_info_addr_item); } } } }
/** * Notifies the hipd about an anchor change in the hipfw * * @param entry the sadb entry for the outbound direction * @return 0 on success, -1 on error, 1 for inbound sadb entry */ int send_anchor_change_to_hipd(const struct hip_sa_entry *entry) { int err = 0; int hash_length = 0; long i = 0; unsigned char *anchor = NULL; struct hip_common *msg = NULL; struct hash_chain *hchain = NULL; struct hash_tree *htree = NULL; HIP_ASSERT(entry != NULL); HIP_ASSERT(entry->direction == HIP_SPI_DIRECTION_OUT); HIP_IFEL((hash_length = esp_prot_get_hash_length(entry->esp_prot_transform)) <= 0, -1, "error or tried to resolve UNUSED transform\n"); HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1, "failed to allocate memory\n"); hip_msg_init(msg); HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_ANCHOR_CHANGE, 0), -1, "build hdr failed\n"); HIP_DEBUG_HIT("src_hit", &entry->inner_src_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_src_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG_HIT("dst_hit", &entry->inner_dst_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_dst_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG("direction: %i\n", entry->direction); HIP_IFEL(hip_build_param_contents(msg, &entry->direction, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("esp_prot_transform: %u\n", entry->esp_prot_transform); HIP_IFEL(hip_build_param_contents(msg, &entry->esp_prot_transform, HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)), -1, "build param contents failed\n"); HIP_DEBUG("esp_prot_num_parallel_hchains: %i\n", num_parallel_hchains); HIP_IFEL(hip_build_param_contents(msg, &num_parallel_hchains, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); for (i = 0; i < num_parallel_hchains; i++) { // the anchor change has already occurred on fw-side if (entry->esp_prot_transform == ESP_PROT_TFM_TREE) { htree = entry->active_hash_items[i]; anchor = htree->root; } else { hchain = entry->active_hash_items[i]; anchor = hchain_get_anchor(hchain); } HIP_HEXDUMP("anchor: ", anchor, hash_length); HIP_IFEL(hip_build_param_contents(msg, anchor, HIP_PARAM_HCHAIN_ANCHOR, hash_length), -1, "build param contents failed\n"); } HIP_DUMP_MSG(msg); /* send msg to hipd and receive corresponding reply */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_sock), -1, "send_recv msg failed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n"); HIP_DEBUG("send_recv msg succeeded\n"); out_err: free(msg); return err; }
/** * Invokes an UPDATE message containing an anchor element as a hook to * next hash structure to be used when the active one depletes * * @param entry the sadb entry for the outbound direction * @param anchors the anchor elements to be sent * @param hash_item_length length of the respective hash item * @param soft_update indicates if HHL-based updates should be used * @param anchor_offset the offset of the anchor element in the link tree * @param link_trees the link trees for the anchor elements, in case of HHL * @return 0 on success, -1 on error */ int send_trigger_update_to_hipd(const struct hip_sa_entry *entry, const unsigned char *anchors[MAX_NUM_PARALLEL_HCHAINS], const int hash_item_length, const int soft_update, const int *anchor_offset, struct hash_tree *link_trees[MAX_NUM_PARALLEL_HCHAINS]) { int err = 0; int i = 0; struct hip_common *msg = NULL; int hash_length = 0; struct hash_chain *hchain = NULL; struct hash_tree *htree = NULL; struct hash_tree *link_tree = NULL; int secret_length = 0; int branch_length = 0; int root_length = 0; const unsigned char *secret = NULL; unsigned char *branch_nodes = NULL; const unsigned char *root = NULL; HIP_ASSERT(entry != NULL); HIP_IFEL((hash_length = esp_prot_get_hash_length(entry->esp_prot_transform)) <= 0, -1, "error or tried to resolve UNUSED transform\n"); HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1, "failed to allocate memory\n"); hip_msg_init(msg); HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_TRIGGER_UPDATE, 0), -1, "build hdr failed\n"); HIP_DEBUG_HIT("src_hit", &entry->inner_src_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_src_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG_HIT("dst_hit", &entry->inner_dst_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_dst_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG("esp_prot_transform: %u\n", entry->esp_prot_transform); HIP_IFEL(hip_build_param_contents(msg, &entry->esp_prot_transform, HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)), -1, "build param contents failed\n"); // also send the hchain/htree length for all update items HIP_IFEL(hip_build_param_contents(msg, &hash_item_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("added hash_item_length: %i\n", hash_item_length); HIP_DEBUG("num_parallel_hchains: %u\n", num_parallel_hchains); HIP_IFEL(hip_build_param_contents(msg, &num_parallel_hchains, HIP_PARAM_INT, sizeof(long)), -1, "build param contents failed\n"); // add update anchors for (i = 0; i < num_parallel_hchains; i++) { HIP_HEXDUMP("anchor: ", anchors[i], hash_length); HIP_IFEL(hip_build_param_contents(msg, anchors[i], HIP_PARAM_HCHAIN_ANCHOR, hash_length), -1, "build param contents failed\n"); } // now transmit root for each next hash item for tree-based updates, if available for (i = 0; i < num_parallel_hchains; i++) { if (entry->esp_prot_transform == ESP_PROT_TFM_TREE) { htree = entry->next_hash_items[i]; link_tree = htree->link_tree; } else { hchain = entry->next_hash_items[i]; link_tree = hchain->link_tree; } if (link_tree) { /* if the next_hchain has got a link_tree, we need its root for * the verification of the next_hchain's elements */ root = htree_get_root(link_tree, &root_length); } // only transmit root length once if (i == 0) { HIP_DEBUG("root_length: %i\n", root_length); HIP_IFEL(hip_build_param_contents(msg, &root_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); } if (root) { HIP_HEXDUMP("root: ", root, root_length); HIP_IFEL(hip_build_param_contents(msg, root, HIP_PARAM_ROOT, root_length), -1, "build param contents failed\n"); } } HIP_DEBUG("soft_update: %i\n", soft_update); HIP_IFEL(hip_build_param_contents(msg, &soft_update, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); if (soft_update) { for (i = 0; i < num_parallel_hchains; i++) { secret = htree_get_secret(link_trees[i], anchor_offset[i], &secret_length); HIP_IFEL(!(branch_nodes = htree_get_branch(link_trees[i], anchor_offset[i], NULL, &branch_length)), -1, "failed to get branch nodes\n"); HIP_DEBUG("anchor_offset: %i\n", anchor_offset[i]); HIP_IFEL(hip_build_param_contents(msg, &anchor_offset[i], HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("secret_length: %i\n", secret_length); HIP_IFEL(hip_build_param_contents(msg, &secret_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("branch_length: %i\n", branch_length); HIP_IFEL(hip_build_param_contents(msg, &branch_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_HEXDUMP("secret: ", secret, secret_length); HIP_IFEL(hip_build_param_contents(msg, secret, HIP_PARAM_SECRET, secret_length), -1, "build param contents failed\n"); HIP_HEXDUMP("branch_nodes: ", branch_nodes, branch_length); HIP_IFEL(hip_build_param_contents(msg, branch_nodes, HIP_PARAM_BRANCH_NODES, branch_length), -1, "build param contents failed\n"); } } HIP_DUMP_MSG(msg); /* send msg to hipd and receive corresponding reply */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_sock), -1, "send_recv msg failed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n"); HIP_DEBUG("send_recv msg succeeded\n"); out_err: free(msg); free(branch_nodes); return err; }
/** * main_server_native - it handles the functionality of the client-native * @param socktype the type of socket * @param port_name the prot number * * @return 1 with success, 0 otherwise. */ int main_server_native(int socktype, char *port_name, char *name) { struct endpointinfo hints, *res = NULL; struct sockaddr_eid peer_eid; struct sockaddr_hip our_sockaddr, peer_sock; char mylovemostdata[IP_MAXPACKET]; int recvnum, sendnum, serversock = 0, sockfd = 0, err = 0, on = 1; int endpoint_family = PF_HIP; socklen_t peer_eid_len = sizeof(struct sockaddr_hip); /* recvmsg() stuff for UDP multihoming */ char control[CMSG_SPACE(40)]; struct cmsghdr *cmsg; struct inet6_pktinfo *pktinfo; struct iovec iov = { &mylovemostdata, sizeof(mylovemostdata) - 1 }; struct msghdr msg = { &peer_sock, sizeof(peer_sock), &iov, 1, &control, sizeof(control), 0 }; serversock = socket(endpoint_family, socktype, 0); if (serversock < 0) { HIP_PERROR("socket: "); err = 1; goto out_err; } setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (socktype == SOCK_DGRAM) setsockopt(serversock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on)); memset(&hints, 0, sizeof(struct endpointinfo)); hints.ei_family = endpoint_family; hints.ei_socktype = socktype; HIP_DEBUG("Native server calls getendpointinfo\n"); err = getendpointinfo(NULL, port_name, &hints, &res); if (err || !res) { HIP_ERROR("Resolving of peer identifiers failed (%d)\n", err); goto out_err; } memset(&our_sockaddr, 0, sizeof(struct sockaddr_hip)); if (name) { HIP_IFEL(inet_pton(AF_INET6, name, &our_sockaddr.ship_hit) != 1, 1, "Failed to parse HIT\n"); } our_sockaddr.ship_port = htons(atoi(port_name)); HIP_DEBUG("Binding to port %d\n", ntohs(our_sockaddr.ship_port)); our_sockaddr.ship_family = endpoint_family; if (bind(serversock, &our_sockaddr, sizeof(struct sockaddr_hip)) < 0) { HIP_PERROR("bind: "); err = 1; goto out_err; } HIP_DEBUG("Native server calls listen\n"); if (socktype == SOCK_STREAM && listen(serversock, 1) < 0) { HIP_PERROR("listen: "); err = 1; goto out_err; } HIP_DEBUG("Native server waits connection request\n"); while(1) { if (socktype == SOCK_STREAM) { sockfd = accept(serversock, (struct sockaddr *) &peer_sock, &peer_eid_len); if (sockfd < 0) { HIP_PERROR("accept: "); err = 1; goto out_err; } while((recvnum = recv(sockfd, mylovemostdata, sizeof(mylovemostdata), 0)) > 0 ) { mylovemostdata[recvnum] = '\0'; printf("%s", mylovemostdata); fflush(stdout); sendnum = send(sockfd, mylovemostdata, recvnum, 0); if (sendnum < 0) { HIP_PERROR("send: "); err = 1; goto out_err; } } } else { /* UDP */ sockfd = serversock; serversock = 0; while((recvnum = recvmsg(sockfd, &msg, 0)) > 0) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_2292PKTINFO) { pktinfo = CMSG_DATA(cmsg); break; } } HIP_DEBUG_HIT("localaddr", &pktinfo->ipi6_addr); iov.iov_len = strlen(mylovemostdata); /* ancillary data contains the src * and dst addresses */ sendnum = sendmsg(sockfd, &msg, 0); if (sendnum < 0) { HIP_PERROR("sendto: "); err = 1; goto out_err; } } } } out_err: if (res) free_endpointinfo(res); if (sockfd) close(sockfd); // discard errors if (serversock) close(serversock); // discard errors return err; }
/* Security associations in the kernel with BEET are bounded to the outer * address, meaning IP addresses. As a result the parameters to be given * should be such an addresses and not the HITs. */ uint32_t hip_add_sa(struct in6_addr *saddr, struct in6_addr *daddr, struct in6_addr *src_hit, struct in6_addr *dst_hit, uint32_t spi, int ealg, struct hip_crypto_key *enckey, struct hip_crypto_key *authkey, int already_acquired, int direction, int update, hip_ha_t *entry) { int so, len, err = 0, e_keylen, a_keylen; int aalg = ealg; u_int wsize = 4; /* XXX static size of window */ struct sockaddr_storage ss_addr, dd_addr; struct sockaddr *s_saddr; struct sockaddr *d_saddr; uint32_t reqid = 0; u_int32_t seq = 0; u_int flags = 0; // always zero u_int64_t lifebyte = 0, lifetime = 0; //u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP_NON_IKE; u_int8_t l_natt_type = HIP_UDP_ENCAP_ESPINUDP; // FIXME: this parameter maybe should be related to some esp parameters (according to racoon source code) u_int16_t l_natt_frag = 0; /* Mappings from HIP to PFKEY algo names */ u_int e_types[] = {SADB_EALG_NULL, SADB_X_EALG_AESCBC, SADB_EALG_3DESCBC, SADB_EALG_3DESCBC, SADB_X_EALG_BLOWFISHCBC, SADB_EALG_NULL, SADB_EALG_NULL}; u_int a_algos[] = {SADB_AALG_NONE, SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_SHA1HMAC, SADB_AALG_MD5HMAC}; u_int e_type = e_types[ealg]; u_int a_type = a_algos[aalg]; in_port_t sport = entry->local_udp_port; in_port_t dport = entry->peer_udp_port; a_keylen = hip_auth_key_length_esp(ealg); e_keylen = hip_enc_key_length(ealg); get_random_bytes(&reqid, sizeof(uint32_t)); get_random_bytes(&seq, sizeof(uint32_t)); HIP_DEBUG("\n"); HIP_DEBUG_HIT("src_hit", src_hit); HIP_DEBUG_HIT("dst_hit", dst_hit); HIP_DEBUG_IN6ADDR("saddr", saddr); HIP_DEBUG_IN6ADDR("daddr", daddr); HIP_IFEL((!saddr || !daddr), 1, "Addresses not valid when adding SA's\n"); HIP_IFEL(((so = pfkey_open()) < 0), 1, "ERROR in opening pfkey socket: %s\n", ipsec_strerror()); s_saddr = (struct sockaddr*) &ss_addr; d_saddr = (struct sockaddr*) &dd_addr; get_sock_addr_from_in6(s_saddr, saddr); get_sock_addr_from_in6(d_saddr, daddr); if (direction == HIP_SPI_DIRECTION_OUT) { entry->outbound_sa_count++; } else { entry->inbound_sa_count++; } // NOTE: port numbers remains in host representation if (update) { if (sport) { // pfkey_send_update_nat when update = 1 and sport != 0 HIP_IFEBL(((len = pfkey_send_update_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq, l_natt_type, sport, dport, NULL, l_natt_frag)) < 0), 1, pfkey_close(so), "ERROR in updating sa for nat: %s\n", ipsec_strerror()); } else { // pfkey_send_update when update = 1 and sport == 0 HIP_IFEBL(((len = pfkey_send_update(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq)) < 0), 1, pfkey_close(so), "ERROR in updating sa: %s\n", ipsec_strerror()); } } else { if (sport) { // pfkey_send_add_nat when update = 0 and sport != 0 HIP_IFEBL(((len = pfkey_send_add_nat(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq, l_natt_type, sport, dport, NULL, l_natt_frag)) < 0), 1, pfkey_close(so), "ERROR in adding sa for nat: %s\n", ipsec_strerror()); } else { // pfkey_send_add when update = 0 and sport == 0 HIP_IFEBL(((len = pfkey_send_add(so, SADB_SATYPE_ESP, HIP_IPSEC_DEFAULT_MODE, s_saddr, d_saddr, spi, reqid, wsize, (void*) enckey, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, lifetime, 0, seq)) < 0), 1, pfkey_close(so), "ERROR in adding sa: %s\n", ipsec_strerror()); } } return 0; out_err: return err; }