~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/ipv6-payload.patch/push.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 *
8
 
 *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9
 
 *
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.
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
 
#include "syshead.h"
26
 
 
27
 
#include "push.h"
28
 
#include "options.h"
29
 
#include "ssl.h"
30
 
#include "manage.h"
31
 
 
32
 
#include "memdbg.h"
33
 
 
34
 
#if P2MP
35
 
 
36
 
/*
37
 
 * Auth username/password
38
 
 *
39
 
 * Client received an authentication failed message from server.
40
 
 * Runs on client.
41
 
 */
42
 
void
43
 
receive_auth_failed (struct context *c, const struct buffer *buffer)
44
 
{
45
 
  msg (M_VERB0, "AUTH: Received AUTH_FAILED control message");
46
 
  connection_list_set_no_advance(&c->options);
47
 
  if (c->options.pull)
48
 
    {
49
 
      switch (auth_retry_get ())
50
 
        {
51
 
        case AR_NONE:
52
 
          c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
53
 
          break;
54
 
        case AR_INTERACT:
55
 
          ssl_purge_auth ();
56
 
        case AR_NOINTERACT:
57
 
          c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
58
 
          break;
59
 
        default:
60
 
          ASSERT (0);
61
 
        }
62
 
      c->sig->signal_text = "auth-failure";
63
 
#ifdef ENABLE_MANAGEMENT
64
 
      if (management)
65
 
        {
66
 
          const char *reason = NULL;
67
 
          struct buffer buf = *buffer;
68
 
          if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
69
 
            reason = BSTR (&buf);
70
 
          management_auth_failure (management, UP_TYPE_AUTH, reason);
71
 
        } else
72
 
#endif
73
 
        {
74
 
#ifdef ENABLE_CLIENT_CR
75
 
          struct buffer buf = *buffer;
76
 
          if (buf_string_match_head_str (&buf, "AUTH_FAILED,CRV1:") && BLEN (&buf))
77
 
            {
78
 
              buf_advance (&buf, 12); /* Length of "AUTH_FAILED," substring */
79
 
              ssl_put_auth_challenge (BSTR (&buf));
80
 
            }
81
 
#endif
82
 
        }
83
 
    }
84
 
}
85
 
 
86
 
/*
87
 
 * Act on received restart message from server
88
 
 */
89
 
void
90
 
server_pushed_restart (struct context *c, const struct buffer *buffer)
91
 
{
92
 
  if (c->options.pull)
93
 
    {
94
 
      msg (D_STREAM_ERRORS, "Connection reset command was pushed by server");
95
 
      c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
96
 
      c->sig->signal_text = "server-pushed-connection-reset";
97
 
    }
98
 
}
99
 
 
100
 
#if P2MP_SERVER
101
 
 
102
 
/*
103
 
 * Send auth failed message from server to client.
104
 
 */
105
 
void
106
 
send_auth_failed (struct context *c, const char *client_reason)
107
 
{
108
 
  struct gc_arena gc = gc_new ();
109
 
  static const char auth_failed[] = "AUTH_FAILED";
110
 
  size_t len;
111
 
 
112
 
  schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
113
 
 
114
 
  len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
115
 
  if (len > PUSH_BUNDLE_SIZE)
116
 
    len = PUSH_BUNDLE_SIZE;
117
 
 
118
 
  {
119
 
    struct buffer buf = alloc_buf_gc (len, &gc);
120
 
    buf_printf (&buf, auth_failed);
121
 
    if (client_reason)
122
 
      buf_printf (&buf, ",%s", client_reason);
123
 
    send_control_channel_string (c, BSTR (&buf), D_PUSH);
124
 
  }
125
 
 
126
 
  gc_free (&gc);
127
 
}
128
 
 
129
 
/*
130
 
 * Send restart message from server to client.
131
 
 */
132
 
void
133
 
send_restart (struct context *c)
134
 
{
135
 
  schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
136
 
  send_control_channel_string (c, "RESTART", D_PUSH);
137
 
}
138
 
 
139
 
#endif
140
 
 
141
 
/*
142
 
 * Push/Pull
143
 
 */
144
 
 
145
 
void
146
 
incoming_push_message (struct context *c, const struct buffer *buffer)
147
 
{
148
 
  struct gc_arena gc = gc_new ();
149
 
  unsigned int option_types_found = 0;
150
 
  int status;
151
 
 
152
 
  msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
153
 
 
154
 
  status = process_incoming_push_msg (c,
155
 
                                      buffer,
156
 
                                      c->options.pull,
157
 
                                      pull_permission_mask (c),
158
 
                                      &option_types_found);
159
 
 
160
 
  if (status == PUSH_MSG_ERROR)
161
 
    msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
162
 
  else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
163
 
    {
164
 
      if (status == PUSH_MSG_REPLY)
165
 
        do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */
166
 
      event_timeout_clear (&c->c2.push_request_interval);
167
 
    }
168
 
 
169
 
  gc_free (&gc);
170
 
}
171
 
 
172
 
