Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / push.c
blobf817c870e44d7a6ae40bc8bcbfb4a28c160e17f8
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "syshead.h"
27 #include "push.h"
28 #include "options.h"
29 #include "ssl.h"
30 #include "manage.h"
32 #include "memdbg.h"
34 #if P2MP
37 * Auth username/password
39 * Client received an authentication failed message from server.
40 * Runs on client.
42 void
43 receive_auth_failed (struct context *c, const struct buffer *buffer)
45 msg (M_VERB0, "AUTH: Received AUTH_FAILED control message");
46 if (c->options.pull)
48 switch (auth_retry_get ())
50 case AR_NONE:
51 c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
52 break;
53 case AR_INTERACT:
54 ssl_purge_auth ();
55 case AR_NOINTERACT:
56 c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
57 break;
58 default:
59 ASSERT (0);
61 c->sig->signal_text = "auth-failure";
62 #ifdef ENABLE_MANAGEMENT
63 if (management)
65 const char *reason = UP_TYPE_AUTH;
66 struct buffer buf = *buffer;
67 if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
68 reason = BSTR (&buf);
69 management_auth_failure (management, reason);
71 #endif
76 * Act on received restart message from server
78 void
79 server_pushed_restart (struct context *c, const struct buffer *buffer)
81 if (c->options.pull)
83 msg (D_STREAM_ERRORS, "Connection reset command was pushed by server");
84 c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
85 c->sig->signal_text = "server-pushed-connection-reset";
89 #if P2MP_SERVER
92 * Send auth failed message from server to client.
94 void
95 send_auth_failed (struct context *c, const char *client_reason)
97 struct gc_arena gc = gc_new ();
98 static const char auth_failed[] = "AUTH_FAILED";
99 size_t len;
101 schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
103 len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
104 if (len > TLS_CHANNEL_BUF_SIZE)
105 len = TLS_CHANNEL_BUF_SIZE;
108 struct buffer buf = alloc_buf_gc (len, &gc);
109 buf_printf (&buf, auth_failed);
110 if (client_reason)
111 buf_printf (&buf, ",%s", client_reason);
112 send_control_channel_string (c, BSTR (&buf), D_PUSH);
115 gc_free (&gc);
119 * Send restart message from server to client.
121 void
122 send_restart (struct context *c)
124 schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
125 send_control_channel_string (c, "RESTART", D_PUSH);
128 #endif
131 * Push/Pull
134 void
135 incoming_push_message (struct context *c, const struct buffer *buffer)
137 struct gc_arena gc = gc_new ();
138 unsigned int option_types_found = 0;
139 int status;
141 msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
143 status = process_incoming_push_msg (c,
144 buffer,
145 c->options.pull,
146 pull_permission_mask (c),
147 &option_types_found);
149 if (status == PUSH_MSG_ERROR)
150 msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
151 else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
153 if (status == PUSH_MSG_REPLY)
154 do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */
155 event_timeout_clear (&c->c2.push_request_interval);
158 gc_free (&gc);
161 bool
162 send_push_request (struct context *c)
164 return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH);
167 #if P2MP_SERVER
169 bool
170 send_push_reply (struct context *c)
172 struct gc_arena gc = gc_new ();
173 struct buffer buf = alloc_buf_gc (TLS_CHANNEL_BUF_SIZE, &gc);
174 struct push_entry *e = c->options.push_list.head;
175 bool multi_push = false;
176 static char cmd[] = "PUSH_REPLY";
177 const int extra = 64; /* extra space for possible trailing ifconfig and push-continuation */
178 const int safe_cap = BCAP (&buf) - extra;
180 buf_printf (&buf, cmd);
182 while (e)
184 if (e->enable)
186 const int l = strlen (e->option);
187 if (BLEN (&buf) + l >= safe_cap)
189 buf_printf (&buf, ",push-continuation 2");
191 const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
192 if (!status)
193 goto fail;
194 multi_push = true;
195 buf_reset_len (&buf);
196 buf_printf (&buf, cmd);
199 if (BLEN (&buf) + l >= safe_cap)
201 msg (M_WARN, "--push option is too long");
202 goto fail;
204 buf_printf (&buf, ",%s", e->option);
206 e = e->next;
209 if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
210 buf_printf (&buf, ",ifconfig %s %s",
211 print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
212 print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
213 if (multi_push)
214 buf_printf (&buf, ",push-continuation 1");
216 if (BLEN (&buf) > sizeof(cmd)-1)
218 const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
219 if (!status)
220 goto fail;
223 gc_free (&gc);
224 return true;
226 fail:
227 gc_free (&gc);
228 return false;
231 static void
232 push_option_ex (struct options *o, const char *opt, bool enable, int msglevel)
234 if (!string_class (opt, CC_ANY, CC_COMMA))
236 msg (msglevel, "PUSH OPTION FAILED (illegal comma (',') in string): '%s'", opt);
238 else
240 struct push_entry *e;
241 ALLOC_OBJ_CLEAR_GC (e, struct push_entry, &o->gc);
242 e->enable = true;
243 e->option = opt;
244 if (o->push_list.head)
246 ASSERT(o->push_list.tail);
247 o->push_list.tail->next = e;
248 o->push_list.tail = e;
250 else
252 ASSERT(!o->push_list.tail);
253 o->push_list.head = e;
254 o->push_list.tail = e;
259 void
260 push_option (struct options *o, const char *opt, int msglevel)
262 push_option_ex (o, opt, true, msglevel);
265 void
266 clone_push_list (struct options *o)
268 if (o->push_list.head)
270 const struct push_entry *e = o->push_list.head;
271 push_reset (o);
272 while (e)
274 push_option_ex (o, string_alloc (e->option, &o->gc), true, M_FATAL);
275 e = e->next;
280 void
281 push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc)
283 const char **argv = make_extended_arg_array (p, gc);
284 char *opt = print_argv (argv, gc, 0);
285 push_option (o, opt, msglevel);
288 void
289 push_reset (struct options *o)
291 CLEAR (o->push_list);
293 #endif
296 process_incoming_push_msg (struct context *c,
297 const struct buffer *buffer,
298 bool honor_received_options,
299 unsigned int permission_mask,
300 unsigned int *option_types_found)
302 int ret = PUSH_MSG_ERROR;
303 struct buffer buf = *buffer;
305 #if P2MP_SERVER
306 if (buf_string_compare_advance (&buf, "PUSH_REQUEST"))
308 if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
310 const char *client_reason = tls_client_reason (c->c2.tls_multi);
311 send_auth_failed (c, client_reason);
312 ret = PUSH_MSG_AUTH_FAILURE;
314 else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
316 if (send_push_reply (c))
317 ret = PUSH_MSG_REQUEST;
319 else
321 ret = PUSH_MSG_REQUEST_DEFERRED;
324 else
325 #endif
327 if (honor_received_options && buf_string_compare_advance (&buf, "PUSH_REPLY"))
329 const uint8_t ch = buf_read_u8 (&buf);
330 if (ch == ',')
332 struct buffer buf_orig = buf;
333 if (!c->c2.did_pre_pull_restore)
335 pre_pull_restore (&c->options);
336 md5_state_init (&c->c2.pulled_options_state);
337 c->c2.did_pre_pull_restore = true;
339 if (apply_push_options (&c->options,
340 &buf,
341 permission_mask,
342 option_types_found,
343 c->c2.es))
344 switch (c->options.push_continuation)
346 case 0:
347 case 1:
348 md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
349 md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
350 ret = PUSH_MSG_REPLY;
351 break;
352 case 2:
353 md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
354 ret = PUSH_MSG_CONTINUATION;
355 break;
358 else if (ch == '\0')
360 ret = PUSH_MSG_REPLY;
362 /* show_settings (&c->options); */
364 return ret;
367 #if P2MP_SERVER
370 * Remove iroutes from the push_list.
372 void
373 remove_iroutes_from_push_route_list (struct options *o)
375 if (o && o->push_list.head && o->iroutes)
377 struct gc_arena gc = gc_new ();
378 struct push_entry *e = o->push_list.head;
380 /* cycle through the push list */
381 while (e)
383 char *p[MAX_PARMS];
384 bool enable = true;
386 /* parse the push item */
387 CLEAR (p);
388 if (parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
390 /* is the push item a route directive? */
391 if (p[0] && !strcmp (p[0], "route") && !p[3])
393 /* get route parameters */
394 bool status1, status2;
395 const in_addr_t network = getaddr (GETADDR_HOST_ORDER, p[1], 0, &status1, NULL);
396 const in_addr_t netmask = getaddr (GETADDR_HOST_ORDER, p[2] ? p[2] : "255.255.255.255", 0, &status2, NULL);
398 /* did route parameters parse correctly? */
399 if (status1 && status2)
401 const struct iroute *ir;
403 /* does route match an iroute? */
404 for (ir = o->iroutes; ir != NULL; ir = ir->next)
406 if (network == ir->network && netmask == netbits_to_netmask (ir->netbits >= 0 ? ir->netbits : 32))
408 enable = false;
409 break;
416 /* should we copy the push item? */
417 e->enable = enable;
418 if (!enable)
419 msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option);
421 e = e->next;
424 gc_free (&gc);
428 #endif
430 #endif