1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
/* state and event objects
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2001 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* RCSID $Id$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <gmp.h> /* GNU MP library */
#include "connections.h"
/* Message ID mechanism.
*
* A Message ID is contained in each IKE message header.
* For Phase 1 exchanges (Main and Aggressive), it will be zero.
* For other exchanges, which must be under the protection of an
* ISAKMP SA, the Message ID must be unique within that ISAKMP SA.
* Effectively, this labels the message as belonging to a particular
* exchange.
*
* RFC2408 "ISAKMP" 3.1 "ISAKMP Header Format" (near end) states that
* the Message ID must be unique. We interpret this to be "unique within
* one ISAKMP SA".
*
* BTW, we feel this uniqueness allows rekeying to be somewhat simpler
* than specified by draft-jenkins-ipsec-rekeying-06.txt.
*/
typedef u_int32_t msgid_t; /* Network order! */
#define MAINMODE_MSGID ((msgid_t) 0)
struct state; /* forward declaration of tag */
extern bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid);
extern msgid_t generate_msgid(struct state *isakmp_sa);
/* Oakley (Phase 1 / Main Mode) transform and attributes
* This is a flattened/decoded version of what is represented
* in the Transaction Payload.
* Names are chosen to match corresponding names in state.
*/
struct oakley_trans_attrs {
u_int16_t encrypt; /* Encryption algorithm */
u_int16_t enckeylen; /* encryption key len (bits) */
const struct encrypt_desc *encrypter; /* package of encryption routines */
u_int16_t hash; /* Hash algorithm */
const struct hash_desc *hasher; /* package of hashing routines */
u_int16_t auth; /* Authentication method */
const struct oakley_group_desc *group; /* Oakley group */
time_t life_seconds; /* When this SA expires (seconds) */
u_int32_t life_kilobytes; /* When this SA is exhausted (kilobytes) */
#if 0 /* not yet */
u_int16_t prf; /* Pseudo Random Function */
#endif
};
/* IPsec (Phase 2 / Quick Mode) transform and attributes
* This is a flattened/decoded version of what is represented
* by a Transaction Payload. There may be one for AH, one
* for ESP, and a funny one for IPCOMP.
*/
struct ipsec_trans_attrs {
u_int8_t transid; /* transform id */
ipsec_spi_t spi; /* his SPI */
time_t life_seconds; /* When this SA expires */
u_int32_t life_kilobytes; /* When this SA expires */
u_int16_t encapsulation;
u_int16_t auth;
u_int16_t key_len;
u_int16_t key_rounds;
#if 0 /* not implemented yet */
u_int16_t cmprs_dict_sz;
u_int32_t cmprs_alg;
#endif
};
/* IPsec per protocol state information */
struct ipsec_proto_info {
bool present; /* was this transform specified? */
struct ipsec_trans_attrs attrs;
ipsec_spi_t our_spi;
u_int16_t keymat_len; /* same for both */
u_char *our_keymat;
u_char *peer_keymat;
};
/* state object: record the state of a (possibly nascent) SA
*
* Invariants (violated only during short transitions):
* - each state object will be in statetable exactly once.
* - each state object will always have a pending event.
* This prevents leaks.
*/
struct state
{
so_serial_t st_serialno; /* serial number (for seniority) */
so_serial_t st_clonedfrom; /* serial number of parent */
struct connection *st_connection; /* connection for this SA */
int st_whack_sock; /* fd for our Whack TCP socket.
* Single copy: close when freeing struct.
*/
struct msg_digest *st_suspended_md; /* suspended state-transition */
struct oakley_trans_attrs st_oakley;
struct ipsec_proto_info st_ah;
struct ipsec_proto_info st_esp;
struct ipsec_proto_info st_ipcomp;
#ifdef KLIPS
ipsec_spi_t st_tunnel_in_spi; /* KLUDGE */
ipsec_spi_t st_tunnel_out_spi; /* KLUDGE */
#endif
const struct oakley_group_desc *st_pfs_group; /* group for Phase 2 PFS */
u_int32_t st_doi; /* Domain of Interpretation */
u_int32_t st_situation;
lset_t st_policy; /* policy for IPsec SA */
msgid_t st_msgid; /* MSG-ID from header. Network Order! */
/* only for a state representing an ISAKMP SA */
struct msgid_list *st_used_msgids; /* used-up msgids */
/* symmetric stuff */
/* initiator stuff */
chunk_t st_gi; /* Initiator public value */
u_int8_t st_icookie[COOKIE_SIZE];/* Initiator Cookie */
chunk_t st_ni; /* Ni nonce */
/* responder stuff */
chunk_t st_gr; /* Responder public value */
u_int8_t st_rcookie[COOKIE_SIZE];/* Responder Cookie */
chunk_t st_nr; /* Nr nonce */
/* my stuff */
chunk_t st_tpacket; /* Transmitted packet */
/* Phase 2 ID payload info about my user */
u_int8_t st_myuserprotoid; /* IDcx.protoid */
u_int16_t st_myuserport;
/* his stuff */
chunk_t st_rpacket; /* Received packet */
/* Phase 2 ID payload info about peer's user */
u_int8_t st_peeruserprotoid; /* IDcx.protoid */
u_int16_t st_peeruserport;
/* end of symmetric stuff */
u_int8_t st_sec_in_use; /* bool: does st_sec hold a value */
MP_INT st_sec; /* Our local secret value */
chunk_t st_shared; /* Derived shared secret
* Note: during Quick Mode,
* presence indicates PFS
* selected.
*/
/* In a Phase 1 state, preserve peer's public key after authentication */
struct pubkey *st_peer_pubkey;
enum state_kind st_state; /* State of exchange */
u_int8_t st_retransmit; /* Number of retransmits */
unsigned long st_try; /* number of times rekeying attempted */
/* 0 means the only time */
time_t st_margin; /* life after EVENT_SA_REPLACE */
unsigned long st_outbound_count; /* traffic through eroute */
time_t st_outbound_time; /* time of last change to st_outbound_count */
chunk_t st_p1isa; /* Phase 1 initiator SA (Payload) for HASH */
chunk_t st_skeyid; /* Key material */
chunk_t st_skeyid_d; /* KM for non-ISAKMP key derivation */
chunk_t st_skeyid_a; /* KM for ISAKMP authentication */
chunk_t st_skeyid_e; /* KM for ISAKMP encryption */
u_char st_iv[MAX_DIGEST_LEN]; /* IV for encryption */
u_char st_new_iv[MAX_DIGEST_LEN];
u_char st_ph1_iv[MAX_DIGEST_LEN]; /* IV at end if phase 1 */
unsigned int st_iv_len;
unsigned int st_new_iv_len;
unsigned int st_ph1_iv_len;
chunk_t st_enc_key; /* Oakley Encryption key */
struct event *st_event; /* backpointer for certain events */
struct state *st_hashchain_next; /* Next in list */
struct state *st_hashchain_prev; /* Previous in list */
struct {
bool vars_set;
bool started;
} st_modecfg;
struct {
int attempt;
bool started;
bool status;
} st_xauth;
u_int32_t nat_traversal;
ip_address nat_oa;
/* RFC 3706 Dead Peer Detection */
bool st_dpd; /* Peer supports DPD */
time_t st_last_dpd; /* Time of last DPD transmit */
u_int32_t st_dpd_seqno; /* Next R_U_THERE to send */
u_int32_t st_dpd_expectseqno; /* Next R_U_THERE_ACK to receive */
u_int32_t st_dpd_peerseqno; /* global variables */
struct event *st_dpd_event; /* backpointer for DPD events */
u_int32_t st_seen_vendorid; /* Bit field about recognized Vendor ID */
};
/* global variables */
extern u_int16_t pluto_port; /* Pluto's port */
extern bool states_use_connection(struct connection *c);
/* state functions */
extern struct state *new_state(void);
extern void init_states(void);
extern void insert_state(struct state *st);
extern void unhash_state(struct state *st);
extern void release_whack(struct state *st);
extern void state_eroute_usage(ip_subnet *ours, ip_subnet *his
, unsigned long count, time_t nw);
extern void delete_state(struct state *st);
extern void delete_states_by_connection(struct connection *c, bool relations);
extern struct state
*duplicate_state(struct state *st),
*find_state(const u_char *icookie
, const u_char *rcookie
, const ip_address *peer
, msgid_t msgid),
*state_with_serialno(so_serial_t sn),
*find_phase2_state_to_delete(const struct state *p1st, u_int8_t protoid
, ipsec_spi_t spi, bool *bogus),
*find_phase1_state(const struct connection *c, lset_t ok_states),
*find_sender(size_t packet_len, u_char *packet);
extern void show_states_status(bool all, const char *name);
extern void for_each_state(void *(f)(struct state *, void *data), void *data);
extern void find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi);
extern ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st);
extern void fmt_state(bool all, struct state *st, time_t n
, char *state_buf, size_t state_buf_len
, char *state_buf2, size_t state_buf_len2);
extern void delete_states_by_peer(ip_address *peer);
|