bool
173
 
send_push_request (struct context *c)
174
 
{
175
 
  return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH);
176
 
}
177
 
 
178
 
#if P2MP_SERVER
179
 
 
180
 
bool
181
 
send_push_reply (struct context *c)
182
 
{
183
 
  struct gc_arena gc = gc_new ();
184
 
  struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc);
185
 
  struct push_entry *e = c->options.push_list.head;
186
 
  bool multi_push = false;
187
 
  static char cmd[] = "PUSH_REPLY";
188
 
  const int extra = 64; /* extra space for possible trailing ifconfig and push-continuation */
189
 
  const int safe_cap = BCAP (&buf) - extra;
190
 
  bool push_sent = false;
191
 
 
192
 
  buf_printf (&buf, "%s", cmd);
193
 
 
194
 
  while (e)
195
 
    {
196
 
      if (e->enable)
197
 
        {
198
 
          const int l = strlen (e->option);
199
 
          if (BLEN (&buf) + l >= safe_cap)
200
 
            {
201
 
              buf_printf (&buf, ",push-continuation 2");
202
 
              {
203
 
                const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
204
 
                if (!status)
205
 
                  goto fail;
206
 
                push_sent = true;
207
 
                multi_push = true;
208
 
                buf_reset_len (&buf);
209
 
                buf_printf (&buf, "%s", cmd);
210
 
              }
211
 
            }
212
 
          if (BLEN (&buf) + l >= safe_cap)
213
 
            {
214
 
              msg (M_WARN, "--push option is too long");
215
 
              goto fail;
216
 
            }
217
 
          buf_printf (&buf, ",%s", e->option);
218
 
        }
219
 
      e = e->next;
220
 
    }
221
 
 
222
 
  if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
223
 
    buf_printf (&buf, ",ifconfig %s %s",
224
 
                print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
225
 
                print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
226
 
  if (multi_push)
227
 
    buf_printf (&buf, ",push-continuation 1");
228
 
 
229
 
  if (BLEN (&buf) > sizeof(cmd)-1)
230
 
    {
231
 
      const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
232
 
      if (!status)
233
 
        goto fail;
234
 
      push_sent = true;
235
 
    }
236
 
 
237
 
  /* If nothing have been pushed, send an empty push,
238
 
   * as the client is expecting a response
239
 
   */
240
 
  if (!push_sent)
241
 
    {
242
 
      bool status = false;
243
 
 
244
 
      buf_reset_len (&buf);
245
 
      buf_printf (&buf, "%s", cmd);
246
 
      status = send_control_channel_string (c, BSTR(&buf), D_PUSH);
247
 
      if (!status)
248
 
        goto fail;
249
 
    }
250
 
 
251
 
  gc_free (&gc);
252
 
  return true;
253
 
 
254
 
 fail:
255
 
  gc_free (&gc);
256
 
  return false;
257
 
}
258
 
 
259
 
static void
260
 
push_option_ex (struct options *o, const char *opt, bool enable, int msglevel)
261
 
{
262
 
  if (!string_class (opt, CC_ANY, CC_COMMA))
263
 
    {
264
 
      msg (msglevel, "PUSH OPTION FAILED (illegal comma (',') in string): '%s'", opt);
265
 
    }
266
 
  else
267
 
    {
268
 
      struct push_entry *e;
269
 
      ALLOC_OBJ_CLEAR_GC (e, struct push_entry, &o->gc);
270
 
      e->enable = true;
271
 
      e->option = opt;
272
 
      if (o->push_list.head)
273
 
        {
274
 
          ASSERT(o->push_list.tail);
275
 
          o->push_list.tail->next = e;
276
 
          o->push_list.tail = e;
277
 
        }
278
 
      else
279
 
        {
280
 
          ASSERT(!o->push_list.tail);
281
 
          o->push_list.head = e;
282
 
          o->push_list.tail = e;
283
 
        }
284
 
    }
285
 
}
286
 
 
287
 
void
288
 
push_option (struct options *o, const char *opt, int msglevel)
289
 
{
290
 
  push_option_ex (o, opt, true, msglevel);
291
 
}
292
 
 
293
 
void
294
 
clone_push_list (struct options *o)
295
 
{
296
 
  if (o->push_list.head)
297
 
    {
298
 
      const struct push_entry *e = o->push_list.head;
299
 
      push_reset (o);
300
 
      while (e)
301
 
        {
302
 
          push_option_ex (o, string_alloc (e->option, &o->gc), true, M_FATAL);
303
 
          e = e->next;
304
 
        }
305
 
    }
306
 
}
307
 
 
308
 
void
309
 
push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc)
310
 
{
311
 
  const char **argv = make_extended_arg_array (p, gc);
312
 
  char *opt = print_argv (argv, gc, 0);
313
 
  push_option (o, opt, msglevel);
314
 
}
315
 
 
316
 
void
317
 
push_reset (struct options *o)
318
 
