a3cad0b40037d5c97f2b0f9536935e70bb6847b9
[strongswan.git] / src / charon / sa / tasks / ike_cert_post.c
1 /*
2 * Copyright (C) 2006-2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 * $Id$
16 */
17
18 #include "ike_cert_post.h"
19
20 #include <daemon.h>
21 #include <sa/ike_sa.h>
22 #include <encoding/payloads/cert_payload.h>
23 #include <encoding/payloads/certreq_payload.h>
24 #include <credentials/certificates/x509.h>
25
26
27 typedef struct private_ike_cert_post_t private_ike_cert_post_t;
28
29 /**
30 * Private members of a ike_cert_post_t task.
31 */
32 struct private_ike_cert_post_t {
33
34 /**
35 * Public methods and task_t interface.
36 */
37 ike_cert_post_t public;
38
39 /**
40 * Assigned IKE_SA.
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Are we the initiator?
46 */
47 bool initiator;
48 };
49
50 /**
51 * add certificates to message
52 */
53 static void build_certs(private_ike_cert_post_t *this, message_t *message)
54 {
55 peer_cfg_t *peer_cfg;
56
57 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
58 if (peer_cfg && peer_cfg->get_auth_method(peer_cfg) == AUTH_RSA)
59 {
60 switch (peer_cfg->get_cert_policy(peer_cfg))
61 {
62 case CERT_NEVER_SEND:
63 break;
64 case CERT_SEND_IF_ASKED:
65 if (!this->ike_sa->has_condition(this->ike_sa, COND_CERTREQ_SEEN))
66 {
67 break;
68 }
69 /* FALL */
70 case CERT_ALWAYS_SEND:
71 {
72 cert_payload_t *payload;
73 enumerator_t *enumerator;
74 certificate_t *cert;
75 auth_info_t *auth;
76 auth_item_t item;
77
78 auth = this->ike_sa->get_my_auth(this->ike_sa);
79 /* get subject cert first, then issuing certificates */
80 if (!auth->get_item(auth, AUTHZ_SUBJECT_CERT, (void**)&cert))
81 {
82 break;
83 }
84 payload = cert_payload_create_from_cert(cert);
85 if (!payload)
86 {
87 break;
88 }
89 DBG1(DBG_IKE, "sending end entity cert %D",
90 cert->get_subject(cert));
91 message->add_payload(message, (payload_t*)payload);
92
93 enumerator = auth->create_item_enumerator(auth);
94 while (enumerator->enumerate(enumerator, &item, &cert))
95 {
96 if (item == AUTHZ_IM_CERT)
97 {
98 payload = cert_payload_create_from_cert(cert);
99 if (payload)
100 {
101 DBG1(DBG_IKE, "sending issuer cert %D",
102 cert->get_subject(cert));
103 message->add_payload(message, (payload_t*)payload);
104 }
105 }
106 }
107 enumerator->destroy(enumerator);
108 }
109 }
110 }
111 }
112
113 /**
114 * Implementation of task_t.process for initiator
115 */
116 static status_t build_i(private_ike_cert_post_t *this, message_t *message)
117 {
118 if (message->get_exchange_type(message) == IKE_SA_INIT)
119 {
120 return NEED_MORE;
121 }
122 build_certs(this, message);
123 return SUCCESS;
124 }
125
126 /**
127 * Implementation of task_t.process for responder
128 */
129 static status_t process_r(private_ike_cert_post_t *this, message_t *message)
130 {
131 return NEED_MORE;
132 }
133
134 /**
135 * Implementation of task_t.build for responder
136 */
137 static status_t build_r(private_ike_cert_post_t *this, message_t *message)
138 {
139 if (message->get_exchange_type(message) == IKE_SA_INIT)
140 {
141 return NEED_MORE;
142 }
143 build_certs(this, message);
144 return SUCCESS;
145 }
146
147 /**
148 * Implementation of task_t.process for initiator
149 */
150 static status_t process_i(private_ike_cert_post_t *this, message_t *message)
151 {
152 if (message->get_exchange_type(message) == IKE_SA_INIT)
153 {
154 return NEED_MORE;
155 }
156 return SUCCESS;
157 }
158
159 /**
160 * Implementation of task_t.get_type
161 */
162 static task_type_t get_type(private_ike_cert_post_t *this)
163 {
164 return IKE_CERT_POST;
165 }
166
167 /**
168 * Implementation of task_t.migrate
169 */
170 static void migrate(private_ike_cert_post_t *this, ike_sa_t *ike_sa)
171 {
172 this->ike_sa = ike_sa;
173 }
174
175 /**
176 * Implementation of task_t.destroy
177 */
178 static void destroy(private_ike_cert_post_t *this)
179 {
180 free(this);
181 }
182
183 /*
184 * Described in header.
185 */
186 ike_cert_post_t *ike_cert_post_create(ike_sa_t *ike_sa, bool initiator)
187 {
188 private_ike_cert_post_t *this = malloc_thing(private_ike_cert_post_t);
189
190 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
191 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
192 this->public.task.destroy = (void(*)(task_t*))destroy;
193
194 if (initiator)
195 {
196 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
197 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
198 }
199 else
200 {
201 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
202 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
203 }
204
205 this->ike_sa = ike_sa;
206 this->initiator = initiator;
207
208 return &this->public;
209 }
210