Browse code

Implemented a key/value auth channel from client to server.

Version 2.1.1i


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5668 e7ae566f-a301-0410-adde-c780ea21d3b5

James Yonan authored on 2010/06/01 16:12:27
Showing 14 changed files
... ...
@@ -76,8 +76,15 @@ typedef unsigned long ptr_type;
76 76
 /*
77 77
  * This parameter controls the TLS channel buffer size and the
78 78
  * maximum size of a single TLS message (cleartext).
79
+ * This parameter must be >= PUSH_BUNDLE_SIZE
79 80
  */
80
-#define TLS_CHANNEL_BUF_SIZE 1024
81
+#define TLS_CHANNEL_BUF_SIZE 2048
82
+
83
+/*
84
+ * This parameter controls the maximum size of a bundle
85
+ * of pushed options.
86
+ */
87
+#define PUSH_BUNDLE_SIZE 1024
81 88
 
82 89
 /*
83 90
  * A sort of pseudo-filename for data provided inline within
... ...
@@ -2007,6 +2007,9 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2007 2007
   to.renegotiate_packets = options->renegotiate_packets;
2008 2008
   to.renegotiate_seconds = options->renegotiate_seconds;
2009 2009
   to.single_session = options->single_session;
2010
+#ifdef ENABLE_PUSH_PEER_INFO
2011
+  to.push_peer_info = options->push_peer_info;
2012
+#endif
2010 2013
 
2011 2014
   /* should we not xmit any packets until we get an initial
2012 2015
      response from client? */
... ...
@@ -2275,6 +2275,58 @@ man_output_extra_env (struct management *man)
2275 2275
   gc_free (&gc);
2276 2276
 }
2277 2277
 
2278
+static bool
2279
+validate_peer_info_line(const char *line)
2280
+{
2281
+  uint8_t c;
2282
+  int state = 0;
2283
+  while ((c=*line++))
2284
+    {
2285
+      switch (state)
2286
+	{
2287
+	case 0:
2288
+	case 1:
2289
+	  if (c == '=' && state == 1)
2290
+	    state = 2;
2291
+	  else if (isalnum(c) || c == '_')
2292
+	    state = 1;
2293
+	  else
2294
+	    return false;
2295
+	case 2:
2296
+	  if (isprint(c))
2297
+	    ;
2298
+	  else
2299
+	    return false;
2300
+	}
2301
+    }
2302
+  return (state == 2);
2303
+}
2304
+
2305
+static void
2306
+man_output_peer_info_env (struct management *man, struct man_def_auth_context *mdac)
2307
+{
2308
+  char line[256];
2309
+  if (man->persist.callback.get_peer_info)
2310
+    {
2311
+      const char *peer_info = (*man->persist.callback.get_peer_info) (man->persist.callback.arg, mdac->cid);
2312
+      if (peer_info)
2313
+	{
2314
+	  struct buffer buf;
2315
+	  buf_set_read (&buf, (const uint8_t *) peer_info, strlen(peer_info));
2316
+	  while (buf_parse (&buf, '\n', line, sizeof (line)))
2317
+	    {
2318
+	      chomp (line);
2319
+	      if (validate_peer_info_line(line))
2320
+		{
2321
+		  msg (M_CLIENT, ">CLIENT:ENV,%s", line);
2322
+		}
2323
+	      else
2324
+		msg (D_MANAGEMENT, "validation failed on peer_info line received from client");
2325
+	    }
2326
+	}
2327
+    }
2328
+}
2329
+
2278 2330
 void
2279 2331
 management_notify_client_needing_auth (struct management *management,
2280 2332
 				       const unsigned int mda_key_id,
... ...
@@ -2288,6 +2340,7 @@ management_notify_client_needing_auth (struct management *management,
2288 2288
 	mode = "REAUTH";
2289 2289
       msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
2290 2290
       man_output_extra_env (management);
2291
+      man_output_peer_info_env(management, mdac);
2291 2292
       man_output_env (es, true, management->connection.env_filter_level);
2292 2293
       mdac->flags |= DAF_INITIAL_AUTH;
2293 2294
     }
... ...
@@ -164,6 +164,7 @@ struct management_callback
164 164
 		       const char *reason,
165 165
 		       const char *client_reason,
166 166
 		       struct buffer_list *cc_config); /* ownership transferred */
167
+  char *(*get_peer_info) (void *arg, const unsigned long cid);
167 168
 #endif
168 169
 #ifdef MANAGEMENT_PF