{
319
 
  CLEAR (o->push_list);
320
 
}
321
 
#endif
322
 
 
323
 
int
324
 
process_incoming_push_msg (struct context *c,
325
 
                           const struct buffer *buffer,
326
 
                           bool honor_received_options,
327
 
                           unsigned int permission_mask,
328
 
                           unsigned int *option_types_found)
329
 
{
330
 
  int ret = PUSH_MSG_ERROR;
331
 
  struct buffer buf = *buffer;
332
 
 
333
 
#if P2MP_SERVER
334
 
  if (buf_string_compare_advance (&buf, "PUSH_REQUEST"))
335
 
    {
336
 
      if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
337
 
        {
338
 
          const char *client_reason = tls_client_reason (c->c2.tls_multi);
339
 
          send_auth_failed (c, client_reason);
340
 
          ret = PUSH_MSG_AUTH_FAILURE;
341
 
        }
342
 
      else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
343
 
        {
344
 
          if (send_push_reply (c))
345
 
            ret = PUSH_MSG_REQUEST;
346
 
        }
347
 
      else
348
 
        {
349
 
          ret = PUSH_MSG_REQUEST_DEFERRED;
350
 
        }
351
 
    }
352
 
  else
353
 
#endif
354
 
 
355
 
  if (honor_received_options && buf_string_compare_advance (&buf, "PUSH_REPLY"))
356
 
    {
357
 
      const uint8_t ch = buf_read_u8 (&buf);
358
 
      if (ch == ',')
359
 
        {
360
 
          struct buffer buf_orig = buf;
361
 
          if (!c->c2.did_pre_pull_restore)
362
 
            {
363
 
              pre_pull_restore (&c->options);
364
 
              md5_state_init (&c->c2.pulled_options_state);
365
 
              c->c2.did_pre_pull_restore = true;
366
 
            }
367
 
          if (apply_push_options (&c->options,
368
 
                                  &buf,
369
 
                                  permission_mask,
370
 
                                  option_types_found,
371
 
                                  c->c2.es))
372
 
            switch (c->options.push_continuation)
373
 
              {
374
 
              case 0:
375
 
              case 1:
376
 
                md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
377
 
                md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
378
 
                ret = PUSH_MSG_REPLY;
379
 
                break;
380
 
              case 2:
381
 
                md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
382
 
                ret = PUSH_MSG_CONTINUATION;
383
 
                break;
384
 
              }
385
 
        }
386
 
      else if (ch == '\0')
387
 
        {
388
 
          ret = PUSH_MSG_REPLY;
389
 
        }
390
 
      /* show_settings (&c->options); */
391
 
    }
392
 
  return ret;
393
 
}
394
 
 
395
 
#if P2MP_SERVER
396
 
 
397
 
/*
398
 
 * Remove iroutes from the push_list.
399
 
 */
400
 
void
401
 
remove_iroutes_from_push_route_list (struct options *o)
402
 
{
403
 
  if (o && o->push_list.head && o->iroutes)
404
 
    {
405
 
      struct gc_arena gc = gc_new ();
406
 
      struct push_entry *e = o->push_list.head;
407
 
 
408
 
      /* cycle through the push list */
409
 
      while (e)
410
 
        {
411
 
          char *p[MAX_PARMS];
412
 
          bool enable = true;
413
 
 
414
 
          /* parse the push item */
415
 
          CLEAR (p);
416
 
          if (parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
417
 
            {
418
 
              /* is the push item a route directive? */
419
 
              if (p[0] && !strcmp (p[0], "route") && !p[3])
420
 
                {
421
 
                  /* get route parameters */
422
 
                  bool status1, status2;
423
 
                  const in_addr_t network = getaddr (GETADDR_HOST_ORDER, p[1], 0, &status1, NULL);
424
 
                  const in_addr_t netmask = getaddr (GETADDR_HOST_ORDER, p[2] ? p[2] : "255.255.255.255", 0, &status2, NULL);
425
 
 
426
 
                  /* did route parameters parse correctly? */
427
 
                  if (status1 && status2)
428
 
                    {
429
 
                      const struct iroute *ir;
430
 
 
431
 
                      /* does route match an iroute? */
432
 
                      for (ir = o->iroutes; ir != NULL; ir = ir->next)
433
 
                        {
434
 
                          if (network == ir->network && netmask == netbits_to_netmask (ir->netbits >= 0 ? ir->netbits : 32))
435
 
                            {
436
 
                              enable = false;
437
 
                              break;
438
 
                            }
439
 
                        }
440
 
                    }
441
 
                }
442
 
            }
443
 
 
444
 
          /* should we copy the push item? */
445
 
          e->enable = enable;
446
 
          if (!enable)
447
 
            msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option);
448
 
 
449
 
          e = e->next;
450
 
        }
451
 
 
452
 
      gc_free (&gc);
453
 
    }
454
 
}
455
 
 
456
 
#endif
457
 
 
458
 
#endif