~ubuntu-branches/ubuntu/trusty/openvpn/trusty-security

1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
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.
7
 *
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
8
 *  Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
11
 *  it under the terms of the GNU General Public License version 2
12
 *  as published by the Free Software Foundation.
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
13
 *
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.
18
 *
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
23
 */
24
25
#ifdef WIN32
26
#include "config-win32.h"
27
#else
28
#include "config.h"
29
#endif
30
31
#include "syshead.h"
32
33
#include "push.h"
34
#include "options.h"
35
#include "ssl.h"
36
#include "manage.h"
37
38
#include "memdbg.h"
39
40
#if P2MP
41
42
/*
43
 * Auth username/password
44
 *
45
 * Client received an authentication failed message from server.
46
 * Runs on client.
47
 */
48
void
49
receive_auth_failed (struct context *c, const struct buffer *buffer)
50
{
51
  msg (M_VERB0, "AUTH: Received AUTH_FAILED control message");
52
  if (c->options.pull)
53
    {
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
54
      switch (auth_retry_get ())
55
	{
56
	case AR_NONE:
57
	  c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
58
	  break;
59
	case AR_INTERACT:
60
	  ssl_purge_auth ();
61
	case AR_NOINTERACT:
62
	  c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
63
	  break;
64
	default:
65
	  ASSERT (0);
66
	}
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
67
      c->sig->signal_text = "auth-failure";
68
#ifdef ENABLE_MANAGEMENT
69
      if (management)
70
	management_auth_failure (management, UP_TYPE_AUTH);
71
#endif
72
    }
73
}
74
75
#if P2MP_SERVER
76
/*
77
 * Send auth failed message from server to client.
78
 */
79
bool
80
send_auth_failed (struct context *c)
81
{
82
  return send_control_channel_string (c, "AUTH_FAILED", D_PUSH);
83
}
84
#endif
85
86
/*
87
 * Push/Pull
88
 */
89
90
void
91
incoming_push_message (struct context *c, const struct buffer *buffer)
92
{
93
  struct gc_arena gc = gc_new ();
94
  unsigned int option_types_found = 0;
95
  int status;
96
97
  msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
98
99
  status = process_incoming_push_msg (c,
100
				      buffer,
101
				      c->options.pull,
102
				      pull_permission_mask (),
103
				      &option_types_found);
104
105
  if (status == PUSH_MSG_ERROR)
106
    msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
107
  else if (status == PUSH_MSG_REPLY)
108
    {
109
      do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */
110
      event_timeout_clear (&c->c2.push_request_interval);
111
    }
112
113
  gc_free (&gc);
114
}
115
116
bool
117
send_push_request (struct context *c)
118
{
119
  return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH);
