Handle first exchange in IKEv1 main mode as responder
[strongswan.git] / src / libcharon / sa / tasks / main_mode.c
1 /*
2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 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 "main_mode.h"
17
18 #include <string.h>
19
20 #include <daemon.h>
21 #include <crypto/diffie_hellman.h>
22 #include <encoding/payloads/sa_payload.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/nonce_payload.h>
25
26 typedef struct private_main_mode_t private_main_mode_t;
27
28 /**
29 * Private members of a main_mode_t task.
30 */
31 struct private_main_mode_t {
32
33 /**
34 * Public methods and task_t interface.
35 */
36 main_mode_t public;
37
38 /**
39 * Assigned IKE_SA.
40 */
41 ike_sa_t *ike_sa;
42
43 /**
44 * Are we the initiator?
45 */
46 bool initiator;
47
48 /**
49 * IKE config to establish
50 */
51 ike_cfg_t *config;
52
53 /**
54 * selected IKE proposal
55 */
56 proposal_t *proposal;
57 };
58
59 METHOD(task_t, build_i, status_t,
60 private_main_mode_t *this, message_t *message)
61 {
62 /* TODO-IKEv1: initiate mainmode */
63 return FAILED;
64 }
65
66 METHOD(task_t, process_r, status_t,
67 private_main_mode_t *this, message_t *message)
68 {
69 this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
70 DBG0(DBG_IKE, "%H is initiating a Main Mode", message->get_source(message));
71 this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
72
73 if (!this->proposal)
74 {
75 linked_list_t *list;
76 sa_payload_t *sa_payload;
77
78 sa_payload = (sa_payload_t*)message->get_payload(message,
79 SECURITY_ASSOCIATION_V1);
80 if (!sa_payload)
81 {
82 DBG1(DBG_IKE, "SA payload missing");
83 return FAILED;
84 }
85 list = sa_payload->get_proposals(sa_payload);
86 this->proposal = this->config->select_proposal(this->config, list, FALSE);
87
88 if (!this->proposal)
89 {
90 DBG1(DBG_IKE, "no proposal found");
91 return FAILED;
92 }
93 }
94 return NEED_MORE;
95 }
96
97 METHOD(task_t, build_r, status_t,
98 private_main_mode_t *this, message_t *message)
99 {
100 sa_payload_t *sa_payload;
101
102 sa_payload = sa_payload_create_from_proposal(SECURITY_ASSOCIATION_V1,
103 this->proposal);
104 message->add_payload(message, &sa_payload->payload_interface);
105 return NEED_MORE;
106 }
107
108 METHOD(task_t, process_i, status_t,
109 private_main_mode_t *this, message_t *message)
110 {
111 /* TODO-IKEv1: process main mode as initiator */
112 return FAILED;
113 }
114
115 METHOD(task_t, get_type, task_type_t,
116 private_main_mode_t *this)
117 {
118 return MAIN_MODE;
119 }
120
121 METHOD(task_t, migrate, void,
122 private_main_mode_t *this, ike_sa_t *ike_sa)
123 {
124 this->ike_sa = ike_sa;
125 }
126
127 METHOD(task_t, destroy, void,
128 private_main_mode_t *this)
129 {
130 DESTROY_IF(this->proposal);
131 free(this);
132 }
133
134 /*
135 * Described in header.
136 */
137 main_mode_t *main_mode_create(ike_sa_t *ike_sa, bool initiator)
138 {
139 private_main_mode_t *this;
140
141 INIT(this,
142 .public = {
143 .task = {
144 .get_type = _get_type,
145 .migrate = _migrate,
146 .destroy = _destroy,
147 },
148 },
149 .ike_sa = ike_sa,
150 .initiator = initiator,
151 );
152
153 if (initiator)
154 {
155 this->public.task.build = _build_i;
156 this->public.task.process = _process_i;
157 }
158 else
159 {
160 this->public.task.build = _build_r;
161 this->public.task.process = _process_r;
162 }
163
164 return &this->public;
165 }