void pbs_poke(pb_stream *pbs, int offset, int value) { if(offset < pbs_room(pbs)) { pbs->start[offset] = value; if(pbs->cur < pbs->start + offset) { pbs->cur = pbs->start + offset; } } else { openswan_log("pbs_peek offset:%d < pbs_room(pbs):%d", offset, pbs_room(pbs)); pexpect(offset < pbs_room(pbs)); } }
/* 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); });
/* 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); });
int pbs_peek(pb_stream *pbs, int offset) { if(offset < pbs_room(pbs)) { return pbs->start[offset]; } else { return 0; } }
int pbs_append(pb_stream *dest, int destoffset , pb_stream *src, int offset, int length) { /* -1 means end of destination stream */ if(destoffset == -1) { destoffset = pbs_offset(dest); } if(destoffset > pbs_room(dest) || destoffset + length > pbs_room(dest)) { return 0; } if(offset > pbs_room(src) || offset + length > pbs_room(src)) { return 0; } memcpy(&dest->start[destoffset], &src->start[offset], length); if(dest->cur < (dest->start + destoffset + length)) { dest->cur = dest->start + (destoffset + length); } }
/** * nat_traversal_natoa_lookup() * * Look for NAT-OA in message */ void nat_traversal_natoa_lookup(struct msg_digest *md) { struct payload_digest *p; struct state *st = md->st; int i; ip_address ip; if (!st || !md->iface) { loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d", __FILE__, __LINE__); return; } /** Count NAT-OA **/ for (p = md->chain[ISAKMP_NEXT_NATOA_R], i=0; p != NULL; p = p->next, i++); #if 0 DBG_log("NAT-Traversal: received %d NAT-OA.", i); #endif if (i==0) { return; } else if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) { loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " "ignored because peer is not NATed", i); return; } else if (i>1) { loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " "using first, ignoring others", i); } /** Take first **/ p = md->chain[ISAKMP_NEXT_NATOA_R]; DBG(DBG_PARSING, DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs)); );
int pbs_room_get(pb_stream *pbs) { return pbs_room(pbs); }
void recv_pcap_packet_gen(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct msg_digest *md; u_int32_t *dlt; struct iphdr *ip; struct udphdr *udp; u_char *ike; const struct iface_port *ifp = &if1; int packet_len; err_t from_ugh; union { struct sockaddr sa; struct sockaddr_in sa_in4; struct sockaddr_in6 sa_in6; } from; md = alloc_md(); dlt = (u_int32_t *)bytes; if (*dlt != PF_INET) return; ip = (struct iphdr *)(dlt + 1); udp = (struct udphdr *)(dlt + ip->ihl + 1); ike = (u_char *)(udp + 1); from.sa_in4.sin_addr.s_addr = ip->saddr; from.sa_in4.sin_port = udp->source; md->iface = ifp; packet_len = h->len - (ike - bytes); happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender)); from_ugh = initaddr((void *) &from.sa_in4.sin_addr, sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); setportof(from.sa_in4.sin_port, &md->sender); md->sender_port = ntohs(from.sa_in4.sin_port); cur_from = &md->sender; cur_from_port = md->sender_port; /* Clone actual message contents * and set up md->packet_pbs to describe it. */ init_pbs(&md->packet_pbs, clone_bytes(ike, packet_len, "message buffer in comm_handle()"), packet_len, "packet"); DBG_log("*received %d bytes from %s:%u on %s (port=%d)", (int) pbs_room(&md->packet_pbs), ip_str(&md->sender), (unsigned) md->sender_port, ifp->ip_dev->id_rname, ifp->port); DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)); process_packet(&md); if (md != NULL) release_md(md); cur_state = NULL; reset_cur_connection(); cur_from = NULL; }
static stf_status aggr_inI1_outR1_common(struct msg_digest *md, int authtype) { /* With Aggressive Mode, we get an ID payload in this, the first * message, so we can use it to index the preshared-secrets * when the IP address would not be meaningful (i.e. Road * Warrior). So our first task is to unravel the ID payload. */ struct state *st; struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; struct connection *c = find_host_connection(&md->iface->ip_addr, md->iface->port, &md->sender, md->sender_port, LEMPTY); #if 0 if (c == NULL && md->iface->ike_float) { c = find_host_connection(&md->iface->addr, pluto_nat_port, &md->sender, md->sender_port, LEMPTY); } #endif if (c == NULL) { /* see if a wildcarded connection can be found */ pb_stream pre_sa_pbs = sa_pd->pbs; lset_t policy = preparse_isakmp_sa_body(&pre_sa_pbs) | POLICY_AGGRESSIVE; c = find_host_connection(&md->iface->ip_addr, pluto_port, (ip_address*)NULL, md->sender_port, policy); if (c == NULL || (c->policy & POLICY_AGGRESSIVE) == 0) { ipstr_buf b; loglog(RC_LOG_SERIOUS, "initial Aggressive Mode message from %s" " but no (wildcard) connection has been configured%s%s", ipstr(&md->sender, &b), (policy != LEMPTY) ? " with policy=" : "", (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); /* XXX notification is in order! */ return STF_IGNORE; } /* Create a temporary connection that is a copy of this one. * His ID isn't declared yet. */ c = rw_instantiate(c, &md->sender, NULL, NULL); } /* Set up state */ cur_state = md->st = st = new_state(); /* (caller will reset cur_state) */ st->st_connection = c; st->st_remoteaddr = md->sender; st->st_remoteport = md->sender_port; st->st_localaddr = md->iface->ip_addr; st->st_localport = md->iface->port; st->st_interface = md->iface; change_state(st, STATE_AGGR_R1); /* until we have clue who this is, then be conservative about allocating * them any crypto bandwidth */ st->st_import = pcim_stranger_crypto; st->st_policy |= POLICY_AGGRESSIVE; st->st_oakley.auth = authtype; if (!ikev1_decode_peer_id(md, FALSE, TRUE)) { char buf[IDTOA_BUF]; ipstr_buf b; (void) idtoa(&st->st_connection->spd.that.id, buf, sizeof(buf)); loglog(RC_LOG_SERIOUS, "initial Aggressive Mode packet claiming to be from %s" " on %s but no connection has been authorized", buf, ipstr(&md->sender, &b)); /* XXX notification is in order! */ return STF_FAIL + INVALID_ID_INFORMATION; } c = st->st_connection; extra_debugging(c); st->st_try = 0; /* Not our job to try again from start */ st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */ memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE); get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender); insert_state(st); /* needs cookies, connection, and msgid (0) */ st->st_doi = ISAKMP_DOI_IPSEC; st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */ { ipstr_buf b; libreswan_log("responding to Aggressive Mode, state #%lu, connection \"%s\" from %s", st->st_serialno, st->st_connection->name, ipstr(&c->spd.that.host_addr, &b)); } merge_quirks(st, md); set_nat_traversal(st, md); /* save initiator SA for HASH */ clonereplacechunk(st->st_p1isa, sa_pd->pbs.start, pbs_room(&sa_pd->pbs), "sa in aggr_inI1_outR1()"); /* * parse_isakmp_sa picks the right group, which we need to know * before we do any calculations. We will call it again to have it * emit the winning SA into the output. */ /* SA body in */ { pb_stream sabs = sa_pd->pbs; RETURN_STF_FAILURE(parse_isakmp_sa_body(&sabs, &sa_pd->payload.sa, NULL, FALSE, st)); } /* KE in */ RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, &md->chain[ISAKMP_NEXT_KE]->pbs)); /* Ni in */ RETURN_STF_FAILURE(accept_v1_nonce(md, &st->st_ni, "Ni")); { struct ke_continuation *ke = alloc_thing( struct ke_continuation, "outI2 KE"); ke->ke_md = md; set_suspended(st, md); if (!st->st_sec_in_use) { /* need to calculate KE and Nonce */ pcrc_init(&ke->ke_pcrc, aggr_inI1_outR1_continue1); return build_ke(&ke->ke_pcrc, st, st->st_oakley.group, st->st_import); } else { /* KE and Nonce calculated */ ke->ke_pcrc.pcrc_serialno = st->st_serialno; /* transitional */ return aggr_inI1_outR1_tail(&ke->ke_pcrc, NULL); } } }