120
}
121
122
#if P2MP_SERVER
123
bool
124
send_push_reply (struct context *c)
125
{
126
  struct gc_arena gc = gc_new ();
127
  struct buffer buf = alloc_buf_gc (MAX_PUSH_LIST_LEN + 256, &gc);
128
  bool ret = false;
129
130
  buf_printf (&buf, "PUSH_REPLY");
131
132
  if (c->options.push_list && strlen (c->options.push_list->options))
133
    buf_printf (&buf, ",%s", c->options.push_list->options);
134
135
  if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
136
    buf_printf (&buf, ",ifconfig %s %s",
137
		print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
138
		print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
139
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
140
  if (strlen (BSTR (&buf)) < MAX_PUSH_LIST_LEN)
141
    ret = send_control_channel_string (c, BSTR (&buf), D_PUSH);
142
  else
143
    msg (M_WARN, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN);
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
144
145
  gc_free (&gc);
146
  return ret;
147
}
148
149
void
150
push_option (struct options *o, const char *opt, int msglevel)
151
{
152
  int len;
153
  bool first = false;
154
155
  if (!string_class (opt, CC_ANY, CC_COMMA))
156
    {
157
      msg (msglevel, "PUSH OPTION FAILED (illegal comma (',') in string): '%s'", opt);
158
    }
159
  else
160
    {
161
      if (!o->push_list)
162
	{
163
	  ALLOC_OBJ_CLEAR_GC (o->push_list, struct push_list, &o->gc);
164
	  first = true;
165
	}
166
167
      len = strlen (o->push_list->options);
168
      if (len + strlen (opt) + 2 >= MAX_PUSH_LIST_LEN)
169
	{
170
	  msg (msglevel, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN);
171
	}
172
      else
173
	{
174
	  if (!first)
175
	    strcat (o->push_list->options, ",");
176
	  strcat (o->push_list->options, opt);
177
	}
178
    }
179
}
180
181
void
182
push_reset (struct options *o)
183
{
184
  o->push_list = NULL;
185
}
186
#endif
187
188
int
189
process_incoming_push_msg (struct context *c,
190
			   const struct buffer *buffer,
191
			   bool honor_received_options,
192
			   unsigned int permission_mask,
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
193
			   unsigned int *option_types_found)
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
194
{
195
  int ret = PUSH_MSG_ERROR;
196
  struct buffer buf = *buffer;
197
198
#if P2MP_SERVER
199
  if (buf_string_compare_advance (&buf, "PUSH_REQUEST"))
200
    {
201
      if (!tls_authenticated (c->c2.tls_multi) || c->c2.context_auth == CAS_FAILED)
202
	{
203
	  send_auth_failed (c);
204
	  schedule_exit (c, c->options.scheduled_exit_interval);
205
	  ret = PUSH_MSG_AUTH_FAILURE;
206
	}
207
      else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
208
	{
209
	  if (send_push_reply (c))
210
	    ret = PUSH_MSG_REQUEST;
211
	}
212
      else
213
	{
214
	  ret = PUSH_MSG_REQUEST_DEFERRED;
215
	}
216
    }
217
  else
218
#endif
219
220
  if (honor_received_options && buf_string_compare_advance (&buf, "PUSH_REPLY"))
221
    {
222
      const uint8_t ch = buf_read_u8 (&buf);
223
      if (ch == ',')
224
	{
225
	  pre_pull_restore (&c->options);
226
	  c->c2.pulled_options_string = string_alloc (BSTR (&buf), &c->c2.gc);
227
	  if (apply_push_options (&c->options,
228
				  &buf,
229
				  permission_mask,
230
				  option_types_found,
231
				  c->c2.es))
232
	    ret = PUSH_MSG_REPLY;
233
	}
234
      else if (ch == '\0')
235
	{
236
	  ret = PUSH_MSG_REPLY;
237
	}
238
      /* show_settings (&c->options); */
239
    }
240
  return ret;
241
}
242
243
#if P2MP_SERVER
244
/*
245
 * Remove iroutes from the push_list.
246
 */
247
void
248
remove_iroutes_from_push_route_list (struct options *o)
249
{
250
  if (o && o->push_list && o->iroutes)
251
    {
252
      struct gc_arena gc = gc_new ();
253
      struct push_list *pl;
254
      struct buffer in, out;
255
      char *line;
256
      bool first = true;
257
258
      /* prepare input and output buffers */
259
      ALLOC_OBJ_CLEAR_GC (pl, struct push_list, &gc);
260
      ALLOC_ARRAY_CLEAR_GC (line, char, MAX_PUSH_LIST_LEN, &gc);
261
1.1.2 by Alberto Gonzalez Iniesta
Import upstream version 2.0.2
262
      buf_set_read (&in, (const uint8_t*) o->push_list->options, strlen (o->push_list->options));
263
      buf_set_write (&out, (uint8_t*) pl->options, sizeof (pl->options));
1.1.1 by Alberto Gonzalez Iniesta
Import upstream version 1.99+2.rc6
264
265
      /* cycle through the push list */
266
      while (buf_parse (&in, ',', line, MAX_PUSH_LIST_LEN))
267
	{
268
	  char *p[MAX_PARMS];
269
	  bool copy = true;
270
271
	  /* parse the push item */
272
	  CLEAR (p);
273
	  if (parse_line (line, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
274
	    {
275
	      /* is the push item a route directive? */
276
	      if (p[0] && p[1] && p[2] && !strcmp (p[0], "route"))
277
		{
278
		  /* get route parameters */
279
		  bool status1, status2;
280
		  const in_addr_t network = getaddr (GETADDR_HOST_ORDER, p[1], 0, &status1, NULL);
281
		  const in_addr_t netmask = getaddr (GETADDR_HOST_ORDER, p[2], 0, &status2, NULL);
282
283
		  /* did route parameters parse correctly? */
284
		  if (status1 && status2)
285
		    {
286
		      const struct iroute *ir;
287
288
		      /* does route match an iroute? */
289
		      for (ir = o->iroutes; ir != NULL; ir = ir->next)
290
			{
291
			  if (network == ir->network && netmask == netbits_to_netmask (ir->netbits))
292
			    {
293
			      copy = false;
294
			      break;
295
			    }
296
			}
297
		    }
298
		}
299
	    }
300
301
	  /* should we copy the push item? */
302
	  if (copy)
303
	    {
304
	      if (!first)
305
		buf_printf (&out, ",");
306
	      buf_printf (&out, "%s", line);
307
	      first = false;
308
	    }
309
	  else
310
	    msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", line);
311
	}
312
313
#if 0
314
      msg (M_INFO, "BEFORE: '%s'", o->push_list->options);
315
      msg (M_INFO, "AFTER:  '%s'", pl->options);
316
#endif
317
318
      /* copy new push list back to options */
319
      *o->push_list = *pl;
320
321
      gc_free (&gc);
322
    }
323
}
324
#endif
325
326
#endif