fixed crypter/signer in/out to conform with standard
[strongswan.git] / src / charon / sa / transactions / transaction.c
1 /**
2 * @file transaction.c
3 *
4 * @brief Generic contstructor for the different transaction types.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "transaction.h"
24
25 #include <sa/child_sa.h>
26 #include <sa/transactions/ike_sa_init.h>
27 #include <sa/transactions/ike_auth.h>
28 #include <sa/transactions/delete_ike_sa.h>
29 #include <sa/transactions/create_child_sa.h>
30 #include <sa/transactions/delete_child_sa.h>
31 #include <sa/transactions/dead_peer_detection.h>
32 #include <encoding/payloads/ts_payload.h>
33 #include <encoding/payloads/sa_payload.h>
34 #include <encoding/payloads/nonce_payload.h>
35 #include <encoding/payloads/notify_payload.h>
36 #include <encoding/payloads/delete_payload.h>
37 #include <utils/logger_manager.h>
38
39
40 /*
41 * see header file
42 */
43 transaction_t *transaction_create(ike_sa_t *ike_sa, message_t *request)
44 {
45 iterator_t *iterator;
46 payload_t *current;
47 notify_payload_t *notify;
48 transaction_t *transaction = NULL;
49 u_int32_t message_id;
50
51 if (!request->get_request(request))
52 {
53 return NULL;
54 }
55 message_id = request->get_message_id(request);
56
57 switch (request->get_exchange_type(request))
58 {
59 case IKE_SA_INIT:
60 {
61 if (ike_sa->get_state(ike_sa) == SA_CREATED)
62 {
63 transaction = (transaction_t*)ike_sa_init_create(ike_sa, message_id);
64 }
65 break;
66 }
67 case IKE_AUTH:
68 {
69 /* IKE_AUTH is always created in IKE_SA_INIT, it never should
70 * appear alone */
71 break;
72 }
73 case CREATE_CHILD_SA:
74 {
75 if (ike_sa->get_state(ike_sa) != SA_ESTABLISHED)
76 {
77 break;
78 }
79 /* look for a REKEY_SA notify */
80 iterator = request->get_payload_iterator(request);
81 while (iterator->has_next(iterator))
82 {
83 iterator->current(iterator, (void**)&current);
84 if (current->get_type(current) != NOTIFY)
85 {
86 continue;
87 }
88 notify = (notify_payload_t*)current;
89 if (notify->get_notify_type(notify) != REKEY_SA)
90 {
91 continue;
92 }
93 switch (notify->get_protocol_id(notify))
94 {
95 case PROTO_IKE:
96 /* TODO: transaction = rekey_ike_sa_create(ike_sa, message_id); */
97 break;
98 case PROTO_AH:
99 case PROTO_ESP:
100 /* we do not handle rekeying of CHILD_SAs in a special
101 * transaction, as the procedure is nearly equal
102 * to create a new CHILD_SA. */
103 default:
104 break;
105 }
106 if (transaction)
107 {
108 break;
109 }
110 }
111 iterator->destroy(iterator);
112 if (!transaction)
113 {
114 /* we have not found a REKEY_SA notify for IKE. This means
115 * we create a new CHILD_SA, or rekey an existing one.
116 * Both cases are handled with the create_child_sa transaction. */
117 transaction = (transaction_t*)create_child_sa_create(ike_sa, message_id);
118 }
119 break;
120 }
121 case INFORMATIONAL:
122 {
123 if (ike_sa->get_state(ike_sa) == SA_CREATED)
124 {
125 break;
126 }
127 u_int payload_count = 0;
128 iterator = request->get_payload_iterator(request);
129 while (iterator->has_next(iterator))
130 {
131 payload_count++;
132 iterator->current(iterator, (void**)&current);
133 switch (current->get_type(current))
134 {
135 case DELETE:
136 {
137 delete_payload_t *delete_payload;
138 delete_payload = (delete_payload_t*)current;
139 switch (delete_payload->get_protocol_id(delete_payload))
140 {
141 case PROTO_IKE:
142 transaction = (transaction_t*)
143 delete_ike_sa_create(ike_sa, message_id);
144 break;
145 case PROTO_AH:
146 case PROTO_ESP:
147 transaction = (transaction_t*)
148 delete_child_sa_create(ike_sa, message_id);
149 break;
150 default:
151 break;
152 }
153 break;
154 }
155 default:
156 break;
157 }
158 if (transaction)
159 {
160 break;
161 }
162 }
163 iterator->destroy(iterator);
164 /* empty informationals are used for dead peer detection in
165 * IKEv2. We use a special transaction for it. */
166 if (payload_count == 0)
167 {
168 transaction = (transaction_t*)
169 dead_peer_detection_create(ike_sa, message_id);
170 }
171 break;
172 }
173 default:
174 break;
175 }
176 return transaction;
177 }