Added a force_hookie hook that requests a COOKIE independent of our COOKIE mechanism
[strongswan.git] / src / conftest / hooks / ike_auth_fill.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "hook.h"
17
18 #include <time.h>
19 #include <netinet/udp.h>
20
21 #include <encoding/payloads/cert_payload.h>
22 #include <encoding/payloads/encryption_payload.h>
23
24 typedef struct private_ike_auth_fill_t private_ike_auth_fill_t;
25
26 /**
27 * Private data of an ike_auth_fill_t object.
28 */
29 struct private_ike_auth_fill_t {
30
31 /**
32 * Implements the hook_t interface.
33 */
34 hook_t hook;
35
36 /**
37 * Alter requests or responses?
38 */
39 bool req;
40
41 /**
42 * ID of message to alter.
43 */
44 int id;
45
46 /**
47 * Number of bytes to fill IKE_AUTH up
48 */
49 int bytes;
50 };
51
52 /** size of non ESP-Marker */
53 #define NON_ESP_MARKER_LEN 4
54
55 /**
56 * Calculate packet size on wire (without ethernet/IP header)
57 */
58 static size_t calculate_wire_size(message_t *message, ike_sa_t *ike_sa)
59 {
60 enumerator_t *enumerator;
61 payload_t *payload;
62 size_t size = 0;
63
64 enumerator = message->create_payload_enumerator(message);
65 while (enumerator->enumerate(enumerator, &payload))
66 {
67 size += payload->get_length(payload);
68 }
69 enumerator->destroy(enumerator);
70
71 if (message->get_exchange_type(message) != IKE_SA_INIT)
72 {
73 keymat_t *keymat;
74 aead_t *aead;
75 size_t bs;
76
77 keymat = ike_sa->get_keymat(ike_sa);
78 aead = keymat->get_aead(keymat, FALSE);
79 if (aead)
80 {
81 bs = aead->get_block_size(aead);
82 size += ENCRYPTION_PAYLOAD_HEADER_LENGTH + NON_ESP_MARKER_LEN +
83 aead->get_icv_size(aead) + aead->get_iv_size(aead) +
84 (bs - (size % bs));
85 }
86 }
87 return sizeof(struct udphdr) + IKE_HEADER_LENGTH + size;
88 }
89
90 METHOD(listener_t, message, bool,
91 private_ike_auth_fill_t *this, ike_sa_t *ike_sa, message_t *message,
92 bool incoming)
93 {
94 if (!incoming &&
95 message->get_request(message) == this->req &&
96 message->get_message_id(message) == this->id)
97 {
98 cert_payload_t *pld;
99 size_t size, diff;
100 chunk_t data;
101
102 size = calculate_wire_size(message, ike_sa);
103 if (size < this->bytes - CERT_PAYLOAD_HEADER_LENGTH)
104 {
105 diff = this->bytes - size - CERT_PAYLOAD_HEADER_LENGTH;
106 data = chunk_alloc(diff);
107 memset(data.ptr, 0x12, data.len);
108 pld = cert_payload_create_custom(201, data);
109 message->add_payload(message, &pld->payload_interface);
110 DBG1(DBG_CFG, "inserting %d dummy bytes certificate payload", diff);
111 }
112 }
113 return TRUE;
114 }
115
116 METHOD(hook_t, destroy, void,
117 private_ike_auth_fill_t *this)
118 {
119 free(this);
120 }
121
122 /**
123 * Create the IKE_AUTH fill hook
124 */
125 hook_t *ike_auth_fill_hook_create(char *name)
126 {
127 private_ike_auth_fill_t *this;
128
129 INIT(this,
130 .hook = {
131 .listener = {
132 .message = _message,
133 },
134 .destroy = _destroy,
135 },
136 .req = conftest->test->get_bool(conftest->test,
137 "hooks.%s.request", TRUE, name),
138 .id = conftest->test->get_int(conftest->test,
139 "hooks.%s.id", 1, name),
140 .bytes = conftest->test->get_int(conftest->test,
141 "hooks.%s.bytes", 0, name),
142 );
143
144 return &this->hook;
145 }