169 170
   bool (*client_pf) (void *arg,
... ...
@@ -2597,6 +2597,20 @@ management_client_auth (void *arg,
2597 2597
     buffer_list_free (cc_config);
2598 2598
   return ret;
2599 2599
 }
2600
+
2601
+static char *
2602
+management_get_peer_info (void *arg, const unsigned long cid)
2603
+{
2604
+  struct multi_context *m = (struct multi_context *) arg;
2605
+  struct multi_instance *mi = lookup_by_cid (m, cid);
2606
+  char *ret = NULL;
2607
+
2608
+  if (mi)
2609
+      ret = tls_get_peer_info (mi->context.c2.tls_multi);
2610
+
2611
+  return ret;
2612
+}
2613
+
2600 2614
 #endif
2601 2615
 
2602 2616
 #ifdef MANAGEMENT_PF
... ...
@@ -2637,6 +2651,7 @@ init_management_callback_multi (struct multi_context *m)
2637 2637
 #ifdef MANAGEMENT_DEF_AUTH
2638 2638
       cb.kill_by_cid = management_kill_by_cid;
2639 2639
       cb.client_auth = management_client_auth;
2640
+      cb.get_peer_info = management_get_peer_info;
2640 2641
 #endif
2641 2642
 #ifdef MANAGEMENT_PF
2642 2643
       cb.client_pf = management_client_pf;
... ...
@@ -196,6 +196,9 @@ static const char usage_message[] =
196 196
   "                  Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
197 197
   "--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
198 198
   "                  the default gateway.  Useful when pushing private subnets.\n"
199
+#ifdef ENABLE_PUSH_PEER_INFO
200
+  "--push-peer-info : (client only) push client info to server.\n"
201
+#endif
199 202
   "--setenv name value : Set a custom environmental variable to pass to script.\n"
200 203
   "--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
201 204
   "                  directives for future OpenVPN versions to be ignored.\n"
... ...
@@ -1348,6 +1351,9 @@ show_settings (const struct options *o)
1348 1348
   SHOW_INT (transition_window);
1349 1349
 
1350 1350
   SHOW_BOOL (single_session);
1351
+#ifdef ENABLE_PUSH_PEER_INFO
1352
+  SHOW_BOOL (push_peer_info);
1353
+#endif
1351 1354
   SHOW_BOOL (tls_exit);
1352 1355
 
1353 1356
   SHOW_STR (tls_auth_file);
... ...
@@ -2057,6 +2063,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2057 2057
       MUST_BE_UNDEF (transition_window);
2058 2058
       MUST_BE_UNDEF (tls_auth_file);
2059 2059
       MUST_BE_UNDEF (single_session);
2060
+#ifdef ENABLE_PUSH_PEER_INFO
2061
+      MUST_BE_UNDEF (push_peer_info);
2062
+#endif
2060 2063
       MUST_BE_UNDEF (tls_exit);
2061 2064
       MUST_BE_UNDEF (crl_file);
2062 2065
       MUST_BE_UNDEF (key_method);
... ...
@@ -5672,6 +5681,13 @@ add_option (struct options *options,
5672 5672
       VERIFY_PERMISSION (OPT_P_GENERAL);
5673 5673
       options->single_session = true;
5674 5674
     }
5675
+#ifdef ENABLE_PUSH_PEER_INFO
5676
+  else if (streq (p[0], "push-peer-info"))
5677
+    {
5678
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5679
+      options->push_peer_info = true;
5680
+    }
5681
+#endif
5675 5682
   else if (streq (p[0], "tls-exit"))
5676 5683
     {
5677 5684
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -520,6 +520,10 @@ struct options
520 520
   /* Allow only one session */
521 521
   bool single_session;
522 522
 
523
+#ifdef ENABLE_PUSH_PEER_INFO
524
+  bool push_peer_info;
525
+#endif
526
+
523 527
   bool tls_exit;
524 528
 
525 529
 #endif /* USE_SSL */
... ...
@@ -102,8 +102,8 @@ send_auth_failed (struct context *c, const char *client_reason)
102 102
   schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
103 103
 
104 104
   len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
105
-  if (len > TLS_CHANNEL_BUF_SIZE)
106
-    len = TLS_CHANNEL_BUF_SIZE;
105
+  if (len > PUSH_BUNDLE_SIZE)
106
+    len = PUSH_BUNDLE_SIZE;
107 107
 
108 108
   {
109 109
     struct buffer buf = alloc_buf_gc (len, &gc);
... ...
@@ -171,7 +171,7 @@ bool
171 171
 send_push_reply (struct context *c)
172 172
 {
173 173
   struct gc_arena gc = gc_new ();
174
-  struct buffer buf = alloc_buf_gc (TLS_CHANNEL_BUF_SIZE, &gc);
174
+  struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc);
175 175
   struct push_entry *e = c->options.push_list.head;
176 176
   bool multi_push = false;
177 177
   static char cmd[] = "PUSH_REPLY";
... ...
@@ -2186,7 +2186,7 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)  /* PLA
2186 2186
 
2187 2187
 #endif
2188 2188
 
2189
-#if AUTO_USERID
2189
+#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
2190 2190
 
2191 2191
 #if defined(TARGET_LINUX)
2192 2192
 
... ...
@@ -174,7 +174,7 @@ bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
174 174
 #define TLA_LOCAL           2
175 175
 int test_local_addr (const in_addr_t addr);
176 176
 
177
-#if AUTO_USERID
177
+#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
178 178
 bool get_default_gateway_mac_addr (unsigned char *macaddr);
179 179
 #endif
180 180
 
... ...
@@ -2558,6 +2558,8 @@ tls_multi_free (struct tls_multi *multi, bool clear)
2558 2558
 
2559 2559
 #ifdef MANAGEMENT_DEF_AUTH
2560 2560
   man_def_auth_set_client_reason(multi, NULL);  
2561
+
2562
+  free (multi->peer_info);
2561 2563
 #endif
2562 2564
 
2563 2565
   if (multi->locked_cn)
... ...
@@ -3106,6 +3108,14 @@ write_string (struct buffer *buf, const char *str, const int maxlen)
3106 3106
 }
3107 3107
 
3108 3108
 static bool
3109
+write_empty_string (struct buffer *buf)
3110
+{
3111
+  if (!buf_write_u16 (buf, 0))
3112
+    return false;
3113
+  return true;
3114
+}
3115
+
3116
+static bool
3109 3117
 read_string (struct buffer *buf, char *str, const unsigned int capacity)
3110 3118
 {
3111 3119
   const int len = buf_read_u16 (buf);
... ...
@@ -3117,6 +3127,33 @@ read_string (struct buffer *buf, char *str, const unsigned int capacity)
3117 3117
   return true;
3118 3118
 }
3119 3119
 
3120
+static char *
3121
+read_string_alloc (struct buffer *buf)
3122
+{
3123
+  const int len = buf_read_u16 (buf);
3124
+  char *str;
3125
+
3126
+  if (len < 1)
3127
+    return NULL;
3128
+  str = (char *) malloc(len);
3129
+  check_malloc_return(str);
3130
+  if (!buf_read (buf, str, len))
3131
+    {
3132
+      free (str);
3133
+      return NULL;
3134
+    }
3135
+  str[len-1] = '\0';
3136
+  return str;
3137
+}
3138
+
3139
+void
3140
+read_string_discard (struct buffer *buf)
3141
+{
3142
+  char *data = read_string_alloc(buf);
3143
+  if (data)
3144
+    free (data);
3145
+}
3146
+
3120 3147
 /*
3121 3148
  * Authenticate a client using username/password.
3122 3149
  * Runs on server.
... ...
@@ -3328,6 +3365,73 @@ key_method_1_write (struct buffer *buf, struct tls_session *session)
3328 3328
 }
3329 3329
 
3330 3330
 static bool
3331
+push_peer_info(struct buffer *buf, struct tls_session *session)
3332
+{
3333
+  struct gc_arena gc = gc_new ();
3334
+  bool ret = false;
3335
+
3336
+#ifdef ENABLE_PUSH_PEER_INFO
3337
+  if (session->opt->push_peer_info) /* write peer info */
3338
+    {
3339
+      struct env_set *es = session->opt->es;
3340
+      struct env_item *e;
3341
+      struct buffer out = alloc_buf_gc (512*3, &gc);
3342
+
3343
+      /* push version */
3344
+      buf_printf (&out, "IV_VER=%s\n", PACKAGE_VERSION);
3345
+
3346
+      /* push platform */
3347
+#if defined(TARGET_LINUX)
3348
+      buf_printf (&out, "IV_PLAT=linux\n");
3349
+#elif defined(TARGET_SOLARIS)
3350
+      buf_printf (&out, "IV_PLAT=solaris\n");
3351
+#elif defined(TARGET_OPENBSD)
3352
+      buf_printf (&out, "IV_PLAT=openbsd\n");
3353
+#elif defined(TARGET_DARWIN)
3354
+      buf_printf (&out, "IV_PLAT=mac\n");
3355
+#elif defined(TARGET_NETBSD)
3356
+      buf_printf (&out, "IV_PLAT=netbsd\n");
3357
+#elif defined(TARGET_FREEBSD)
3358
+      buf_printf (&out, "IV_PLAT=freebsd\n");
3359
+#elif defined(WIN32)
3360
+      buf_printf (&out, "IV_PLAT=win\n");
3361
+#endif
3362
+
3363
+      /* push mac addr */
3364
+      {
3365
+	bool get_default_gateway_mac_addr (unsigned char *macaddr);
3366
+	uint8_t macaddr[6];
3367
+	get_default_gateway_mac_addr (macaddr);
3368
+	buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
3369
+      }
3370
+
3371
+      /* push env vars that begin with UV_ */
3372
+      for (e=es->list; e != NULL; e=e->next)
3373
+	{
3374
+	  if (e->string)
3375
+	    {
3376
+	      if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1))
3377
+		buf_printf (&out, "%s\n", e->string);
3378
+	    }
3379
+	}
3380
+
3381
+      if (!write_string(buf, BSTR(&out), -1))
3382
+	goto error;
3383
+    }
3384
+  else
3385
+#endif
3386
+    {
3387
+      if (!write_empty_string (buf)) /* no peer info */
3388
+	goto error;
3389
+    }
3390
+  ret = true;
3391
+
3392
+ error:
3393
+  gc_free (&gc);
3394
+  return ret;
3395
+}
3396
+
3397
+static bool
3331 3398
 key_method_2_write (struct buffer *buf, struct tls_session *session)
