Annotation of embedaddon/strongswan/src/libcharon/sa/redirect_manager.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2015 Tobias Brunner
3: * HSR 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:
16: #include "redirect_manager.h"
17:
18: #include <collections/linked_list.h>
19: #include <threading/rwlock.h>
20: #include <bio/bio_reader.h>
21: #include <bio/bio_writer.h>
22:
23: typedef struct private_redirect_manager_t private_redirect_manager_t;
24:
25: /**
26: * Private data
27: */
28: struct private_redirect_manager_t {
29:
30: /**
31: * Public interface
32: */
33: redirect_manager_t public;
34:
35: /**
36: * Registered providers
37: */
38: linked_list_t *providers;
39:
40: /**
41: * Lock to access list of providers
42: */
43: rwlock_t *lock;
44: };
45:
46:
47: /**
48: * Gateway identify types
49: *
50: * The encoding is the same as that for corresponding ID payloads.
51: */
52: typedef enum {
53: /** IPv4 address of the VPN gateway */
54: GATEWAY_ID_TYPE_IPV4 = 1,
55: /** IPv6 address of the VPN gateway */
56: GATEWAY_ID_TYPE_IPV6 = 2,
57: /** FQDN of the VPN gateway */
58: GATEWAY_ID_TYPE_FQDN = 3,
59: } gateway_id_type_t;
60:
61: /**
62: * Mapping of gateway identity types to identity types
63: */
64: static id_type_t gateway_to_id_type(gateway_id_type_t type)
65: {
66: switch (type)
67: {
68: case GATEWAY_ID_TYPE_IPV4:
69: return ID_IPV4_ADDR;
70: case GATEWAY_ID_TYPE_IPV6:
71: return ID_IPV6_ADDR;
72: case GATEWAY_ID_TYPE_FQDN:
73: return ID_FQDN;
74: default:
75: return 0;
76: }
77: }
78:
79: /**
80: * Mapping of identity types to gateway identity types
81: */
82: static gateway_id_type_t id_type_to_gateway(id_type_t type)
83: {
84: switch (type)
85: {
86: case ID_IPV4_ADDR:
87: return GATEWAY_ID_TYPE_IPV4;
88: case ID_IPV6_ADDR:
89: return GATEWAY_ID_TYPE_IPV6;
90: case ID_FQDN:
91: return GATEWAY_ID_TYPE_FQDN;
92: default:
93: return 0;
94: }
95: }
96:
97: METHOD(redirect_manager_t, add_provider, void,
98: private_redirect_manager_t *this, redirect_provider_t *provider)
99: {
100: this->lock->write_lock(this->lock);
101: this->providers->insert_last(this->providers, provider);
102: this->lock->unlock(this->lock);
103: }
104:
105: METHOD(redirect_manager_t, remove_provider, void,
106: private_redirect_manager_t *this, redirect_provider_t *provider)
107: {
108: this->lock->write_lock(this->lock);
109: this->providers->remove(this->providers, provider, NULL);
110: this->lock->unlock(this->lock);
111: }
112:
113: /**
114: * Determine whether a client should be redirected using the callback with the
115: * given offset into the redirect_provider_t interface.
116: */
117: static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa,
118: identification_t **gateway, size_t offset)
119: {
120: enumerator_t *enumerator;
121: void *provider;
122: bool redirect = FALSE;
123:
124: this->lock->read_lock(this->lock);
125: enumerator = this->providers->create_enumerator(this->providers);
126: while (enumerator->enumerate(enumerator, &provider))
127: {
128: bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset;
129: if (*method && (*method)(provider, ike_sa, gateway))
130: {
131: if (*gateway && id_type_to_gateway((*gateway)->get_type(*gateway)))
132: {
133: redirect = TRUE;
134: break;
135: }
136: else
137: {
138: DBG1(DBG_CFG, "redirect provider returned invalid gateway ID");
139: DESTROY_IF(*gateway);
140: }
141: }
142: }
143: enumerator->destroy(enumerator);
144: this->lock->unlock(this->lock);
145: return redirect;
146: }
147:
148: METHOD(redirect_manager_t, redirect_on_init, bool,
149: private_redirect_manager_t *this, ike_sa_t *ike_sa,
150: identification_t **gateway)
151: {
152: return should_redirect(this, ike_sa, gateway,
153: offsetof(redirect_provider_t, redirect_on_init));
154: }
155:
156: METHOD(redirect_manager_t, redirect_on_auth, bool,
157: private_redirect_manager_t *this, ike_sa_t *ike_sa,
158: identification_t **gateway)
159: {
160: return should_redirect(this, ike_sa, gateway,
161: offsetof(redirect_provider_t, redirect_on_auth));
162: }
163:
164: METHOD(redirect_manager_t, destroy, void,
165: private_redirect_manager_t *this)
166: {
167: this->providers->destroy(this->providers);
168: this->lock->destroy(this->lock);
169: free(this);
170: }
171:
172: /*
173: * Described in header
174: */
175: redirect_manager_t *redirect_manager_create()
176: {
177: private_redirect_manager_t *this;
178:
179: INIT(this,
180: .public = {
181: .add_provider = _add_provider,
182: .remove_provider = _remove_provider,
183: .redirect_on_init = _redirect_on_init,
184: .redirect_on_auth = _redirect_on_auth,
185: .destroy = _destroy,
186: },
187: .providers = linked_list_create(),
188: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
189: );
190:
191: return &this->public;
192: }
193:
194: /*
195: * Encoding of a REDIRECT or REDIRECTED_FROM notify
196: *
197: 1 2 3
198: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
199: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
200: | Next Payload |C| RESERVED | Payload Length |
201: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202: |Protocol ID(=0)| SPI Size (=0) | Notify Message Type |
203: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204: | GW Ident Type | GW Ident Len | |
205: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~
206: ~ New Responder GW Identity ~
207: | |
208: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
209: | |
210: ~ Nonce Data ~
211: | |
212: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213: */
214:
215: /*
216: * Described in header
217: */
218: chunk_t redirect_data_create(identification_t *gw, chunk_t nonce)
219: {
220: gateway_id_type_t type;
221: bio_writer_t *writer;
222: chunk_t data;
223:
224: type = id_type_to_gateway(gw->get_type(gw));
225: if (!type)
226: {
227: return chunk_empty;
228: }
229:
230: writer = bio_writer_create(0);
231: writer->write_uint8(writer, type);
232: writer->write_data8(writer, gw->get_encoding(gw));
233: if (nonce.ptr)
234: {
235: writer->write_data(writer, nonce);
236: }
237:
238: data = writer->extract_buf(writer);
239: writer->destroy(writer);
240: return data;
241: }
242:
243: /*
244: * Described in header
245: */
246: identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce)
247: {
248: bio_reader_t *reader;
249: id_type_t id_type;
250: chunk_t gateway;
251: uint8_t type;
252:
253: reader = bio_reader_create(data);
254: if (!reader->read_uint8(reader, &type) ||
255: !reader->read_data8(reader, &gateway))
256: {
257: DBG1(DBG_ENC, "invalid REDIRECT notify data");
258: reader->destroy(reader);
259: return NULL;
260: }
261: id_type = gateway_to_id_type(type);
262: if (!id_type)
263: {
264: DBG1(DBG_ENC, "invalid gateway ID type (%d) in REDIRECT notify", type);
265: reader->destroy(reader);
266: return NULL;
267: }
268: if (nonce)
269: {
270: *nonce = chunk_clone(reader->peek(reader));
271: }
272: reader->destroy(reader);
273: return identification_create_from_encoding(id_type, gateway);
274: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>