/* * In IKEv1, some implementations (including freeswan/openswan/libreswan) * interpreted the RFC that the whole IKE message must padded to a multiple * of 4 octets, but other implementations (i.e. Checkpoint in Aggressive Mode) * drop padded IKE packets. Some of the text on this topic can be found in the * IKEv1 RFC 2408 section 3.6 Transform Payload. * * The ikepad= option can be set to yes or no on a per-connection basis, * and defaults to yes. * * In IKEv2, there is no padding specified in the RFC and some implementations * will reject IKEv2 messages that are padded. As there are no known IKEv2 * clients that REQUIRE padding, padding is never done for IKEv2. If IKEv2 * clients are discovered in the wild, we will revisit this - please contact * the libreswan developers if you find such an implementation. * Therefor, the ikepad= option has no effect on IKEv2 connections. * * @param pbs PB Stream */ bool close_message(pb_stream *pbs, struct state *st) { size_t padding; if (st->st_ikev2) { DBG(DBG_CONTROLMORE, DBG_log("no IKE message padding required for IKEv2")); close_output_pbs(pbs); return TRUE; } padding = pad_up(pbs_offset(pbs), 4); if (padding != 0 && st != NULL && st->st_connection != NULL && (st->st_connection->policy & POLICY_NO_IKEPAD)) { DBG(DBG_CONTROLMORE, DBG_log("IKEv1 message padding of %zu bytes skipped by policy", padding)); } else if (padding != 0) { DBG(DBG_CONTROLMORE, DBG_log("padding IKEv1 message with %zu bytes", padding)); if (!out_zero(padding, pbs, "message padding")) return FALSE; } else { DBG(DBG_CONTROLMORE, DBG_log("no IKEv1 message padding required")); } close_output_pbs(pbs); return TRUE; }
/** The whole message must be a multiple of 4 octets. * I'm not sure where this is spelled out, but look at * rfc2408 3.6 Transform Payload. * Note: it talks about 4 BYTE boundaries! * * @param pbs PB Stream */ void close_message(pb_stream *pbs) { size_t padding = pad_up(pbs_offset(pbs), 4); if (padding != 0) (void) out_zero(padding, pbs, "message padding"); close_output_pbs(pbs); }
/** The whole message must be a multiple of 4 octets. * I'm not sure where this is spelled out, but look at * rfc2408 3.6 Transform Payload. * Note: it talks about 4 BYTE boundaries! * * @param pbs PB Stream */ void close_message(pb_stream *pbs, struct state *st) { size_t padding = pad_up(pbs_offset(pbs), 4); if (st && st->st_connection && (st->st_connection->policy & POLICY_IKEPAD) == 0) padding = 0; if (padding != 0) (void) out_zero(padding, pbs, "message padding"); close_output_pbs(pbs); }
bool emit_redirect_notification_decoded_dest( v2_notification_t ntype, const ip_address *dest_ip, const char *dest_str, const chunk_t *nonce, /* optional */ pb_stream *pbs) { struct ikev2_redirect_part gwi; size_t id_len; const unsigned char *id_bytes; if (dest_ip == NULL) { id_len = strlen(dest_str); id_bytes = (const unsigned char *)dest_str; } else { passert(dest_str == NULL); switch (addrtypeof(dest_ip)) { case AF_INET: gwi.gw_identity_type = GW_IPV4; break; case AF_INET6: gwi.gw_identity_type = GW_IPV6; break; default: bad_case(addrtypeof(dest_ip)); } id_len = addrbytesptr_read(dest_ip, &id_bytes); } if (id_len > 0xFF) { /* ??? what should we do? */ loglog(RC_LOG_SERIOUS, "redirect destination longer than 255 octets; ignoring"); return false; } gwi.gw_identity_len = id_len; passert(nonce == NULL || (nonce->len >= IKEv2_MINIMUM_NONCE_SIZE && nonce->len <= IKEv2_MAXIMUM_NONCE_SIZE)); pb_stream gwid_pbs; return - emit_v2Npl(ntype, pbs, &gwid_pbs) && out_struct(&gwi, &ikev2_redirect_desc, &gwid_pbs, NULL) && out_raw(id_bytes, id_len , &gwid_pbs, "redirect ID") && (nonce == NULL || out_chunk(*nonce, &gwid_pbs, "redirect ID len")) && (close_output_pbs(&gwid_pbs), true); }
/** The whole message must be a multiple of 4 octets. * I'm not sure where this is spelled out, but look at * rfc2408 3.6 Transform Payload. * Note: it talks about 4 BYTE boundaries! * * @param pbs PB Stream */ void close_message(pb_stream *pbs, struct state *st) { size_t padding = pad_up(pbs_offset(pbs), 4); /* Workaround for overzealous Checkpoint firewal */ if (padding && st && st->st_connection && (st->st_connection->policy & POLICY_NO_IKEPAD)) { DBG(DBG_CONTROLMORE, DBG_log("IKE message padding of %lu bytes skipped by policy", padding)); padding = 0; } if (padding != 0) { DBG(DBG_CONTROLMORE, DBG_log("padding IKE message with %lu bytes", padding)); (void) out_zero(padding, pbs, "message padding"); } else { DBG(DBG_CONTROLMORE, DBG_log("no IKE message padding required")); } close_output_pbs(pbs); }
void send_v2_notification(struct state *p1st, u_int16_t type , struct state *encst , u_char *icookie , u_char *rcookie , chunk_t *n_data) { u_char buffer[1024]; pb_stream reply; pb_stream rbody; /* this function is not generic enough yet just enough for 6msg * TBD accept HDR FLAGS as arg. default ISAKMP_FLAGS_R * TBD when there is a child SA use that SPI in the notify paylod. * TBD support encrypted notifications payloads. * TBD accept Critical bit as an argument. default is set. * TBD accept exchange type as an arg, default is ISAKMP_v2_SA_INIT * do we need to send a notify with empty data? * do we need to support more Protocol ID? more than PROTO_ISAKMP */ IPSEC_dbg("sending %snotification %s to %s:%u" , encst ? "encrypted " : "" , enum_name(&ikev2_notify_names, type) , ip_str(&p1st->st_remoteaddr) , p1st->st_remoteport); if(n_data == NULL) { DBG(DBG_CONTROLMORE, DBG_log("don't send packet when notification data empty")); return; } memset(buffer, 0, sizeof(buffer)); init_pbs(&reply, buffer, sizeof(buffer), "notification msg"); /* HDR out */ { struct isakmp_hdr n_hdr ; zero(&n_hdr); /* default to 0 */ /* AAA should we copy from MD? */ n_hdr.isa_version = IKEv2_MAJOR_VERSION << ISA_MAJ_SHIFT | IKEv2_MINOR_VERSION; memcpy(n_hdr.isa_rcookie, rcookie, COOKIE_SIZE); memcpy(n_hdr.isa_icookie, icookie, COOKIE_SIZE); n_hdr.isa_xchg = ISAKMP_v2_SA_INIT; n_hdr.isa_np = ISAKMP_NEXT_v2N; n_hdr.isa_flags &= ~ISAKMP_FLAGS_I; n_hdr.isa_flags |= ISAKMP_FLAGS_R; if (!out_struct(&n_hdr, &isakmp_hdr_desc, &reply, &rbody)) { IPSEC_dbg("error initializing hdr for notify message"); return; } } chunk_t child_spi; child_spi.ptr = NULL; child_spi.len = 0; /* build and add v2N payload to the packet */ ship_v2N (ISAKMP_NEXT_NONE, ISAKMP_PAYLOAD_CRITICAL, PROTO_ISAKMP, &child_spi,type, n_data, &rbody); close_message(&rbody); close_output_pbs(&reply); clonetochunk(p1st->st_tpacket, reply.start, pbs_offset(&reply) , "notification packet"); ipsec_child_send_packet(p1st, "notification", TRUE); }