3332 3399
 {
3333 3400
   ASSERT (session->opt->key_method == 2);
... ...
@@ -3361,6 +3465,16 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
3361 3361
 	goto error;
3362 3362
       purge_user_pass (&auth_user_pass, false);
3363 3363
     }
3364
+  else
3365
+    {
3366
+      if (!write_empty_string (buf)) /* no username */
3367
+	goto error;
3368
+      if (!write_empty_string (buf)) /* no password */
3369
+	goto error;
3370
+    }
3371
+
3372
+  if (!push_peer_info (buf, session))
3373
+    goto error;
3364 3374
 
3365 3375
   /*
3366 3376
    * generate tunnel keys if server
... ...
@@ -3507,11 +3621,13 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3507 3507
       int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS;
3508 3508
       bool s2 = true;
3509 3509
       char *raw_username;
3510
+      bool username_status, password_status;
3510 3511
 
3511 3512
       /* get username/password from plaintext buffer */
3512 3513
       ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc);
3513
-      if (!read_string (buf, up->username, USER_PASS_LEN)
3514
-	  || !read_string (buf, up->password, USER_PASS_LEN))
3514
+      username_status = read_string (buf, up->username, USER_PASS_LEN);
3515
+      password_status = read_string (buf, up->password, USER_PASS_LEN);
3516
+      if (!username_status || !password_status)
3515 3517
 	{
3516 3518
 	  CLEAR (*up);
3517 3519
 	  if (!(session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL))
... ...
@@ -3532,6 +3648,10 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3532 3532
 
3533 3533
       /* call plugin(s) and/or script */
3534 3534
 #ifdef MANAGEMENT_DEF_AUTH
3535
+      /* get peer info from control channel */
3536
+      free (multi->peer_info);
3537
+      multi->peer_info = read_string_alloc (buf);
3538
+
3535 3539
       if (man_def_auth == KMDA_DEF)
3536 3540
 	man_def_auth = verify_user_pass_management (session, up, raw_username);
3537 3541
 #endif
... ...
@@ -432,6 +432,9 @@ struct tls_options
432 432
 #ifdef ENABLE_OCC
433 433
   bool disable_occ;
434 434
 #endif
435
+#ifdef ENABLE_PUSH_PEER_INFO
436
+  bool push_peer_info;
437
+#endif
435 438
   int transition_window;
436 439
   int handshake_window;
437 440
   interval_t packet_timeout;
... ...
@@ -618,6 +621,12 @@ struct tls_multi
618 618
    */
619 619
   char *client_reason;
620 620
 
621
+  /*
622
+   * A multi-line string of general-purpose info received from peer
623
+   * over control channel.
624
+   */
625
+  char *peer_info;
626
+
621 627
   /* Time of last call to tls_authentication_status */
622 628
   time_t tas_last;
623 629
 #endif
... ...
@@ -721,6 +730,12 @@ void tls_deauthenticate (struct tls_multi *multi);
721 721
 
722 722
 #ifdef MANAGEMENT_DEF_AUTH
723 723
 bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason);
724
+
725
+static inline char *
726
+tls_get_peer_info(const struct tls_multi *multi)
727
+{
728
+  return multi->peer_info;
729
+}
724 730
 #endif
725 731
 
726 732
 /*
... ...
@@ -662,4 +662,9 @@ socket_defined (const socket_descriptor_t sd)
662 662
 #define AUTO_USERID 0
663 663
 #endif
664 664
 
665
+/*
666
+ * Do we support pushing peer info?
667
+ */
668
+#define ENABLE_PUSH_PEER_INFO
669
+
665 670
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1.1h])
2
+define(PRODUCT_VERSION,[2.1.1i])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])