/* process an input packet, possibly generating a reply. * * If all goes well, this routine eventually calls a state-specific * transition function. */ void process_packet(struct msg_digest **mdp) { struct msg_digest *md = *mdp; int vmaj, vmin; if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs)) { /* The packet was very badly mangled. We can't be sure of any * content - not even to look for major version number! * So we'll just drop it. */ libreswan_log("Received packet with mangled IKE header - dropped"); send_notification_from_md(md, PAYLOAD_MALFORMED); return; } if (md->packet_pbs.roof > md->message_pbs.roof) { /* Some (old?) versions of the Cisco VPN client send an additional * 16 bytes of zero bytes - Complain but accept it */ DBG(DBG_CONTROL, { DBG_log( "size (%u) in received packet is larger than the size " "specified in ISAKMP HDR (%u) - ignoring extraneous bytes", (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); DBG_dump("extraneous bytes:", md->message_pbs.roof, md->packet_pbs.roof - md->message_pbs.roof); });
/* process an input packet, possibly generating a reply. * * If all goes well, this routine eventually calls a state-specific * transition function. */ void process_packet(struct msg_digest **mdp) { struct msg_digest *md = *mdp; struct state *st = NULL; int vmaj, vmin; enum state_kind from_state = STATE_UNDEFINED; /* state we started in */ #define SEND_NOTIFICATION(t) { \ if (st) \ send_notification_from_state(st, from_state, t); \ else \ send_notification_from_md(md, t); } if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs)) { /* * The packet was very badly mangled. We can't be sure of any * content - not even to look for major version number! * So we'll just silently drop it */ libreswan_log("Received packet with mangled IKE header - dropped"); SEND_NOTIFICATION(PAYLOAD_MALFORMED); return; } if (md->packet_pbs.roof < md->message_pbs.roof) { /* I don't think this can happen if in_struct() did not fail */ libreswan_log( "received packet size (%u) is smaller than from " "size specified in ISAKMP HDR (%u) - packet dropped", (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); /* abort processing corrupt packet */ return; } else if (md->packet_pbs.roof > md->message_pbs.roof) { /* * Some (old?) versions of the Cisco VPN client send an additional * 16 bytes of zero bytes - Complain but accept it */ DBG(DBG_CONTROL, { DBG_log( "size (%u) in received packet is larger than the size " "specified in ISAKMP HDR (%u) - ignoring extraneous bytes", (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); DBG_dump("extraneous bytes:", md->message_pbs.roof, md->packet_pbs.roof - md->message_pbs.roof); });
err_t parse_redirect_payload(pb_stream *input_pbs, const char *allowed_targets_list, const chunk_t *nonce, ip_address *redirect_ip /* result */) { struct ikev2_redirect_part gw_info; if (!in_struct(&gw_info, &ikev2_redirect_desc, input_pbs, NULL)) return "received deformed REDIRECT payload"; int af; switch (gw_info.gw_identity_type) { case GW_IPV4: af = AF_INET; break; case GW_IPV6: af = AF_INET6; break; case GW_FQDN: af = AF_UNSPEC; break; default: return "bad GW Ident Type"; } /* in_raw() actual GW Identity */ switch (af) { case AF_UNSPEC: { /* * The FQDN string isn't NUL-terminated. * * The length is stored in a byte so it cannot be * larger than 0xFF. * Some helpful compilers moan about this test being always true * so I eliminated it: * passert(gw_info.gw_identity_len <= 0xFF); */ unsigned char gw_str[0xFF]; if (!in_raw(&gw_str, gw_info.gw_identity_len, input_pbs, "GW Identity")) return "error while extracting GW Identity from variable part of IKEv2_REDIRECT Notify payload"; err_t ugh = ttoaddr((char *) gw_str, gw_info.gw_identity_len, AF_UNSPEC, redirect_ip); if (ugh != NULL) return ugh; break; } case AF_INET: case AF_INET6: { if (pbs_left(input_pbs) < gw_info.gw_identity_len) return "variable part of payload is smaller than transfered GW Identity Length"; /* parse address directly to redirect_ip */ err_t ugh = initaddr(input_pbs->cur, gw_info.gw_identity_len, af, redirect_ip); if (ugh != NULL) return ugh; DBG(DBG_PARSING, { ip_address_buf b; DBG_log(" GW Identity IP: %s", ipstr(redirect_ip, &b)); }); input_pbs->cur += gw_info.gw_identity_len; break; } }