Browse code

Updated version to 2.1_rc7e.

Added client authentication and packet filtering capability
to management interface.

Extended packet filtering capability to work on both --dev tun
and --dev tap tunnels.

Updated valgrind-suppress file.

Made "Linux ip addr del failed" error nonfatal.

Amplified --client-cert-not-required warning.

Added #pragma pack to proto.h.


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

james authored on 2008/06/11 17:45:09
Showing 30 changed files
... ...
@@ -112,7 +112,7 @@ openvpn_SOURCES = \
112 112
 	otime.c otime.h \
113 113
 	packet_id.c packet_id.h \
114 114
 	perf.c perf.h \
115
-	pf.c pf.h \
115
+	pf.c pf.h pf-inline.h \
116 116
 	ping.c ping.h ping-inline.h \
117 117
 	plugin.c plugin.h \
118 118
 	pool.c pool.h \
... ...
@@ -819,3 +819,130 @@ valign4 (const struct buffer *buf, const char *file, const int line)
819 819
     }
820 820
 }
821 821
 #endif
822
+
823
+/*
824
+ * struct buffer_list
825
+ */
826
+
827
+#ifdef ENABLE_BUFFER_LIST
828
+
829
+struct buffer_list *
830
+buffer_list_new (const int max_size)
831
+{
832
+  struct buffer_list *ret;
833
+  ALLOC_OBJ_CLEAR (ret, struct buffer_list);
834
+  ret->max_size = max_size;
835
+  ret->size = 0;
836
+  return ret;
837
+}
838
+
839
+void
840
+buffer_list_free (struct buffer_list *ol)
841
+{
842
+  buffer_list_reset (ol);
843
+  free (ol);
844
+}
845
+
846
+bool
847
+buffer_list_defined (const struct buffer_list *ol)
848
+{
849
+  return ol->head != NULL;
850
+}
851
+
852
+void
853
+buffer_list_reset (struct buffer_list *ol)
854
+{
855
+  struct buffer_entry *e = ol->head;
856
+  while (e)
857
+    {
858
+      struct buffer_entry *next = e->next;
859
+      free_buf (&e->buf);
860
+      free (e);
861
+      e = next;
862
+    }
863
+  ol->head = ol->tail = NULL;
864
+  ol->size = 0;
865
+}
866
+
867
+void
868
+buffer_list_push (struct buffer_list *ol, const unsigned char *str)
869
+{
870
+  if (!ol->max_size || ol->size < ol->max_size)
871
+    {
872
+      struct buffer_entry *e;
873
+      ALLOC_OBJ_CLEAR (e, struct buffer_entry);
874
+
875
+      ++ol->size;
876
+      if (ol->tail)
877
+	{
878
+	  ASSERT (ol->head);
879
+	  ol->tail->next = e;
880
+	}
881
+      else
882
+	{
883
+	  ASSERT (!ol->head);
884
+	  ol->head = e;
885
+	}
886
+      e->buf = string_alloc_buf ((const char *) str, NULL);
887
+      ol->tail = e;
888
+    }
889
+}
890
+
891
+const struct buffer *
892
+buffer_list_peek (struct buffer_list *ol)
893
+{
894
+  if (ol->head)
895
+    return &ol->head->buf;
896
+  else
897
+    return NULL;
898
+}
899
+
900
+static void
901
+buffer_list_pop (struct buffer_list *ol)
902
+{
903
+  if (ol->head)
904
+    {
905
+      struct buffer_entry *e = ol->head->next;
906
+      free_buf (&ol->head->buf);
907
+      free (ol->head);
908
+      ol->head = e;
909
+      --ol->size;
910
+      if (!e)
911
+	ol->tail = NULL;
912
+    }
913
+}
914
+
915
+void
916
+buffer_list_advance (struct buffer_list *ol, int n)
917
+{
918
+  if (ol->head)
919
+    {
920
+      struct buffer *buf = &ol->head->buf;
921
+      ASSERT (buf_advance (buf, n));
922
+      if (!BLEN (buf))
923
+	buffer_list_pop (ol);
924
+    }
925
+}
926
+
927
+struct buffer_list *
928
+buffer_list_file (const char *fn, int max_line_len)
929
+{
930
+  FILE *fp = fopen (fn, "r");
931
+  struct buffer_list *bl = NULL;
932
+
933
+  if (fp)
934
+    {
935
+      char *line = (char *) malloc (max_line_len);
936
+      if (line)
937
+	{
938
+	  bl = buffer_list_new (0);
939
+	  while (fgets (line, max_line_len, fp) != NULL)
940
+	    buffer_list_push (bl, (unsigned char *)line);
941
+	  free (line);
942
+	}
943
+      fclose (fp);
944
+    }
945
+  return bl;
946
+}
947
+
948
+#endif
... ...
@@ -723,4 +723,38 @@ check_malloc_return (void *p)
723 723
     out_of_memory ();
724 724
 }
725 725
 
726
+/*
727
+ * Manage lists of buffers
728
+ */
729
+
730
+#ifdef ENABLE_BUFFER_LIST
731
+
732
+struct buffer_entry
733
+{
734
+  struct buffer buf;
735
+  struct buffer_entry *next;
736
+};
737
+
738
+struct buffer_list
739
+{
740
+  struct buffer_entry *head; /* next item to pop/peek */
741
+  struct buffer_entry *tail; /* last item pushed */
742
+  int size;                  /* current number of entries */
743
+  int max_size;              /* maximum size list should grow to */
744
+};
745
+
746
+struct buffer_list *buffer_list_new (const int max_size);
747
+void buffer_list_free (struct buffer_list *ol);
748
+
749
+bool buffer_list_defined (const struct buffer_list *ol);
750
+void buffer_list_reset (struct buffer_list *ol);
751
+
752
+void buffer_list_push (struct buffer_list *ol, const unsigned char *str);
753
+const struct buffer *buffer_list_peek (struct buffer_list *ol);
754
+void buffer_list_advance (struct buffer_list *ol, int n);
755
+
756
+struct buffer_list *buffer_list_file (const char *fn, int max_line_len);
757
+
758
+#endif
759
+
726 760
 #endif /* BUFFER_H */
... ...
@@ -1,118 +1,411 @@
1
-# Valgrind suppressions file for OpenVPN.
2
-#
3
-# Mostly deal with uninitialized data warnings
4
-# in OpenSSL.
1
+{
2
+   <insert a suppression name here>
3
+   Memcheck:Addr8
4
+   obj:/lib/ld-2.5.so
5
+   obj:/lib/ld-2.5.so
6
+   obj:/lib/ld-2.5.so
7
+   obj:/lib/ld-2.5.so
8
+   obj:/lib/ld-2.5.so
9
+   obj:/lib/ld-2.5.so
10
+   obj:/lib/ld-2.5.so
11
+   obj:/lib/ld-2.5.so
12
+   obj:/lib/ld-2.5.so
13
+   obj:/lib/ld-2.5.so
14
+   obj:/lib/libc-2.5.so
15
+   obj:/lib/ld-2.5.so
16
+   fun:__libc_dlopen_mode
17
+   fun:__nss_lookup_function
18
+   obj:/lib/libc-2.5.so
19
+   fun:getgrnam_r
20
+   fun:getgrnam
21
+   fun:get_group
22
+   fun:do_init_first_time
23
+   fun:init_instance
24
+   fun:init_instance_handle_signals
25
+   fun:tunnel_server_tcp
26
+   fun:main
27
+}
5 28
 
6 29
 {
7
-   cond_BN
8
-   Memcheck:Cond
9
-   fun:BN_*
30
+   <insert a suppression name here>
31
+   Memcheck:Addr8
32
+   obj:/lib/ld-2.5.so
33
+   obj:/lib/ld-2.5.so
34
+   obj:/lib/ld-2.5.so
35
+   obj:/lib/ld-2.5.so
36
+   obj:/lib/ld-2.5.so
37
+   obj:/lib/ld-2.5.so
38
+   obj:/lib/ld-2.5.so
39
+   obj:/lib/libc-2.5.so
40
+   obj:/lib/ld-2.5.so
41
+   fun:__libc_dlopen_mode
42
+   fun:__nss_lookup_function
43
+   fun:__nss_next
44
+   fun:gethostbyname_r
45
+   fun:gethostbyname
46
+   fun:getaddr
47
+   fun:resolve_remote
48
+   fun:link_socket_init_phase1
49
+   fun:init_instance
50
+   fun:init_instance_handle_signals
51
+   fun:main
10 52
 }
11 53
 
12 54
 {
13
-   value4_BN
14
-   Memcheck:Value4
15
-   fun:BN_*
55
+   <insert a suppression name here>
56
+   Memcheck:Addr8
57
+   obj:/lib/ld-2.5.so
58
+   obj:/lib/ld-2.5.so
59
+   obj:/lib/ld-2.5.so
60
+   obj:/lib/ld-2.5.so
61
+   obj:/lib/ld-2.5.so
62
+   obj:/lib/ld-2.5.so
63
+   obj:/lib/ld-2.5.so
64
+   obj:/lib/libc-2.5.so
65
+   obj:/lib/ld-2.5.so
66
+   fun:__libc_dlopen_mode
67
+   fun:__nss_lookup_function
68
+   obj:/lib/libc-2.5.so
69
+   fun:gethostbyname_r
70
+   fun:gethostbyname
71
+   fun:getaddr
72
+   fun:resolve_remote
73
+   fun:link_socket_init_phase1
74
+   fun:init_instance
75
+   fun:init_instance_handle_signals
76
+   fun:main
16 77
 }
17 78
 
18 79
 {
19
-   cond_bn
20
-   Memcheck:Cond
21
-   fun:bn_*
80
+   <insert a suppression name here>
81
+   Memcheck:Addr8
82
+   obj:/lib/ld-2.5.so
83
+   obj:/lib/ld-2.5.so
84
+   obj:/lib/ld-2.5.so
85
+   obj:/lib/ld-2.5.so
86
+   obj:/lib/ld-2.5.so
87
+   obj:/lib/ld-2.5.so
88
+   obj:/lib/ld-2.5.so
89
+   obj:/lib/libdl-2.5.so
90
+   obj:/lib/ld-2.5.so
91
+   obj:/lib/libdl-2.5.so
92
+   fun:dlopen
93
+   fun:plugin_list_init
94
+   fun:init_plugins
95
+   fun:main
22 96
 }
23 97
 
24 98
 {
25
-   value4_bn
26
-   Memcheck:Value4
27
-   fun:bn_*
99
+   <insert a suppression name here>
100
+   Memcheck:Addr8
101
+   obj:/lib/ld-2.5.so
102
+   obj:/lib/ld-2.5.so
103
+   obj:/lib/ld-2.5.so
104
+   obj:/lib/ld-2.5.so
105
+   obj:/lib/ld-2.5.so
106
+   obj:/lib/ld-2.5.so
107
+   obj:/lib/libdl-2.5.so
108
+   obj:/lib/ld-2.5.so
109
+   obj:/lib/libdl-2.5.so
110
+   fun:dlopen
111
+   fun:plugin_list_init
112
+   fun:init_plugins
113
+   fun:main
28 114
 }
29 115
 
30 116
 {
31
-   cond_SHA1_Update
32
-   Memcheck:Cond
33
-   fun:SHA1_Update
117
+   <insert a suppression name here>
118
+   Memcheck:Addr8
119
+   obj:/lib/ld-2.5.so
120
+   obj:/lib/ld-2.5.so
121
+   obj:/lib/ld-2.5.so
122
+   obj:/lib/ld-2.5.so
123
+   obj:/lib/libc-2.5.so
124
+   obj:/lib/libdl-2.5.so
125
+   obj:/lib/ld-2.5.so
126
+   obj:/lib/libdl-2.5.so
127
+   fun:dlsym
128
+   fun:libdl_resolve_symbol
129
+   fun:plugin_list_init
130
+   fun:init_plugins
131
+   fun:main
34 132
 }
35 133
 
36 134
 {
37
-   value4_SHA1_Update
38
-   Memcheck:Value4
39
-   fun:SHA1_Update
135
+   <insert a suppression name here>
136
+   Memcheck:Addr8
137
+   obj:/lib/ld-2.5.so
138
+   obj:/lib/ld-2.5.so
139
+   obj:/lib/ld-2.5.so
140
+   obj:/lib/ld-2.5.so
141
+   obj:/lib/libdl-2.5.so
142
+   obj:/lib/ld-2.5.so
143
+   obj:/lib/libdl-2.5.so
144
+   fun:dlopen
145
+   fun:plugin_list_init
146
+   fun:init_plugins
147
+   fun:main
40 148
 }
41 149
 
42 150
 {
43
-   cond_ssl3_read_bytes
151
+   <insert a suppression name here>
44 152
    Memcheck:Cond
45
-   fun:ssl3_read_bytes
153
+   obj:/lib/ld-2.5.so
154
+   obj:/lib/ld-2.5.so
155
+   obj:/lib/ld-2.5.so
156
+   obj:/lib/ld-2.5.so
157
+   obj:/lib/ld-2.5.so
158
+   obj:*
159
+   obj:*
160
+   obj:*
46 161
 }
47 162
 
48 163
 {
49
-   cond_crypto
164
+   <insert a suppression name here>
50 165
    Memcheck:Cond
51
-   obj:/lib/libcrypto.so.*
166
+   obj:/lib/ld-2.5.so
167
+   obj:/lib/ld-2.5.so
168
+   obj:/lib/ld-2.5.so
169
+   obj:/lib/ld-2.5.so
170
+   obj:/lib/ld-2.5.so
171
+   obj:/lib/ld-2.5.so
172
+   obj:/lib/ld-2.5.so
173
+   obj:/lib/libc-2.5.so
174
+   obj:/lib/ld-2.5.so
175
+   fun:__libc_dlopen_mode
176
+   fun:__nss_lookup_function
177
+   fun:__nss_next
178
+   fun:gethostbyname_r
179
+   fun:gethostbyname
180
+   fun:getaddr
181
+   fun:resolve_remote
182
+   fun:link_socket_init_phase1
183
+   fun:init_instance
184
+   fun:init_instance_handle_signals
185
+   fun:main
52 186
 }
53 187
 
54 188
 {
55
-   value4_crypto
56
-   Memcheck:Value4
57
-   obj:/lib/libcrypto.so.*
189
+   <insert a suppression name here>
190
+   Memcheck:Cond
191
+   obj:/lib/ld-2.5.so
192
+   obj:/lib/ld-2.5.so
193
+   obj:/lib/ld-2.5.so
194
+   obj:/lib/ld-2.5.so
195
+   obj:/lib/ld-2.5.so
196
+   obj:/lib/ld-2.5.so
197
+   obj:/lib/ld-2.5.so
198
+   obj:/lib/libc-2.5.so
199
+   obj:/lib/ld-2.5.so
200
+   fun:__libc_dlopen_mode
201
+   fun:__nss_lookup_function
202
+   obj:/lib/libc-2.5.so
203
+   fun:getgrnam_r
204
+   fun:getgrnam
205
+   fun:get_group
206
+   fun:do_init_first_time
207
+   fun:init_instance
208
+   fun:init_instance_handle_signals
209
+   fun:tunnel_server_tcp
210
+   fun:main
58 211
 }
59 212
 
60 213
 {
61
-   cond_ssl
214
+   <insert a suppression name here>
62 215
    Memcheck:Cond
63
-   obj:/lib/libssl.so.*
216
+   obj:/lib/ld-2.5.so
217
+   obj:/lib/ld-2.5.so
218
+   obj:/lib/ld-2.5.so
219
+   obj:/lib/ld-2.5.so
220
+   obj:/lib/ld-2.5.so
221
+   obj:/lib/ld-2.5.so
222
+   obj:/lib/ld-2.5.so
223
+   obj:/lib/libc-2.5.so
224
+   obj:/lib/ld-2.5.so
225
+   fun:__libc_dlopen_mode
226
+   fun:__nss_lookup_function
227
+   obj:/lib/libc-2.5.so
228
+   fun:gethostbyname_r
229
+   fun:gethostbyname
230
+   fun:getaddr
231
+   fun:resolve_remote
232
+   fun:link_socket_init_phase1
233
+   fun:init_instance
234
+   fun:init_instance_handle_signals
235
+   fun:main
64 236
 }
65 237
 
66 238
 {
67
-   value4_ssl
68
-   Memcheck:Value4
69
-   obj:/lib/libssl.so.*
239
+   <insert a suppression name here>
240
+   Memcheck:Cond
241
+   obj:/lib/ld-2.5.so
242
+   obj:/lib/ld-2.5.so
243
+   obj:/lib/ld-2.5.so
244
+   obj:/lib/ld-2.5.so
245
+   obj:/lib/ld-2.5.so
246
+   obj:/lib/libc-2.5.so
247
+   obj:/lib/ld-2.5.so
248
+   fun:__libc_dlopen_mode
249
+   fun:__nss_lookup_function
250
+   fun:__nss_next
251
+   fun:gethostbyname_r
252
+   fun:gethostbyname
253
+   fun:getaddr
254
+   fun:resolve_remote
255
+   fun:link_socket_init_phase1
256
+   fun:init_instance
257
+   fun:init_instance_handle_signals
258
+   fun:main
70 259
 }
71 260
 
72 261
 {
73
-   addr4_AES_cbc_encrypt
74
-   Memcheck:Addr4
75
-   fun:AES_cbc_encrypt
262
+   <insert a suppression name here>
263
+   Memcheck:Cond
264
+   obj:/lib/ld-2.5.so
265
+   obj:/lib/ld-2.5.so
266
+   obj:/lib/ld-2.5.so
267
+   obj:/lib/ld-2.5.so
268
+   obj:/lib/ld-2.5.so
269
+   obj:/lib/libc-2.5.so
270
+   obj:/lib/ld-2.5.so
271
+   fun:__libc_dlopen_mode
272
+   fun:__nss_lookup_function
273
+   obj:/lib/libc-2.5.so
274
+   fun:getgrnam_r
275
+   fun:getgrnam
276
+   fun:get_group
277
+   fun:do_init_first_time
278
+   fun:init_instance
279
+   fun:init_instance_handle_signals
280
+   fun:tunnel_server_tcp
281
+   fun:main
76 282
 }
77 283
 
78 284
 {
79
-   cond_memcpy_ssl3_read_bytes
285
+   <insert a suppression name here>
80 286
    Memcheck:Cond
81
-   fun:memcpy
82
-   fun:ssl3_read_bytes
287
+   obj:/lib/ld-2.5.so
288
+   obj:/lib/ld-2.5.so
289
+   obj:/lib/ld-2.5.so
290
+   obj:/lib/ld-2.5.so
291
+   obj:/lib/ld-2.5.so
292
+   obj:/lib/libc-2.5.so
293
+   obj:/lib/ld-2.5.so
294
+   fun:__libc_dlopen_mode
295
+   fun:__nss_lookup_function
296
+   obj:/lib/libc-2.5.so
297
+   fun:gethostbyname_r
298
+   fun:gethostbyname
299
+   fun:getaddr
300
+   fun:resolve_remote
301
+   fun:link_socket_init_phase1
302
+   fun:init_instance
303
+   fun:init_instance_handle_signals
304
+   fun:main
83 305
 }
84 306
 
85 307
 {
86
-   value4_memcpy_ssl3_read_bytes
87
-   Memcheck:Value4
88
-   fun:memcpy
89
-   fun:ssl3_read_bytes
308
+   <insert a suppression name here>
309
+   Memcheck:Cond
310
+   obj:/lib/ld-2.5.so
311
+   obj:/lib/ld-2.5.so
312
+   obj:/lib/ld-2.5.so
313
+   obj:/lib/ld-2.5.so
314
+   obj:/lib/libc-2.5.so
315
+   obj:/lib/ld-2.5.so
316
+   fun:__libc_dlopen_mode
317
+   fun:__nss_lookup_function
318
+   fun:__nss_next
319
+   fun:gethostbyname_r
320
+   fun:gethostbyname
321
+   fun:getaddr
322
+   fun:resolve_remote
323
+   fun:link_socket_init_phase1
324
+   fun:init_instance
325
+   fun:init_instance_handle_signals
326
+   fun:main
90 327
 }
91 328
 
92 329
 {
93
-   cond_memset_BUF_MEM_grow_clean
330
+   <insert a suppression name here>
94 331
    Memcheck:Cond
95
-   fun:memset
96
-   fun:BUF_MEM_grow_clean
332
+   obj:/lib/ld-2.5.so
333
+   obj:/lib/ld-2.5.so
334
+   obj:/lib/ld-2.5.so
335
+   obj:/lib/ld-2.5.so
336
+   obj:/lib/libc-2.5.so
337
+   obj:/lib/ld-2.5.so
338
+   fun:__libc_dlopen_mode
339
+   fun:__nss_lookup_function
340
+   obj:/lib/libc-2.5.so
341
+   fun:getgrnam_r
342
+   fun:getgrnam
343
+   fun:get_group
344
+   fun:do_init_first_time
345
+   fun:init_instance
346
+   fun:init_instance_handle_signals
347
+   fun:tunnel_server_tcp
348
+   fun:main
97 349
 }
98 350
 
99 351
 {
100
-   value4_memset_BUF_MEM_grow_clean
101
-   Memcheck:Value4
102
-   fun:memset
103
-   fun:BUF_MEM_grow_clean
352
+   <insert a suppression name here>
353
+   Memcheck:Cond
354
+   obj:/lib/ld-2.5.so
355
+   obj:/lib/ld-2.5.so
356
+   obj:/lib/ld-2.5.so
357
+   obj:/lib/ld-2.5.so
358
+   obj:/lib/libc-2.5.so
359
+   obj:/lib/ld-2.5.so
360
+   fun:__libc_dlopen_mode
361
+   fun:__nss_lookup_function
362
+   obj:/lib/libc-2.5.so
363
+   fun:getgrnam_r
364
+   fun:getgrnam
365
+   fun:get_group
366
+   fun:do_init_first_time
367
+   fun:init_instance
368
+   fun:init_instance_handle_signals
369
+   fun:tunnel_server_udp
370
+   fun:main
104 371
 }
105 372
 
106 373
 {
107 374
    <insert a suppression name here>
108
-   Memcheck:Addr8
375
+   Memcheck:Cond
376
+   obj:/lib/ld-2.5.so
109 377
    obj:/lib/ld-2.5.so
378
+   obj:/lib/ld-2.5.so
379
+   obj:/lib/ld-2.5.so
380
+   obj:/lib/libc-2.5.so
381
+   obj:/lib/ld-2.5.so
382
+   fun:__libc_dlopen_mode
383
+   fun:__nss_lookup_function
384
+   obj:/lib/libc-2.5.so
385
+   fun:gethostbyname_r
386
+   fun:gethostbyname
387
+   fun:getaddr
388
+   fun:resolve_remote
389
+   fun:link_socket_init_phase1
390
+   fun:init_instance
391
+   fun:init_instance_handle_signals
392
+   fun:main
110 393
 }
111 394
 
112 395
 {
113 396
    <insert a suppression name here>
114 397
    Memcheck:Cond
115 398
    obj:/lib/ld-2.5.so
399
+   obj:/lib/ld-2.5.so
400
+   obj:/lib/ld-2.5.so
401
+   obj:/lib/ld-2.5.so
402
+   obj:/lib/libdl-2.5.so
403
+   obj:/lib/ld-2.5.so
404
+   obj:/lib/libdl-2.5.so
405
+   fun:dlopen
406
+   fun:plugin_list_init
407
+   fun:init_plugins
408
+   fun:main
116 409
 }
117 410
 
118 411
 {
... ...
@@ -128,3 +421,172 @@
128 128
    fun:init_static
129 129
    fun:main
130 130
 }
131
+
132
+{
133
+   <insert a suppression name here>
134
+   Memcheck:Leak
135
+   fun:malloc
136
+   fun:__nss_lookup_function
137
+   obj:*
138
+   obj:*
139
+   fun:getgrnam_r
140
+   fun:getgrnam
141
+   fun:get_group
142
+   fun:do_init_first_time
143
+   fun:init_instance
144
+   fun:init_instance_handle_signals
145
+   fun:main
146
+}
147
+
148
+{
149
+   <insert a suppression name here>
150
+   Memcheck:Leak
151
+   fun:malloc
152
+   fun:__nss_lookup_function
153
+   obj:*
154
+   obj:*
155
+   fun:getgrnam_r
156
+   fun:getgrnam
157
+   fun:get_group
158
+   fun:do_init_first_time
159
+   fun:init_instance
160
+   fun:init_instance_handle_signals
161
+   fun:tunnel_server_tcp
162
+   fun:main
163
+}
164
+
165
+{
166
+   <insert a suppression name here>
167
+   Memcheck:Leak
168
+   fun:malloc
169
+   fun:__nss_lookup_function
170
+   obj:*
171
+   obj:*
172
+   fun:getgrnam_r
173
+   fun:getgrnam
174
+   fun:get_group
175
+   fun:do_init_first_time
176
+   fun:init_instance
177
+   fun:init_instance_handle_signals
178
+   fun:tunnel_server_udp
179
+   fun:main
180
+}
181
+
182
+{
183
+   <insert a suppression name here>
184
+   Memcheck:Leak
185
+   fun:malloc
186
+   fun:getdelim
187
+   fun:getpass
188
+   fun:get_console_input
189
+   fun:get_user_pass
190
+   fun:context_init_1
191
+   fun:main
192
+}
193
+
194
+{
195
+   <insert a suppression name here>
196
+   Memcheck:Leak
197
+   fun:malloc
198
+   fun:tsearch
199
+   fun:__nss_lookup_function
200
+   obj:*
201
+   obj:*
202
+   fun:getgrnam_r
203
+   fun:getgrnam
204
+   fun:get_group
205
+   fun:do_init_first_time
206
+   fun:init_instance
207
+   fun:init_instance_handle_signals
208
+   fun:main
209
+}
210
+
211
+{
212
+   <insert a suppression name here>
213
+   Memcheck:Leak
214
+   fun:malloc
215
+   fun:tsearch
216
+   fun:__nss_lookup_function
217
+   obj:*
218
+   obj:*
219
+   fun:getgrnam_r
220
+   fun:getgrnam
221
+   fun:get_group
222
+   fun:do_init_first_time
223
+   fun:init_instance
224
+   fun:init_instance_handle_signals
225
+   fun:tunnel_server_tcp
226
+   fun:main
227
+}
228
+
229
+{
230
+   <insert a suppression name here>
231
+   Memcheck:Leak
232
+   fun:malloc
233
+   fun:tsearch
234
+   fun:__nss_lookup_function
235
+   obj:*
236
+   obj:*
237
+   fun:getgrnam_r
238
+   fun:getgrnam
239
+   fun:get_group
240
+   fun:do_init_first_time
241
+   fun:init_instance
242
+   fun:init_instance_handle_signals
243
+   fun:tunnel_server_udp
244
+   fun:main
245
+}
246
+
247
+{
248
+   <insert a suppression name here>
249
+   Memcheck:Leak
250
+   fun:malloc
251
+   obj:/lib/libc-2.5.so
252
+   fun:__nss_database_lookup
253
+   obj:*
254
+   obj:*
255
+   fun:getgrnam_r
256
+   fun:getgrnam
257
+   fun:get_group
258
+   fun:do_init_first_time
259
+   fun:init_instance
260
+   fun:init_instance_handle_signals
261
+   fun:main
262
+}
263
+
264
+{
265
+   <insert a suppression name here>
266
+   Memcheck:Leak
267
+   fun:malloc
268
+   obj:/lib/libc-2.5.so
269
+   fun:__nss_database_lookup
270
+   obj:*
271
+   obj:*
272
+   fun:getgrnam_r
273
+   fun:getgrnam
274
+   fun:get_group
275
+   fun:do_init_first_time
276
+   fun:init_instance
277
+   fun:init_instance_handle_signals
278
+   fun:tunnel_server_tcp
279
+   fun:main
280
+}
281
+
282
+{
283
+   <insert a suppression name here>
284
+   Memcheck:Leak
285
+   fun:malloc
286
+   obj:/lib/libc-2.5.so
287
+   fun:__nss_database_lookup
288
+   obj:*
289
+   obj:*
290
+   fun:getgrnam_r
291
+   fun:getgrnam
292
+   fun:get_group
293
+   fun:do_init_first_time
294
+   fun:init_instance
295
+   fun:init_instance_handle_signals
296
+   fun:tunnel_server_udp
297
+   fun:main
298
+}
299
+
131 300
new file mode 100755
... ...
@@ -0,0 +1,2 @@
0
+#!/bin/bash
1
+valgrind --tool=memcheck --error-limit=no --gen-suppressions=all --leak-check=full --show-reachable=yes --num-callers=32 $*
... ...
@@ -94,7 +94,7 @@
94 94
 #define D_ROUTE_QUOTA        LOGLEV(3, 43, 0)        /* show route quota exceeded messages */
95 95
 #define D_OSBUF              LOGLEV(3, 44, 0)        /* show socket/tun/tap buffer sizes */
96 96
 #define D_PS_PROXY           LOGLEV(3, 45, 0)        /* messages related to --port-share option */
97
-#define D_PF                 LOGLEV(3, 46, 0)        /* messages related to packet filter */
97
+#define D_PF_INFO            LOGLEV(3, 46, 0)        /* packet filter informational messages */
98 98
 
99 99
 #define D_SHOW_PARMS         LOGLEV(4, 50, 0)        /* show all parameters on program initiation */
100 100
 #define D_SHOW_OCC           LOGLEV(4, 51, 0)        /* show options compatibility string */
... ...
@@ -102,6 +102,7 @@
102 102
 #define D_DHCP_OPT           LOGLEV(4, 53, 0)        /* show DHCP options binary string */
103 103
 #define D_MBUF               LOGLEV(4, 54, 0)        /* mbuf.[ch] routines */
104 104
 #define D_PACKET_TRUNC_ERR   LOGLEV(4, 55, 0)        /* PACKET_TRUNCATION_CHECK */
105
+#define D_PF_DROPPED         LOGLEV(4, 56, 0)        /* packet filter dropped a packet */
105 106
 
106 107
 #define D_LOG_RW             LOGLEV(5, 0,  0)        /* Print 'R' or 'W' to stdout for read/write */
107 108
 
... ...
@@ -136,6 +137,8 @@
136 136
 #define D_PING               LOGLEV(7, 70, M_DEBUG)  /* PING send/receive messages */
137 137
 #define D_PS_PROXY_DEBUG     LOGLEV(7, 70, M_DEBUG)  /* port share proxy debug */
138 138
 #define D_AUTO_USERID        LOGLEV(7, 70, M_DEBUG)  /* AUTO_USERID debugging */
139
+#define D_PF_DROPPED_BCAST   LOGLEV(7, 71, M_DEBUG)  /* packet filter dropped a broadcast packet */
140
+#define D_PF_DEBUG           LOGLEV(7, 72, M_DEBUG)  /* packet filter debugging, must also define PF_DEBUG in pf.h */
139 141
 
140 142
 #define D_HANDSHAKE_VERBOSE  LOGLEV(8, 70, M_DEBUG)  /* show detailed description of each handshake */
141 143
 #define D_TLS_DEBUG_MED      LOGLEV(8, 70, M_DEBUG)  /* limited info from tls_session routines */
... ...
@@ -268,7 +268,10 @@ void x_msg (const unsigned int flags, const char *format, ...)
268 268
 #endif
269 269
 
270 270
   /* set up client prefix */
271
-  prefix = msg_get_prefix ();
271
+  if (flags & M_NOIPREFIX)
272
+    prefix = NULL;
273
+  else
274
+    prefix = msg_get_prefix ();
272 275
   prefix_sep = " ";
273 276
   if (!prefix)
274 277
     prefix_sep = prefix = "";
... ...
@@ -102,13 +102,14 @@ extern int x_msg_line_num;
102 102
 #define M_MSG_VIRT_OUT    (1<<14)        /* output message through msg_status_output callback */
103 103
 #define M_OPTERR          (1<<15)        /* print "Options error:" prefix */
104 104
 #define M_NOLF            (1<<16)        /* don't print new line */
105
+#define M_NOIPREFIX       (1<<17)        /* don't print instance prefix */
105 106
 
106 107
 /* flag combinations which are frequently used */
107 108
 #define M_ERR     (M_FATAL | M_ERRNO)
108 109
 #define M_SOCKERR (M_FATAL | M_ERRNO_SOCK)
109 110
 #define M_SSLERR  (M_FATAL | M_SSL)
110 111
 #define M_USAGE   (M_USAGE_SMALL | M_NOPREFIX | M_OPTERR)
111
-#define M_CLIENT  (M_MSG_VIRT_OUT|M_NOMUTE)
112
+#define M_CLIENT  (M_MSG_VIRT_OUT | M_NOMUTE | M_NOIPREFIX)
112 113
 
113 114
 /*
114 115
  * Mute levels are designed to avoid large numbers of
... ...
@@ -126,6 +127,11 @@ extern int x_msg_line_num;
126 126
  * log_level:  verbosity level n (--verb n) must be >= log_level to print.
127 127
  * mute_level: don't print more than n (--mute n) consecutive messages at
128 128
  *             a given mute level, or if 0 disable muting and print everything.
129
+ *
130
+ * Mask map:
131
+ * Bits 0-3:   log level
132
+ * Bits 4-23:  M_x flags
133
+ * Bits 24-31: mute level
129 134
  */
130 135
 #define LOGLEV(log_level, mute_level, other) ((log_level) | ENCODE_MUTE_LEVEL(mute_level) | other)
131 136
 
... ...
@@ -492,7 +492,7 @@ process_coarse_timers (struct context *c)
492 492
   check_push_request (c);
493 493
 #endif
494 494
 
495
-#ifdef ENABLE_PF
495
+#ifdef PLUGIN_PF
496 496
   pf_check_reload (c);
497 497
 #endif
498 498
 
... ...
@@ -1558,6 +1558,10 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
1558 1558
 
1559 1559
   to.plugins = c->plugins;
1560 1560
 
1561
+#ifdef MANAGEMENT_DEF_AUTH
1562
+  to.mda_context = &c->c2.mda_context;
1563
+#endif
1564
+
1561 1565
 #if P2MP_SERVER
1562 1566
   to.auth_user_pass_verify_script = options->auth_user_pass_verify_script;
1563 1567
   to.auth_user_pass_verify_script_via_file = options->auth_user_pass_verify_script_via_file;
... ...
@@ -2356,7 +2360,7 @@ open_plugins (struct context *c, const bool import_options, int init_point)
2356 2356
 		{
2357 2357
 		  unsigned int option_types_found = 0;
2358 2358
 		  if (config.list[i] && config.list[i]->value)
2359
-		    options_plugin_import (&c->options,
2359
+		    options_string_import (&c->options,
2360 2360
 					   config.list[i]->value,
2361 2361
 					   D_IMPORT_ERRORS|M_OPTERR,
2362 2362
 					   OPT_P_DEFAULT & ~OPT_P_PLUGIN,
... ...
@@ -2452,21 +2456,19 @@ open_management (struct context *c)
2452 2452
     {
2453 2453
       if (c->options.management_addr)
2454 2454
 	{
2455
+	  unsigned int flags = c->options.management_flags;
2456
+	  if (c->options.mode == MODE_SERVER)
2457
+	    flags |= MF_SERVER;
2455 2458
 	  if (management_open (management,
2456 2459
 			       c->options.management_addr,
2457 2460
 			       c->options.management_port,
2458 2461
 			       c->options.management_user_pass,
2459
-			       c->options.mode == MODE_SERVER,
2460
-			       c->options.management_query_passwords,
2461 2462
 			       c->options.management_log_history_cache,
2462 2463
 			       c->options.management_echo_buffer_size,
2463 2464
 			       c->options.management_state_buffer_size,
2464
-			       c->options.management_hold,
2465
-			       c->options.management_signal,
2466
-			       c->options.management_forget_disconnect,
2467
-			       c->options.management_client,
2468 2465
 			       c->options.management_write_peer_info_file,
2469
-			       c->options.remap_sigusr1))
2466
+			       c->options.remap_sigusr1,
2467
+			       flags))
2470 2468
 	    {
2471 2469
 	      management_set_state (management,
2472 2470
 				    OPENVPN_STATE_CONNECTING,
... ...
@@ -2792,6 +2794,11 @@ close_instance (struct context *c)
2792 2792
 	/* close TUN/TAP device */
2793 2793
 	do_close_tun (c, false);
2794 2794
 
2795
+#ifdef MANAGEMENT_DEF_AUTH
2796
+	if (management)
2797
+	  management_notify_client_close (management, &c->c2.mda_context, NULL);
2798
+#endif
2799
+
2795 2800
 #ifdef ENABLE_PF
2796 2801
 	pf_destroy_context (&c->c2.pf);
2797 2802
 #endif
... ...
@@ -88,6 +88,15 @@ man_help ()
88 88
   msg (M_CLIENT, "pkcs11-id-count        : Get number of available PKCS#11 identities.");
89 89
   msg (M_CLIENT, "pkcs11-id-get index    : Get PKCS#11 identity at index.");
90 90
 #endif
91
+#ifdef MANAGEMENT_DEF_AUTH
92
+  msg (M_CLIENT, "client-auth CID KID    : Authenticate client-id/key-id CID/KID (MULTILINE)");
93
+  msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
94
+  msg (M_CLIENT, "client-deny CID KID R  : Deny auth client-id/key-id CID/KID with reason text R");
95
+  msg (M_CLIENT, "client-kill CID        : Kill client instance CID");
96
+#ifdef MANAGEMENT_PF
97
+  msg (M_CLIENT, "client-pf CID          : Define packet filter for client CID (MULTILINE)");
98
+#endif
99
+#endif
91 100
   msg (M_CLIENT, "signal s               : Send signal s to daemon,");
92 101
   msg (M_CLIENT, "                         s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
93 102
   msg (M_CLIENT, "state [on|off] [N|all] : Like log, but show state history.");
... ...
@@ -178,7 +187,7 @@ man_update_io_state (struct management *man)
178 178
 {
179 179
   if (socket_defined (man->connection.sd_cli))
180 180
     {
181
-      if (output_list_defined (man->connection.out))
181
+      if (buffer_list_defined (man->connection.out))
182 182
 	{
183 183
 	  man->connection.state = MS_CC_WAIT_WRITE;
184 184
 	}
... ...
@@ -195,7 +204,7 @@ man_output_list_push (struct management *man, const char *str)
195 195
   if (management_connected (man))
196 196
     {
197 197
       if (str)
198
-	output_list_push (man->connection.out, (const unsigned char *) str);
198
+	buffer_list_push (man->connection.out, (const unsigned char *) str);
199 199
       man_update_io_state (man);
200 200
       if (!man->persist.standalone_disabled)
201 201
 	{
... ...
@@ -672,12 +681,12 @@ man_hold (struct management *man, const char *cmd)
672 672
     {
673 673
       if (streq (cmd, "on"))
674 674
 	{
675
-	  man->settings.hold = true;
675
+	  man->settings.flags |= MF_HOLD;
676 676
 	  msg (M_CLIENT, "SUCCESS: hold flag set to ON");
677 677
 	}
678 678
       else if (streq (cmd, "off"))
679 679
 	{
680
-	  man->settings.hold = false;
680
+	  man->settings.flags &= ~MF_HOLD;
681 681
 	  msg (M_CLIENT, "SUCCESS: hold flag set to OFF");
682 682
 	}
683 683
       else if (streq (cmd, "release"))
... ...
@@ -691,9 +700,205 @@ man_hold (struct management *man, const char *cmd)
691 691
 	}
692 692
     }
693 693
   else
694
-    msg (M_CLIENT, "SUCCESS: hold=%d", (int) man->settings.hold);
694
+    msg (M_CLIENT, "SUCCESS: hold=%d", BOOL_CAST(man->settings.flags & MF_HOLD));
695
+}
696
+
697
+#ifdef MANAGEMENT_DEF_AUTH
698
+
699
+static bool
700
+parse_cid (const char *str, unsigned long *cid)
701
+{
702
+  if (sscanf (str, "%lu", cid) == 1)
703
+    return true;
704
+  else
705
+    {
706
+      msg (M_CLIENT, "ERROR: cannot parse CID");
707
+      return false;
708
+    }
709
+}
710
+
711
+static bool
712
+parse_kid (const char *str, unsigned int *kid)
713
+{
714
+  if (sscanf (str, "%u", kid) == 1)
715
+    return true;
716
+  else
717
+    {
718
+      msg (M_CLIENT, "ERROR: cannot parse KID");
719
+      return false;
720
+    }
721
+}
722
+
723
+static void
724
+in_extra_reset (struct man_connection *mc, const bool new)
725
+{
726
+  if (mc)
727
+    {
728
+      if (!new)
729
+	{
730
+	  mc->in_extra_cmd = IEC_UNDEF;
731
+	  mc->in_extra_cid = 0;
732
+	  mc->in_extra_kid = 0;
733
+	}
734
+      if (mc->in_extra)
735
+	{
736
+	  buffer_list_free (mc->in_extra);
737
+	  mc->in_extra = NULL;
738
+	}
739
+      if (new)
740
+	mc->in_extra = buffer_list_new (0);
741
+    }
742
+}
743
+
744
+static void
745
+in_extra_dispatch (struct management *man)
746
+{
747
+   switch (man->connection.in_extra_cmd)
748
+    {
749
+    case IEC_CLIENT_AUTH:
750
+       if (man->persist.callback.client_auth)
751
+	{
752
+	  const bool status = (*man->persist.callback.client_auth)
753
+	    (man->persist.callback.arg,
754
+	     man->connection.in_extra_cid,
755
+	     man->connection.in_extra_kid,
756
+	     true,
757
+	     NULL,
758
+	     man->connection.in_extra);
759
+	  man->connection.in_extra = NULL;
760
+	  if (status)
761
+	    {
762
+	      msg (M_CLIENT, "SUCCESS: client-auth command succeeded");
763
+	    }
764
+	  else
765
+	    {
766
+	      msg (M_CLIENT, "ERROR: client-auth command failed");
767
+	    }
768
+	}
769
+      else
770
+	{
771
+	  msg (M_CLIENT, "ERROR: The client-auth command is not supported by the current daemon mode");
772
+	}
773
+      break;
774
+#ifdef MANAGEMENT_PF
775
+    case IEC_CLIENT_PF:
776
+      if (man->persist.callback.client_pf)
777
+	{
778
+	  const bool status = (*man->persist.callback.client_pf)
779
+	    (man->persist.callback.arg,
780
+	     man->connection.in_extra_cid,
781
+	     man->connection.in_extra);
782
+	  man->connection.in_extra = NULL;
783
+	  if (status)
784
+	    {
785
+	      msg (M_CLIENT, "SUCCESS: client-pf command succeeded");
786
+	    }
787
+	  else
788
+	    {
789
+	      msg (M_CLIENT, "ERROR: client-pf command failed");
790
+	    }
791
+	}
792
+      else
793
+	{
794
+	  msg (M_CLIENT, "ERROR: The client-pf command is not supported by the current daemon mode");
795
+	}
796
+      break;
797
+#endif
798
+    }
799
+   in_extra_reset (&man->connection, false);
695 800
 }
696 801
 
802
+static void
803
+man_client_auth (struct management *man, const char *cid_str, const char *kid_str, const bool extra)
804
+{
805
+  struct man_connection *mc = &man->connection;
806
+  mc->in_extra_cid = 0;
807
+  mc->in_extra_kid = 0;
808
+  if (parse_cid (cid_str, &mc->in_extra_cid)
809
+      && parse_kid (kid_str, &mc->in_extra_kid))
810
+    {
811
+      mc->in_extra_cmd = IEC_CLIENT_AUTH;
812
+      in_extra_reset (mc, true);
813
+      if (!extra)
814
+	in_extra_dispatch (man);
815
+    }
816
+}
817
+
818
+static void
819
+man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason)
820
+{
821
+  unsigned long cid = 0;
822
+  unsigned int kid = 0;
823
+  if (parse_cid (cid_str, &cid) && parse_kid (kid_str, &kid))
824
+    {
825
+      if (man->persist.callback.client_auth)
826
+	{
827
+	  const bool status = (*man->persist.callback.client_auth)
828
+	    (man->persist.callback.arg,
829
+	     cid,
830
+	     kid,
831
+	     false,
832
+	     reason,
833
+	     NULL);
834
+	  if (status)
835
+	    {
836
+	      msg (M_CLIENT, "SUCCESS: client-deny command succeeded");
837
+	    }
838
+	  else
839
+	    {
840
+	      msg (M_CLIENT, "ERROR: client-deny command failed");
841
+	    }
842
+	}
843
+      else
844
+	{
845
+	  msg (M_CLIENT, "ERROR: The client-deny command is not supported by the current daemon mode");
846
+	}
847
+    }
848
+}
849
+
850
+static void
851
+man_client_kill (struct management *man, const char *cid_str)
852
+{
853
+  unsigned long cid = 0;
854
+  if (parse_cid (cid_str, &cid))
855
+    {
856
+      if (man->persist.callback.kill_by_cid)
857
+	{
858
+	  const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid);
859
+	  if (status)
860
+	    {
861
+	      msg (M_CLIENT, "SUCCESS: client-kill command succeeded");
862
+	    }
863
+	  else
864
+	    {
865
+	      msg (M_CLIENT, "ERROR: client-kill command failed");
866
+	    }
867
+	}
868
+      else
869
+	{
870
+	  msg (M_CLIENT, "ERROR: The client-kill command is not supported by the current daemon mode");
871
+	}
872
+    }
873
+}
874
+
875
+#ifdef MANAGEMENT_PF
876
+
877
+static void
878
+man_client_pf (struct management *man, const char *cid_str)
879
+{
880
+  struct man_connection *mc = &man->connection;
881
+  mc->in_extra_cid = 0;
882
+  mc->in_extra_kid = 0;
883
+  if (parse_cid (cid_str, &mc->in_extra_cid))
884
+    {
885
+      mc->in_extra_cmd = IEC_CLIENT_PF;
886
+      in_extra_reset (mc, true);
887
+    }
888
+}
889
+
890
+#endif
891
+#endif
892
+
697 893
 #define MN_AT_LEAST (1<<0)
698 894
 
699 895
 static bool
... ...
@@ -867,6 +1072,35 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
867 867
       if (man_need (man, p, 1, 0))
868 868
 	man_bytecount (man, atoi(p[1]));
869 869
     }
870
+#ifdef MANAGEMENT_DEF_AUTH
871
+  else if (streq (p[0], "client-kill"))
872
+    {
873
+      if (man_need (man, p, 1, 0))
874
+	man_client_kill (man, p[1]);
875
+    }
876
+  else if (streq (p[0], "client-deny"))
877
+    {
878
+      if (man_need (man, p, 3, 0))
879
+	man_client_deny (man, p[1], p[2], p[3]);
880
+    }
881
+  else if (streq (p[0], "client-auth-nt"))
882
+    {
883
+      if (man_need (man, p, 2, 0))
884
+	man_client_auth (man, p[1], p[2], false);
885
+    }
886
+  else if (streq (p[0], "client-auth"))
887
+    {
888
+      if (man_need (man, p, 2, 0))
889
+	man_client_auth (man, p[1], p[2], true);
890
+    }
891
+#ifdef MANAGEMENT_PF
892
+  else if (streq (p[0], "client-pf"))
893
+    {
894
+      if (man_need (man, p, 1, 0))
895
+	man_client_pf (man, p[1]);
896
+    }
897
+#endif
898
+#endif
870 899
 #ifdef ENABLE_PKCS11
871 900
   else if (streq (p[0], "pkcs11-id-count"))
872 901
     {
... ...
@@ -999,7 +1233,7 @@ man_new_connection_post (struct management *man, const char *description)
999 999
        description,
1000 1000
        print_sockaddr (&man->settings.local, &gc));
1001 1001
 
1002
-  output_list_reset (man->connection.out);
1002
+  buffer_list_reset (man->connection.out);
1003 1003
 
1004 1004
   if (!man_password_needed (man))
1005 1005
     man_welcome (man);
... ...
@@ -1134,14 +1368,17 @@ man_reset_client_socket (struct management *man, const bool exiting)
1134 1134
       man_close_socket (man, man->connection.sd_cli);
1135 1135
       man->connection.sd_cli = SOCKET_UNDEFINED;
1136 1136
       command_line_reset (man->connection.in);
1137
-      output_list_reset (man->connection.out);
1137
+      buffer_list_reset (man->connection.out);
1138
+#ifdef MANAGEMENT_DEF_AUTH
1139
+      in_extra_reset (&man->connection, false);
1140
+#endif
1138 1141
     }
1139 1142
   if (!exiting)
1140 1143
     {
1141
-      if (man->settings.management_forget_disconnect)
1144
+      if (man->settings.flags & MF_FORGET_DISCONNECT)
1142 1145
 	 ssl_purge_auth ();
1143 1146
 
1144
-      if (man->settings.signal_on_disconnect) {
1147
+      if (man->settings.flags & MF_SIGNAL) {
1145 1148
       	  int mysig = man_mod_signal (man, SIGUSR1);
1146 1149
 	  if (mysig >= 0)
1147 1150
 	    {
... ...
@@ -1150,7 +1387,7 @@ man_reset_client_socket (struct management *man, const bool exiting)
1150 1150
 	    }
1151 1151
       }
1152 1152
 
1153
-      if (man->settings.connect_as_client)
1153
+      if (man->settings.flags & MF_CONNECT_AS_CLIENT)
1154 1154
 	{
1155 1155
 	  msg (D_MANAGEMENT, "MANAGEMENT: Triggering management exit");
1156 1156
 	  throw_signal_soft (SIGTERM, "management-exit");
... ...
@@ -1170,6 +1407,9 @@ man_process_command (struct management *man, const char *line)
1170 1170
 
1171 1171
   CLEAR (parms);
1172 1172
   so = status_open (NULL, 0, -1, &man->persist.vout, 0);
1173
+#ifdef MANAGEMENT_DEF_AUTH
1174
+  in_extra_reset (&man->connection, false);
1175
+#endif
1173 1176
 
1174 1177
   if (man_password_needed (man))
1175 1178
     {
... ...
@@ -1243,7 +1483,7 @@ man_read (struct management *man)
1243 1243
       /*
1244 1244
        * Reset output object
1245 1245
        */
1246
-      output_list_reset (man->connection.out);
1246
+      buffer_list_reset (man->connection.out);
1247 1247
 
1248 1248
       /*
1249 1249
        * process command line if complete
... ...
@@ -1252,7 +1492,22 @@ man_read (struct management *man)
1252 1252
 	const unsigned char *line;
1253 1253
 	while ((line = command_line_get (man->connection.in)))
1254 1254
 	  {
1255
-	    man_process_command (man, (char *) line);
1255
+#ifdef MANAGEMENT_DEF_AUTH
1256
+	    if (man->connection.in_extra)
1257
+	      {
1258
+		if (!strcmp ((char *)line, "END"))
1259
+		  {
1260
+		    in_extra_dispatch (man);
1261
+		    in_extra_reset (&man->connection, false);
1262
+		  }
1263
+		else
1264
+		  {
1265
+		    buffer_list_push (man->connection.in_extra, line);
1266
+		  }
1267
+	      }
1268
+	    else
1269
+#endif
1270
+	      man_process_command (man, (char *) line);
1256 1271
 	    if (man->connection.halt)
1257 1272
 	      break;
1258 1273
 	    command_line_next (man->connection.in);
... ...
@@ -1289,14 +1544,14 @@ man_write (struct management *man)
1289 1289
   const int max_send = 256;
1290 1290
   int sent = 0;
1291 1291
 
1292
-  const struct buffer *buf = output_list_peek (man->connection.out);
1292
+  const struct buffer *buf = buffer_list_peek (man->connection.out);
1293 1293
   if (buf && BLEN (buf))
1294 1294
     {
1295 1295
       const int len = min_int (max_send, BLEN (buf));
1296 1296
       sent = send (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL);
1297 1297
       if (sent >= 0)
1298 1298
 	{
1299
-	  output_list_advance (man->connection.out, sent);
1299
+	  buffer_list_advance (man->connection.out, sent);
1300 1300
 	}
1301 1301
       else if (sent < 0)
1302 1302
 	{
... ...
@@ -1387,27 +1642,18 @@ man_settings_init (struct man_settings *ms,
1387 1387
 		   const char *addr,
1388 1388
 		   const int port,
1389 1389
 		   const char *pass_file,
1390
-		   const bool server,
1391
-		   const bool query_passwords,
1392 1390
 		   const int log_history_cache,
1393 1391
 		   const int echo_buffer_size,
1394 1392
 		   const int state_buffer_size,
1395
-		   const bool hold,
1396
-		   const bool signal_on_disconnect,
1397
-		   const bool management_forget_disconnect,
1398
-		   const bool connect_as_client,
1399 1393
 		   const char *write_peer_info_file,
1400
-		   const int remap_sigusr1)
1394
+		   const int remap_sigusr1,
1395
+		   const unsigned int flags)
1401 1396
 {
1402 1397
   if (!ms->defined)
1403 1398
     {
1404 1399
       CLEAR (*ms);
1405 1400
 
1406
-      /*
1407
-       * Are we a server?  If so, it will influence
1408
-       * the way we handle state transitions.
1409
-       */
1410
-      ms->server = server;
1401
+      ms->flags = flags;
1411 1402
 
1412 1403
       /*
1413 1404
        * Get username/password
... ...
@@ -1415,34 +1661,6 @@ man_settings_init (struct man_settings *ms,
1415 1415
       if (pass_file)
1416 1416
 	get_user_pass (&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
1417 1417
 
1418
-      /*
1419
-       * Should OpenVPN query the management layer for
1420
-       * passwords?
1421
-       */
1422
-      ms->up_query_passwords = query_passwords;
1423
-
1424
-      /*
1425
-       * Should OpenVPN hibernate on startup?
1426
-       */
1427
-      ms->hold = hold;
1428
-
1429
-      /*
1430
-       * Should OpenVPN be signaled if management
1431
-       * disconnects?
1432
-       */
1433
-      ms->signal_on_disconnect = signal_on_disconnect;
1434
-
1435
-      /*
1436
-       * Should OpenVPN forget passwords when managmenet
1437
-       * session disconnects?
1438
-       */
1439
-      ms->management_forget_disconnect = management_forget_disconnect;
1440
-
1441
-      /*
1442
-       * Should OpenVPN connect to management interface as a client
1443
-       * rather than a server?
1444
-       */
1445
-      ms->connect_as_client = connect_as_client;
1446 1418
       ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
1447 1419
 
1448 1420
       /*
... ...
@@ -1456,7 +1674,7 @@ man_settings_init (struct man_settings *ms,
1456 1456
        * Run management over tunnel, or
1457 1457
        * separate channel?
1458 1458
        */
1459
-      if (streq (addr, "tunnel") && !connect_as_client)
1459
+      if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
1460 1460
 	{
1461 1461
 	  ms->management_over_tunnel = true;
1462 1462
 	}
... ...
@@ -1511,7 +1729,7 @@ man_connection_init (struct management *man)
1511 1511
        * command output from/to the socket.
1512 1512
        */
1513 1513
       man->connection.in = command_line_new (256);
1514
-      man->connection.out = output_list_new (0);
1514
+      man->connection.out = buffer_list_new (0);
1515 1515
 
1516 1516
       /*
1517 1517
        * Initialize event set for standalone usage, when we are
... ...
@@ -1525,7 +1743,7 @@ man_connection_init (struct management *man)
1525 1525
       /*
1526 1526
        * Listen/connect socket
1527 1527
        */
1528
-      if (man->settings.connect_as_client)
1528
+      if (man->settings.flags & MF_CONNECT_AS_CLIENT)
1529 1529
 	man_connect (man);
1530 1530
       else
1531 1531
 	man_listen (man);
... ...
@@ -1549,7 +1767,10 @@ man_connection_close (struct management *man)
1549 1549
   if (mc->in)
1550 1550
     command_line_free (mc->in);
1551 1551
   if (mc->out)
1552
-    output_list_free (mc->out);
1552
+    buffer_list_free (mc->out);
1553
+#ifdef MANAGEMENT_DEF_AUTH
1554
+  in_extra_reset (&man->connection, false);
1555
+#endif
1553 1556
   man_connection_clear (mc);
1554 1557
 }
1555 1558
 
... ...
@@ -1574,17 +1795,12 @@ management_open (struct management *man,
1574 1574
 		 const char *addr,
1575 1575
 		 const int port,
1576 1576
 		 const char *pass_file,
1577
-		 const bool server,
1578
-		 const bool query_passwords,
1579 1577
 		 const int log_history_cache,
1580 1578
 		 const int echo_buffer_size,
1581 1579
 		 const int state_buffer_size,
1582
-		 const bool hold,
1583
-		 const bool signal_on_disconnect,
1584
-		 const bool management_forget_disconnect,
1585
-		 const bool connect_as_client,
1586 1580
 		 const char *write_peer_info_file,
1587
-		 const int remap_sigusr1)
1581
+		 const int remap_sigusr1,
1582
+		 const unsigned int flags)
1588 1583
 {
1589 1584
   bool ret = false;
1590 1585
 
... ...
@@ -1596,17 +1812,12 @@ management_open (struct management *man,
1596 1596
 		     addr,
1597 1597
 		     port,
1598 1598
 		     pass_file,
1599
-		     server,
1600
-		     query_passwords,
1601 1599
 		     log_history_cache,
1602 1600
 		     echo_buffer_size,
1603 1601
 		     state_buffer_size,
1604
-		     hold,
1605
-		     signal_on_disconnect,
1606
-		     management_forget_disconnect,
1607
-		     connect_as_client,
1608 1602
 		     write_peer_info_file,
1609
-		     remap_sigusr1);
1603
+		     remap_sigusr1,
1604
+		     flags);
1610 1605
 
1611 1606
   /*
1612 1607
    * The log is initially sized to MANAGEMENT_LOG_HISTORY_INITIAL_SIZE,
... ...
@@ -1665,7 +1876,7 @@ management_set_state (struct management *man,
1665 1665
 		      const in_addr_t tun_local_ip,
1666 1666
 		      const in_addr_t tun_remote_ip)
1667 1667
 {
1668
-  if (man->persist.state && (!man->settings.server || state < OPENVPN_STATE_CLIENT_BASE))
1668
+  if (man->persist.state && (!(man->settings.flags & MF_SERVER) || state < OPENVPN_STATE_CLIENT_BASE))
1669 1669
     {
1670 1670
       struct gc_arena gc = gc_new ();
1671 1671
       struct log_entry e;
... ...
@@ -1697,6 +1908,79 @@ management_set_state (struct management *man,
1697 1697
     }
1698 1698
 }
1699 1699
 
1700
+#ifdef MANAGEMENT_DEF_AUTH
1701
+
1702
+static void
1703
+man_output_env (const struct env_set *es)
1704
+{
1705
+  if (es)
1706
+    {
1707
+      struct env_item *e;
1708
+      for (e = es->list; e != NULL; e = e->next)
1709
+	{
1710
+	  if (e->string)
1711
+	    msg (M_CLIENT, ">CLIENT:ENV,%s", e->string);
1712
+	}
1713
+    }
1714
+  msg (M_CLIENT, ">CLIENT:ENV,END");
1715
+}
1716
+
1717
+void
1718
+management_notify_client_needing_auth (struct management *management,
1719
+				       const unsigned int mda_key_id,
1720
+				       struct man_def_auth_context *mdac,
1721
+				       const struct env_set *es)
1722
+{
1723
+  if (!(mdac->flags & DAF_CONNECTION_CLOSED))
1724
+    {
1725
+      const char *mode = "CONNECT";
1726
+      if (mdac->flags & DAF_CONNECTION_ESTABLISHED)
1727
+	mode = "REAUTH";
1728
+      msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
1729
+      man_output_env (es);
1730
+      mdac->flags |= DAF_INITIAL_AUTH;
1731
+    }
1732
+}
1733
+
1734
+void
1735
+management_connection_established (struct management *management,
1736
+				   struct man_def_auth_context *mdac)
1737
+{
1738
+  mdac->flags |= DAF_CONNECTION_ESTABLISHED;
1739
+}
1740
+
1741
+void
1742
+management_notify_client_close (struct management *management,
1743
+				struct man_def_auth_context *mdac,
1744
+				const struct env_set *es)
1745
+{
1746
+  if ((mdac->flags & DAF_INITIAL_AUTH) && !(mdac->flags & DAF_CONNECTION_CLOSED))
1747
+    {
1748
+      msg (M_CLIENT, ">CLIENT:DISCONNECT,%lu", mdac->cid);
1749
+      man_output_env (es);
1750
+      mdac->flags |= DAF_CONNECTION_CLOSED;
1751
+    }
1752
+}
1753
+
1754
+void
1755
+management_learn_addr (struct management *management,
1756
+		       struct man_def_auth_context *mdac,
1757
+		       const struct mroute_addr *addr,
1758
+		       const bool primary)
1759
+{
1760
+  struct gc_arena gc = gc_new ();
1761
+  if ((mdac->flags & DAF_INITIAL_AUTH) && !(mdac->flags & DAF_CONNECTION_CLOSED))
1762
+    {
1763
+      msg (M_CLIENT, ">CLIENT:ADDRESS,%lu,%s,%d",
1764
+	   mdac->cid,
1765
+	   mroute_addr_print_ex (addr, MAPF_SUBNET, &gc),
1766
+	   BOOL_CAST (primary));
1767
+    }
1768
+  gc_free (&gc);
1769
+}
1770
+
1771
+#endif
1772
+
1700 1773
 void
1701 1774
 management_echo (struct management *man, const char *string, const bool pull)
1702 1775
 {
... ...
@@ -2178,7 +2462,7 @@ management_query_user_pass (struct management *man,
2178 2178
 bool
2179 2179
 management_would_hold (struct management *man)
2180 2180
 {
2181
-  return man->settings.hold && !man->persist.hold_release && man_standalone_ok (man);
2181
+  return (man->settings.flags & MF_HOLD) && !man->persist.hold_release && man_standalone_ok (man);
2182 2182
 }
2183 2183
 
2184 2184
 /*
... ...
@@ -2188,7 +2472,7 @@ management_would_hold (struct management *man)
2188 2188
 bool
2189 2189
 management_should_daemonize (struct management *man)
2190 2190
 {
2191
-  return management_would_hold (man) || man->settings.up_query_passwords;
2191
+  return management_would_hold (man) || (man->settings.flags & MF_QUERY_PASSWORDS);
2192 2192
 }
2193 2193
 
2194 2194
 /*
... ...
@@ -2302,108 +2586,6 @@ command_line_next (struct command_line *cl)
2302 2302
 }
2303 2303
 
2304 2304
 /*
2305
- * struct output_list
2306
- */
2307
-
2308
-struct output_list *
2309
-output_list_new (const int max_size)
2310
-{
2311
-  struct output_list *ret;
2312
-  ALLOC_OBJ_CLEAR (ret, struct output_list);
2313
-  ret->max_size = max_size;
2314
-  ret->size = 0;
2315
-  return ret;
2316
-}
2317
-
2318
-void
2319
-output_list_free (struct output_list *ol)
2320
-{
2321
-  output_list_reset (ol);
2322
-  free (ol);
2323
-}
2324
-
2325
-bool
2326
-output_list_defined (const struct output_list *ol)
2327
-{
2328
-  return ol->head != NULL;
2329
-}
2330
-
2331
-void
2332
-output_list_reset (struct output_list *ol)
2333
-{
2334
-  struct output_entry *e = ol->head;
2335
-  while (e)
2336
-    {
2337
-      struct output_entry *next = e->next;
2338
-      free_buf (&e->buf);
2339
-      free (e);
2340
-      e = next;
2341
-    }
2342
-  ol->head = ol->tail = NULL;
2343
-  ol->size = 0;
2344
-}
2345
-
2346
-void
2347
-output_list_push (struct output_list *ol, const unsigned char *str)
2348
-{
2349
-  if (!ol->max_size || ol->size < ol->max_size)
2350
-    {
2351
-      struct output_entry *e;
2352
-      ALLOC_OBJ_CLEAR (e, struct output_entry);
2353
-
2354
-      ++ol->size;
2355
-      if (ol->tail)
2356
-	{
2357
-	  ASSERT (ol->head);
2358
-	  ol->tail->next = e;
2359
-	}
2360
-      else
2361
-	{
2362
-	  ASSERT (!ol->head);
2363
-	  ol->head = e;
2364
-	}
2365
-      e->buf = string_alloc_buf ((const char *) str, NULL);
2366
-      ol->tail = e;
2367
-    }
2368
-}
2369
-
2370
-const struct buffer *
2371
-output_list_peek (struct output_list *ol)
2372
-{
2373
-  if (ol->head)
2374
-    return &ol->head->buf;
2375
-  else
2376
-    return NULL;
2377
-}
2378
-
2379
-static void
2380
-output_list_pop (struct output_list *ol)
2381
-{
2382
-  if (ol->head)
2383
-    {
2384
-      struct output_entry *e = ol->head->next;
2385
-      free_buf (&ol->head->buf);
2386
-      free (ol->head);
2387
-      ol->head = e;
2388
-      --ol->size;
2389
-      if (!e)
2390
-	ol->tail = NULL;
2391
-    }
2392
-}
2393
-
2394
-void
2395
-output_list_advance (struct output_list *ol, int n)
2396
-{
2397
-  if (ol->head)
2398
-    {
2399
-      struct buffer *buf = &ol->head->buf;
2400
-      ASSERT (buf_advance (buf, n));
2401
-      if (!BLEN (buf))
2402
-	output_list_pop (ol);
2403
-    }
2404
-}
2405
-
2406
-/*
2407 2305
  * struct log_entry
2408 2306
  */
2409 2307
 
... ...
@@ -30,6 +30,7 @@
30 30
 #include "misc.h"
31 31
 #include "event.h"
32 32
 #include "socket.h"
33
+#include "mroute.h"
33 34
 
34 35
 #define MANAGEMENT_VERSION                      1
35 36
 #define MANAGEMENT_N_PASSWORD_RETRIES           3
... ...
@@ -38,6 +39,22 @@
38 38
 #define MANAGEMENT_STATE_BUFFER_SIZE          100
39 39
 
40 40
 /*
41
+ * Management-interface-based deferred authentication
42
+ */
43
+#ifdef MANAGEMENT_DEF_AUTH
44
+struct man_def_auth_context {
45
+  unsigned long cid;
46
+
47
+#define DAF_CONNECTION_ESTABLISHED (1<<0)
48
+#define DAF_CONNECTION_CLOSED      (1<<1)
49
+#define DAF_INITIAL_AUTH           (1<<2)
50
+  unsigned int flags;
51
+
52
+  unsigned int mda_key_id_counter;
53
+};
54
+#endif
55
+
56
+/*
41 57
  * Manage build-up of command line
42 58
  */
43 59
 struct command_line
... ...
@@ -55,34 +72,6 @@ void command_line_reset (struct command_line *cl);
55 55
 void command_line_next (struct command_line *cl);
56 56
 
57 57
 /*
58
- * Manage lists of output strings
59
- */
60
-
61
-struct output_entry
62
-{
63
-  struct buffer buf;
64
-  struct output_entry *next;
65
-};
66
-
67
-struct output_list
68
-{
69
-  struct output_entry *head; /* next item to pop/peek */
70
-  struct output_entry *tail; /* last item pushed */
71
-  int size;                  /* current number of entries */
72
-  int max_size;              /* maximum size list should grow to */
73
-};
74
-
75
-struct output_list *output_list_new (const int max_size);
76
-void output_list_free (struct output_list *ol);
77
-
78
-bool output_list_defined (const struct output_list *ol);
79
-void output_list_reset (struct output_list *ol);
80
-
81
-void output_list_push (struct output_list *ol, const unsigned char *str);
82
-const struct buffer *output_list_peek (struct output_list *ol);
83
-void output_list_advance (struct output_list *ol, int n);
84
-
85
-/*
86 58
  * Manage log file history
87 59
  */
88 60
 
... ...
@@ -148,7 +137,8 @@ log_history_capacity (const struct log_history *h)
148 148
 }
149 149
 
150 150
 /*
151
- * Callbacks for 'status' and 'kill' commands
151
+ * Callbacks for 'status' and 'kill' commands.
152
+ * Also for management-based deferred authentication and packet filter.
152 153
  */
153 154
 struct management_callback
154 155
 {
... ...
@@ -158,6 +148,20 @@ struct management_callback
158 158
   int (*kill_by_cn) (void *arg, const char *common_name);
159 159
   int (*kill_by_addr) (void *arg, const in_addr_t addr, const int port);
160 160
   void (*delete_event) (void *arg, event_t event);
161
+#ifdef MANAGEMENT_DEF_AUTH
162
+  bool (*kill_by_cid) (void *arg, const unsigned long cid);
163
+  bool (*client_auth) (void *arg,
164
+		       const unsigned long cid,
165
+		       const unsigned int mda_key_id,
166
+		       const bool auth,
167
+		       const char *reason,
168
+		       struct buffer_list *cc_config); /* ownership transferred */
169
+#endif
170
+#ifdef MANAGEMENT_PF
171
+  bool (*client_pf) (void *arg,
172
+		     const unsigned long cid,
173
+		     struct buffer_list *pf_config);   /* ownership transferred */
174
+#endif
161 175
 };
162 176
 
163 177
 /*
... ...
@@ -196,18 +200,13 @@ struct man_persist {
196 196
 
197 197
 struct man_settings {
198 198
   bool defined;
199
+  unsigned int flags; /* MF_x flags */
199 200
   struct openvpn_sockaddr local;
200
-  bool up_query_passwords;
201 201
   bool management_over_tunnel;
202 202
   struct user_pass up;
203 203
   int log_history_cache;
204 204
   int echo_buffer_size;
205 205
   int state_buffer_size;
206
-  bool server;
207
-  bool hold;
208
-  bool signal_on_disconnect;
209
-  bool management_forget_disconnect;
210
-  bool connect_as_client;
211 206
   char *write_peer_info_file;
212 207
 
213 208
 /* flags for handling the management interface "signal" command */
... ...
@@ -246,8 +245,17 @@ struct man_connection {
246 246
   int password_tries;
247 247
 
248 248
   struct command_line *in;
249
-  struct output_list *out;
250
-
249
+  struct buffer_list *out;
250
+
251
+#ifdef MANAGEMENT_DEF_AUTH
252
+# define IEC_UNDEF       0
253
+# define IEC_CLIENT_AUTH 1
254
+# define IEC_CLIENT_PF   2
255
+  int in_extra_cmd;
256
+  unsigned long in_extra_cid;
257
+  unsigned int in_extra_kid;
258
+  struct buffer_list *in_extra;
259
+#endif
251 260
   struct event_set *es;
252 261
 
253 262
   bool state_realtime;
... ...
@@ -274,21 +282,29 @@ struct user_pass;
274 274
 
275 275
 struct management *management_init (void);
276 276
 
277
+/* management_open flags */
278
+# define MF_SERVER            (1<<0)
279
+# define MF_QUERY_PASSWORDS   (1<<1)
280
+# define MF_HOLD              (1<<2)
281
+# define MF_SIGNAL            (1<<3)
282
+# define MF_FORGET_DISCONNECT (1<<4)
283
+# define MF_CONNECT_AS_CLIENT (1<<5)
284
+#ifdef MANAGEMENT_DEF_AUTH
285
+# define MF_CLIENT_AUTH       (1<<6)
286
+#endif
287
+#ifdef MANAGEMENT_PF
288
+# define MF_CLIENT_PF         (1<<7)
289
+#endif
277 290
 bool management_open (struct management *man,
278 291
 		      const char *addr,
279 292
 		      const int port,
280 293
 		      const char *pass_file,
281
-		      const bool server,
282
-		      const bool query_passwords,
283 294
 		      const int log_history_cache,
284 295
 		      const int echo_buffer_size,
285 296
 		      const int state_buffer_size,
286
-		      const bool hold,
287
-		      const bool signal_on_disconnect,
288
-		      const bool management_forget_disconnect,
289
-		      const bool connect_as_client,
290 297
 		      const char *write_peer_info_file,
291
-		      const int remap_sigusr1);
298
+		      const int remap_sigusr1,
299
+		      const unsigned int flags);
292 300
 
293 301
 void management_close (struct management *man);
294 302
 
... ...
@@ -316,6 +332,25 @@ bool management_hold (struct management *man);
316 316
 
317 317
 void management_event_loop_n_seconds (struct management *man, int sec);
318 318
 
319
+#ifdef MANAGEMENT_DEF_AUTH
320
+void management_notify_client_needing_auth (struct management *management,
321
+					    const unsigned int auth_id,
322
+					    struct man_def_auth_context *mdac,
323
+					    const struct env_set *es);
324
+
325
+void management_connection_established (struct management *management,
326
+					struct man_def_auth_context *mdac);
327
+
328
+void management_notify_client_close (struct management *management,
329
+				     struct man_def_auth_context *mdac,
330
+				     const struct env_set *es);
331
+
332
+void management_learn_addr (struct management *management,
333
+			    struct man_def_auth_context *mdac,
334
+			    const struct mroute_addr *addr,
335
+			    const bool primary);
336
+#endif
337
+
319 338
 static inline bool
320 339
 management_connected (const struct management *man)
321 340
 {
... ...
@@ -325,9 +360,25 @@ management_connected (const struct management *man)
325 325
 static inline bool
326 326
 management_query_user_pass_enabled (const struct management *man)
327 327
 {
328
-  return man->settings.up_query_passwords;
328
+  return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
329 329
 }
330 330
 
331
+#ifdef MANAGEMENT_PF
332
+static inline bool
333
+management_enable_pf (const struct management *man)
334
+{
335
+  return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF);
336
+}
337
+#endif
338
+
339
+#ifdef MANAGEMENT_DEF_AUTH
340
+static inline bool
341
+management_enable_def_auth (const struct management *man)
342
+{
343
+  return man && BOOL_CAST(man->settings.flags & MF_CLIENT_AUTH);
344
+}
345
+#endif
346
+
331 347
 /*
332 348
  * OpenVPN tells the management layer what state it's in
333 349
  */
... ...
@@ -25,13 +25,12 @@ Future versions of the management interface may allow out-of-band
25 25
 connections (i.e. not over the VPN) and secured with SSL/TLS.
26 26
 
27 27
 The management interface is enabled in the OpenVPN
28
-configuration file using the following directives:
28
+configuration file using the following directive:
29 29
 
30 30
 --management
31 31
 
32
-See the man page for documentation on these directives.
32
+See the man page for documentation on this and related
33
+directives.
33 34
 
34 35
 Once OpenVPN has started with the management layer enabled,
35 36
 you can telnet to the management port (make sure to use
... ...
@@ -444,6 +443,199 @@ Example:
444 444
      pkcs11-id-get 1
445 445
      PKCS11ID-ENTRY:'1', ID:'<snip>', BLOB:'<snip>'
446 446
 
447
+COMMAND -- client-auth  (OpenVPN 2.1 or higher)
448
+-----------------------------------------------
449
+
450
+Authorize a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request and specify
451
+"client-connect" configuration directives in a subsequent text block.
452
+
453
+The OpenVPN server should have been started with the
454
+--management-client-auth directive so that it will ask the management
455
+interface to approve client connections.
456
+
457
+
458
+  client-auth {CID} {KID}
459
+  line_1
460
+  line_2
461
+  ...
462
+  line_n
463
+  END
464
+
465
+CID,KID -- client ID and Key ID.  See documentation for ">CLIENT:"
466
+notification for more info.
467
+
468
+line_1 to line_n -- client-connect configuration text block, as would be
469
+returned by a --client-connect script.  The text block may be null, with
470
+"END" immediately following the "client-auth" line (using a null text
471
+block is equivalent to using the client-auth-nt command).
472
+
473
+A client-connect configuration text block contains OpenVPN directives
474
+that will be applied to the client instance object representing a newly
475
+connected client.
476
+
477
+COMMAND -- client-auth-nt  (OpenVPN 2.1 or higher)
478
+--------------------------------------------------
479
+
480
+Authorize a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request without specifying
481
+client-connect configuration text.
482
+
483
+The OpenVPN server should have been started with the
484
+--management-client-auth directive so that it will ask the management
485
+interface to approve client connections.
486
+
487
+  client-auth-nt {CID} {KID}
488
+
489
+CID,KID -- client ID and Key ID.  See documentation for ">CLIENT:"
490
+notification for more info.
491
+
492
+COMMAND -- client-deny  (OpenVPN 2.1 or higher)
493
+-----------------------------------------------
494
+
495
+Deny a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request.
496
+
497
+  client-deny {CID} {KID} "reason-text"
498
+
499
+CID,KID -- client ID and Key ID.  See documentation for ">CLIENT:"
500
+notification for more info.
501
+
502
+reason-text: a human-readable message explaining why the authentication
503
+request was denied.  This message will be output to the OpenVPN log
504
+file or syslog.
505
+
506
+Note that client-deny denies a specific Key ID (pertaining to a
507
+TLS renegotiation).  A client-deny command issued in response to
508
+an initial TLS key negotiation (notified by ">CLIENT:CONNECT") will
509
+terminate the client session after returning "AUTH-FAILED" to the client.
510
+On the other hand, a client-deny command issued in response to
511
+a TLS renegotiation (">CLIENT:REAUTH") will invalidate the renegotiated
512
+key, however the TLS session associated with the currently active
513
+key will continue to live for up to --tran-window seconds before
514
+expiration.
515
+
516
+To immediately kill a client session, use "client-kill".
517
+
518
+COMMAND -- client-kill  (OpenVPN 2.1 or higher)
519
+-----------------------------------------------
520
+
521
+Immediately kill a client instance by CID.
522
+
523
+  client-kill {CID}
524
+
525
+CID -- client ID.  See documentation for ">CLIENT:" notification for more
526
+info.
527
+
528
+COMMAND -- client-pf  (OpenVPN 2.1 or higher)
529
+---------------------------------------------
530
+
531
+Push a packet filter file to a specific client.
532
+
533
+The OpenVPN server should have been started with the
534
+--management-client-pf directive so that it will require that
535
+VPN tunnel packets sent or received by client instances must
536
+conform to that client's packet filter configuration.
537
+
538
+  client-pf {CID}
539
+  line_1
540
+  line_2
541
+  ...
542
+  line_n
543
+  END
544
+
545
+CID -- client ID.  See documentation for ">CLIENT:" notification for
546
+more info.
547
+
548
+line_1 to line_n -- the packet filter configuration file for this
549
+client.
550
+
551
+Packet filter file grammar:
552
+
553
+ [CLIENTS DROP|ACCEPT]
554
+ {+|-}common_name1
555
+ {+|-}common_name2
556
+ . . .
557
+ [SUBNETS DROP|ACCEPT]
558
+ {+|-}subnet1
559
+ {+|-}subnet2
560
+ . . .
561
+ [END]
562
+
563
+ Subnet: IP-ADDRESS | IP-ADDRESS/NUM_NETWORK_BITS | "unknown"
564
+
565
+ CLIENTS refers to the set of clients (by their common-name) which
566
+ this instance is allowed ('+') to connect to, or is excluded ('-')
567
+ from connecting to.  Note that in the case of client-to-client
568
+ connections, such communication must be allowed by the packet filter
569
+ configuration files of both clients AND the --client-to-client
570
+ directive must have been specified in the OpenVPN server config.
571
+
572
+ SUBNETS refers to IP addresses or IP address subnets which this
573
+ client instance may connect to ('+') or is excluded ('-') from
574
+ connecting to, and applies to IPv4 and ARP packets.  The special
575
+ "unknown" tag refers to packets of unknown type, i.e. a packet that
576
+ is not IPv4 or ARP.
577
+
578
+ DROP or ACCEPT defines default policy when there is no explicit match
579
+ for a common-name or subnet.  The [END] tag must exist.
580
+
581
+ Notes:
582
+
583
+ * The SUBNETS section currently only supports IPv4 addresses and
584
+   subnets.
585
+
586
+ * A given client or subnet rule applies to both incoming and
587
+   outgoing packets.
588
+
589
+ * The CLIENTS list is order-invariant.  Because the list is stored
590
+   as a hash-table, the order of the list does not affect its function.
591
+
592
+ * The SUBNETS table is scanned sequentially, and the first item to
593
+   match is chosen.  Therefore the SUBNETS table is NOT order-invariant.
594
+
595
+ * No client-to-client communication is allowed unless the
596
+   --client-to-client configuration directive is enabled AND
597
+   the CLIENTS list of BOTH clients allows the communication.
598
+
599
+Example packet filter spec, as transmitted to the management interface:
600
+
601
+ client-pf 42
602
+ [CLIENTS ACCEPT]
603
+ -accounting
604
+ -enigma
605
+ [SUBNETS DROP]
606
+ -10.46.79.9
607
+ +10.0.0.0/8
608
+ [END]
609
+ END
610
+
611
+The above example sets the packet filter policy for the client
612
+identified by CID=42.  This client may connect to all other clients
613
+except those having a common name of "accounting" or "enigma".
614
+The client may only interact with external IP addresses in the
615
+10.0.0.0/8 subnet, however access to 10.46.79.9 is specifically
616
+excluded.
617
+
618
+Another example packet filter spec, as transmitted to the
619
+management interface:
620
+
621
+ client-pf 99
622
+ [CLIENTS DENY]
623
+ +public
624
+ [SUBNETS ACCEPT]
625
+ +10.10.0.1
626
+ -10.0.0.0/8
627
+ -unknown
628
+ [END]
629
+ END
630
+
631
+The above example sets the packet filter policy for the client
632
+identified by CID=99.  This client may not connect to any other
633
+clients except those having a common name of "public".  It may
634
+interact with any external IP address except those in the
635
+10.0.0.0/8 netblock.  However interaction with one address in
636
+the 10.0.0.0/8 netblock is allowed: 10.10.0.1.  Also, the client
637
+may not interact with external IP addresses using an "unknown"
638
+protocol (i.e. one that is not IPv4 or ARP).
639
+
447 640
 OUTPUT FORMAT
448 641
 -------------
449 642
 
... ...
@@ -454,7 +646,7 @@ OUTPUT FORMAT
454 454
     the last line will be "END".
455 455
 
456 456
 (3) Real-time messages will be in the form ">[source]:[text]",
457
-    where source is "ECHO", "FATAL", "HOLD", "INFO", "LOG",
457
+    where source is "CLIENT", "ECHO", "FATAL", "HOLD", "INFO", "LOG",
458 458
     "NEED-OK", "PASSWORD", or "STATE".
459 459
 
460 460
 REAL-TIME MESSAGE FORMAT
... ...
@@ -469,6 +661,12 @@ column and are immediately followed by a type keyword
469 469
 indicating the type of real-time message.  The following
470 470
 types are currently defined:
471 471
 
472
+CLIENT   -- Notification of client connections and disconnections
473
+            on an OpenVPN server.  Enabled when OpenVPN is started
474
+            with the --management-client-auth option.  CLIENT
475
+            notifications may be multi-line.  See "The CLIENT
476
+            notification" section below for detailed info.
477
+
472 478
 ECHO     -- Echo messages as controlled by the "echo" command.
473 479
 
474 480
 FATAL    -- A fatal error which is output to the log file just
... ...
@@ -497,6 +695,60 @@ PASSWORD -- Used to tell the management client that OpenVPN
497 497
 STATE    -- Shows the current OpenVPN state, as controlled
498 498
             by the "state" command.
499 499
 
500
+The CLIENT notification
501
+-----------------------
502
+
503
+The ">CLIENT:" notification is enabled by the --management-client-auth
504
+OpenVPN configuration directive that gives the management interface client
505
+the responsibility to authenticate OpenVPN clients after their client
506
+certificate has been verified.  CLIENT notifications may be multi-line, and
507
+the sequentiality of a given CLIENT notification, its associated environmental
508
+variables, and the terminating ">CLIENT:ENV,END" line are guaranteed to be
509
+atomic.
510
+
511
+CLIENT notification types:
512
+
513
+(1) Notify new client connection ("CONNECT") or existing client TLS session
514
+    renegotiation ("REAUTH").  Information about the client is provided
515
+    by a list of environmental variables which are documented in the OpenVPN
516
+    man page.  The environmental variables passed are equivalent to those
517
+    that would be passed to an --auth-user-pass-verify script.
518
+
519
+    >CLIENT:CONNECT|REAUTH,{CID},{KID}
520
+    >CLIENT:ENV,name1=val1
521
+    >CLIENT:ENV,name2=val2
522
+    >CLIENT:ENV,...
523
+    >CLIENT:ENV,END
524
+
525
+(2) Notify existing client disconnection.  The environmental variables passed
526
+    are equivalent to those that would be passed to a --client-disconnect
527
+    script.
528
+
529
+    >CLIENT:DISCONNECT,{CID}
530
+    >CLIENT:ENV,name1=val1
531
+    >CLIENT:ENV,name2=val2
532
+    >CLIENT:ENV,...
533
+    >CLIENT:ENV,END
534
+
535
+(3) Notify that a particular virtual address or subnet
536
+    is now associated with a specific client.
537
+
538
+    >CLIENT:ADDRESS,{CID},{ADDR},{PRI}
539
+
540
+Variables:
541
+
542
+CID --  Client ID, numerical ID for each connecting client, sequence = 0,1,2,...
543
+KID --  Key ID, numerical ID for the key associated with a given client TLS session,
544
+        sequence = 0,1,2,...
545
+PRI --  Primary (1) or Secondary (0) VPN address/subnet.  All clients have at least
546
+        one primary IP address.  Secondary address/subnets are associated with
547
+        client-specific "iroute" directives.
548
+ADDR -- IPv4 address/subnet in the form 1.2.3.4 or 1.2.3.0/255.255.255.0
549
+
550
+In the unlikely scenario of an extremely long-running OpenVPN server,
551
+CID and KID should be assumed to recycle to 0 after (2^32)-1, however this
552
+recycling behavior is guaranteed to be collision-free.
553
+
500 554
 Command Parsing
501 555
 ---------------
502 556
 
... ...
@@ -76,87 +76,144 @@ mroute_learnable_address (const struct mroute_addr *addr)
76 76
   return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
77 77
 }
78 78
 
79
-/*
80
- * Given a raw packet in buf, return the src and dest
81
- * addresses of the packet.
82
- */
79
+static inline void
80
+mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
81
+{
82
+  if (ma)
83
+    {
84
+      ma->type = MR_ADDR_IPV4 | mask;
85
+      ma->netbits = 0;
86
+      ma->len = 4;
87
+      *(in_addr_t*)ma->addr = src;
88
+    }
89
+}
90
+
91
+static inline bool
92
+mroute_is_mcast (const in_addr_t addr)
93
+{
94
+  return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
95
+}
96
+
97
+#ifdef ENABLE_PF
98
+
99
+static unsigned int
100
+mroute_extract_addr_arp (struct mroute_addr *src,
101
+			 struct mroute_addr *dest,
102
+			 const struct buffer *buf)
103
+{
104
+  unsigned int ret = 0;
105
+  if (BLEN (buf) >= (int) sizeof (struct openvpn_arp))
106
+    {
107
+      const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf);
108
+      if (arp->mac_addr_type == htons(0x0001)
109
+	  && arp->proto_addr_type == htons(0x0800)
110
+	  && arp->mac_addr_size == 0x06
111
+	  && arp->proto_addr_size == 0x04)
112
+	{
113
+	  mroute_get_in_addr_t (src, arp->ip_src, MR_ARP);
114
+	  mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP);
115
+
116
+	  /* multicast packet? */
117
+	  if (mroute_is_mcast (arp->ip_dest))
118
+	    ret |= MROUTE_EXTRACT_MCAST;
119
+
120
+	  ret |= MROUTE_EXTRACT_SUCCEEDED;
121
+	}
122
+    }
123
+  return ret;
124
+}
125
+
126
+#endif
127
+
83 128
 unsigned int
84
-mroute_extract_addr_from_packet (struct mroute_addr *src,
85
-				 struct mroute_addr *dest,
86
-				 struct buffer *buf,
87
-				 int tunnel_type)
129
+mroute_extract_addr_ipv4 (struct mroute_addr *src,
130
+			  struct mroute_addr *dest,
131
+			  const struct buffer *buf)
88 132
 {
89 133
   unsigned int ret = 0;
90
-  verify_align_4 (buf);
91
-  if (tunnel_type == DEV_TYPE_TUN)
134
+  if (BLEN (buf) >= 1)
92 135
     {
93
-      if (BLEN (buf) >= 1)
136
+      switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
94 137
 	{
95
-	  switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
138
+	case 4:
139
+	  if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
96 140
 	    {
97
-	    case 4:
98
-	      if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
99
-		{
100
-		  const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
101
-		  if (src)
102
-		    {
103
-		      src->type = MR_ADDR_IPV4;
104
-		      src->netbits = 0;
105
-		      src->len = 4;
106
-		      memcpy (src->addr, &ip->saddr, 4);
107
-		    }
108
-		  if (dest)
109
-		    {
110
-		      dest->type = MR_ADDR_IPV4;
111
-		      dest->netbits = 0;
112
-		      dest->len = 4;
113
-		      memcpy (dest->addr, &ip->daddr, 4);
114
-
115
-		      /* mcast address? */
116
-		      if ((ip->daddr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK))
117
-			ret |= MROUTE_EXTRACT_MCAST;
118
-
119
-		      /* IGMP message? */
120
-		      if (ip->protocol == OPENVPN_IPPROTO_IGMP)
121
-			ret |= MROUTE_EXTRACT_IGMP;
122
-		    }
123
-		  ret |= MROUTE_EXTRACT_SUCCEEDED;
124
-		}
125
-	      break;
126
-	    case 6:
127
-	      {
128
-		msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet"); 
129
-		break;
130
-	      }
141
+	      const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
142
+
143
+	      mroute_get_in_addr_t (src, ip->saddr, 0);
144
+	      mroute_get_in_addr_t (dest, ip->daddr, 0);
145
+
146
+	      /* multicast packet? */
147
+	      if (mroute_is_mcast (ip->daddr))
148
+		ret |= MROUTE_EXTRACT_MCAST;
149
+
150
+	      /* IGMP message? */
151
+	      if (ip->protocol == OPENVPN_IPPROTO_IGMP)
152
+		ret |= MROUTE_EXTRACT_IGMP;
153
+
154
+	      ret |= MROUTE_EXTRACT_SUCCEEDED;
131 155
 	    }
156
+	  break;
157
+	case 6:
158
+	  {
159
+	    msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet"); 
160
+	    break;
161
+	  }
132 162
 	}
133 163
     }
134
-  else if (tunnel_type == DEV_TYPE_TAP)
164
+  return ret;
165
+}
166
+
167
+unsigned int
168
+mroute_extract_addr_ether (struct mroute_addr *src,
169
+			   struct mroute_addr *dest,
170
+			   struct mroute_addr *esrc,
171
+			   struct mroute_addr *edest,
172
+			   const struct buffer *buf)
173
+{
174
+  unsigned int ret = 0;
175
+  if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
135 176
     {
136
-      if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
177
+      const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
178
+      if (src)
137 179
 	{
138
-	  const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
139
-	  if (src)
140
-	    {
141
-	      src->type = MR_ADDR_ETHER;
142
-	      src->netbits = 0;
143
-	      src->len = 6;
144
-	      memcpy (src->addr, eth->source, 6);
145
-	    }
146
-	  if (dest)
180
+	  src->type = MR_ADDR_ETHER;
181
+	  src->netbits = 0;
182
+	  src->len = 6;
183
+	  memcpy (src->addr, eth->source, 6);
184
+	}
185
+      if (dest)
186
+	{
187
+	  dest->type = MR_ADDR_ETHER;
188
+	  dest->netbits = 0;
189
+	  dest->len = 6;
190
+	  memcpy (dest->addr, eth->dest, 6);
191
+
192
+	  /* ethernet broadcast/multicast packet? */
193
+	  if (is_mac_mcast_addr (eth->dest))
194
+	    ret |= MROUTE_EXTRACT_BCAST;
195
+	}
196
+	  
197
+      ret |= MROUTE_EXTRACT_SUCCEEDED;
198
+
199
+#ifdef ENABLE_PF
200
+      if (esrc || edest)
201
+	{
202
+	  struct buffer b = *buf;
203
+	  if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
147 204
 	    {
148
-	      dest->type = MR_ADDR_ETHER;
149
-	      dest->netbits = 0;
150
-	      dest->len = 6;
151
-	      memcpy (dest->addr, eth->dest, 6);
152
-
153
-	      /* ethernet broadcast/multicast packet? */
154
-	      if (is_mac_mcast_addr (eth->dest))
155
-		ret |= MROUTE_EXTRACT_BCAST;
205
+	      switch (ntohs (eth->proto))
206
+		{
207
+		case OPENVPN_ETH_P_IPV4:
208
+		  ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT);
209
+		  break;
210
+		case OPENVPN_ETH_P_ARP:
211
+		  ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT);
212
+		  break;
213
+		}
156 214
 	    }
157
-	  
158
-	  ret |= MROUTE_EXTRACT_SUCCEEDED;
159 215
 	}
216
+#endif
160 217
     }
161 218
   return ret;
162 219
 }
... ...
@@ -229,6 +286,14 @@ const char *
229 229
 mroute_addr_print (const struct mroute_addr *ma,
230 230
 		   struct gc_arena *gc)
231 231
 {
232
+  return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
233
+}
234
+
235
+const char *
236
+mroute_addr_print_ex (const struct mroute_addr *ma,
237
+		      const unsigned int flags,
238
+		      struct gc_arena *gc)
239
+{
232 240
   struct buffer out = alloc_buf_gc (64, gc);
233 241
   if (ma)
234 242
     {
... ...
@@ -249,9 +314,19 @@ mroute_addr_print (const struct mroute_addr *ma,
249 249
 	    addr = buf_read_u32 (&buf, &status);
250 250
 	    if (status)
251 251
 	      {
252
-		buf_printf (&out, "%s", print_in_addr_t (addr, IA_EMPTY_IF_UNDEF, gc));
252
+		if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
253
+		  buf_printf (&out, "ARP/");
254
+		buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
253 255
 		if (maddr.type & MR_WITH_NETBITS)
254
-		  buf_printf (&out, "/%d", maddr.netbits);
256
+		  {
257
+		    if (flags & MAPF_SUBNET)
258
+		      {
259
+			const in_addr_t netmask = netbits_to_netmask (maddr.netbits);
260
+			buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc));
261
+		      }
262
+		    else
263
+		      buf_printf (&out, "/%d", maddr.netbits);
264
+		  }
255 265
 	      }
256 266
 	    if (maddr.type & MR_WITH_PORT)
257 267
 	      {
... ...
@@ -35,10 +35,18 @@
35 35
 #define IP_MCAST_NETWORK      ((in_addr_t)224<<24)
36 36
 
37 37
 /* Return status values for mroute_extract_addr_from_packet */
38
-#define MROUTE_EXTRACT_SUCCEEDED (1<<1)
39
-#define MROUTE_EXTRACT_BCAST     (1<<2)
40
-#define MROUTE_EXTRACT_MCAST     (1<<3)
41
-#define MROUTE_EXTRACT_IGMP      (1<<4)
38
+
39
+#define MROUTE_EXTRACT_SUCCEEDED (1<<0)
40
+#define MROUTE_EXTRACT_BCAST     (1<<1)
41
+#define MROUTE_EXTRACT_MCAST     (1<<2)
42
+#define MROUTE_EXTRACT_IGMP      (1<<3)
43
+
44
+#define MROUTE_SEC_EXTRACT_SUCCEEDED (1<<(0+MROUTE_SEC_SHIFT))
45
+#define MROUTE_SEC_EXTRACT_BCAST     (1<<(1+MROUTE_SEC_SHIFT))
46
+#define MROUTE_SEC_EXTRACT_MCAST     (1<<(2+MROUTE_SEC_SHIFT))
47
+#define MROUTE_SEC_EXTRACT_IGMP      (1<<(3+MROUTE_SEC_SHIFT))
48
+
49
+#define MROUTE_SEC_SHIFT         4
42 50
 
43 51
 /*
44 52
  * Choose the largest address possible with
... ...
@@ -62,6 +70,9 @@
62 62
 /* Address type mask indicating that netbits is part of address */
63 63
 #define MR_WITH_NETBITS          8
64 64
 
65
+/* Indicates than IPv4 addr was extracted from ARP packet */
66
+#define MR_ARP                   16
67
+
65 68
 struct mroute_addr {
66 69
   uint8_t len;      /* length of address */
67 70
   uint8_t unused;
... ...
@@ -72,8 +83,7 @@ struct mroute_addr {
72 72
 };
73 73
 
74 74
 /*
75
- * Number of bits in an address.  Should be raised for
76
- * IPv6.
75
+ * Number of bits in an address.  Should be raised for IPv6.
77 76
  */
78 77
 #define MR_HELPER_NET_LEN 32
79 78
 
... ...
@@ -89,11 +99,6 @@ struct mroute_helper {
89 89
   int net_len_refcount[MR_HELPER_NET_LEN]; /* refcount of each netlength */
90 90
 };
91 91
 
92
-unsigned int mroute_extract_addr_from_packet (struct mroute_addr *src,
93
-					      struct mroute_addr *dest,
94
-					      struct buffer *buf,
95
-					      int tunnel_type);
96
-
97 92
 struct openvpn_sockaddr;
98 93
 
99 94
 bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
... ...
@@ -110,6 +115,13 @@ void mroute_addr_init (struct mroute_addr *addr);
110 110
 const char *mroute_addr_print (const struct mroute_addr *ma,
111 111
 			       struct gc_arena *gc);
112 112
 
113
+#define MAPF_SUBNET            (1<<0)
114
+#define MAPF_IA_EMPTY_IF_UNDEF (1<<1)
115
+#define MAPF_SHOW_ARP          (1<<2)
116
+const char *mroute_addr_print_ex (const struct mroute_addr *ma,
117
+				  const unsigned int flags,
118
+				  struct gc_arena *gc);
119
+
113 120
 void mroute_addr_mask_host_bits (struct mroute_addr *ma);
114 121
 
115 122
 struct mroute_helper *mroute_helper_init (int ageable_ttl_secs);
... ...
@@ -117,6 +129,36 @@ void mroute_helper_free (struct mroute_helper *mh);
117 117
 void mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir);
118 118
 void mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir);
119 119
 
120
+/*
121
+ * Given a raw packet in buf, return the src and dest
122
+ * addresses of the packet.
123
+ */
124
+static inline unsigned int
125
+mroute_extract_addr_from_packet (struct mroute_addr *src,
126
+				 struct mroute_addr *dest,
127
+				 struct mroute_addr *esrc,
128
+				 struct mroute_addr *edest,
129
+				 const struct buffer *buf,
130
+				 int tunnel_type)
131
+{
132
+  unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src,
133
+					 struct mroute_addr *dest,
134
+					 const struct buffer *buf);
135
+
136
+  unsigned int mroute_extract_addr_ether (struct mroute_addr *src,
137
+					  struct mroute_addr *dest,
138
+					  struct mroute_addr *esrc,
139
+					  struct mroute_addr *edest,
140
+					  const struct buffer *buf);
141
+  unsigned int ret = 0;
142
+  verify_align_4 (buf);
143
+  if (tunnel_type == DEV_TYPE_TUN)
144
+    ret = mroute_extract_addr_ipv4 (src, dest, buf);
145
+  else if (tunnel_type == DEV_TYPE_TAP)
146
+    ret = mroute_extract_addr_ether (src, dest, esrc, edest, buf);
147
+  return ret;
148
+}
149
+
120 150
 static inline void
121 151
 mroute_helper_lock (struct mroute_helper *mh)
122 152
 {
... ...
@@ -166,11 +208,18 @@ mroute_extract_in_addr_t (struct mroute_addr *dest, const in_addr_t src)
166 166
 static inline in_addr_t
167 167
 in_addr_t_from_mroute_addr (const struct mroute_addr *addr)
168 168
 {
169
-  if (addr->type == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4)
169
+  if ((addr->type & MR_ADDR_MASK) == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4)
170 170
     return ntohl(*(in_addr_t*)addr->addr);
171 171
   else
172 172
     return 0;
173 173
 }
174 174
 
175
+static inline void
176
+mroute_addr_reset (struct mroute_addr *ma)
177
+{
178
+  ma->len = 0;
179
+  ma->type = MR_ADDR_NONE;
180
+}
181
+
175 182
 #endif /* P2MP_SERVER */
176 183
 #endif /* MROUTE_H */
... ...
@@ -35,6 +35,7 @@
35 35
 #include "memdbg.h"
36 36
 
37 37
 #include "forward-inline.h"
38
+#include "pf-inline.h"
38 39
 
39 40
 /*#define MULTI_DEBUG_EVENT_LOOP*/
40 41
 
... ...
@@ -49,6 +50,16 @@ id (struct multi_instance *mi)
49 49
 }
50 50
 #endif
51 51
 
52
+#ifdef MANAGEMENT_DEF_AUTH
53
+static void
54
+set_cc_config (struct multi_instance *mi, struct buffer_list *cc_config)
55
+{
56
+  if (mi->cc_config)
57
+    buffer_list_free (mi->cc_config);
58
+  mi->cc_config = cc_config;
59
+}
60
+#endif
61
+
52 62
 static bool
53 63
 learn_address_script (const struct multi_context *m,
54 64
 		      const struct multi_instance *mi,
... ...
@@ -198,6 +209,25 @@ reap_buckets_per_pass (int n_buckets)
198 198
   return constrain_int (n_buckets / REAP_DIVISOR, REAP_MIN, REAP_MAX);
199 199
 }
200 200
 
201
+#ifdef MANAGEMENT_DEF_AUTH
202
+
203
+static uint32_t
204
+cid_hash_function (const void *key, uint32_t iv)
205
+{
206
+  const unsigned long *k = (const unsigned long *)key;
207
+  return (uint32_t) *k;
208
+}
209
+
210
+static bool
211
+cid_compare_function (const void *key1, const void *key2)
212
+{
213
+  const unsigned long *k1 = (const unsigned long *)key1;
214
+  const unsigned long *k2 = (const unsigned long *)key2;
215
+  return *k1 == *k2;
216
+}
217
+
218
+#endif
219
+
201 220
 /*
202 221
  * Main initialization function, init multi_context object.
203 222
  */
... ...
@@ -252,6 +282,13 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa
252 252
 		       mroute_addr_hash_function,
253 253
 		       mroute_addr_compare_function);
254 254
 
255
+#ifdef MANAGEMENT_DEF_AUTH
256
+  m->cid_hash = hash_init (t->options.real_hash_size,
257
+			   0,
258
+			   cid_hash_function,
259
+			   cid_compare_function);
260
+#endif
261
+
255 262
   /*
256 263
    * This is our scheduler, for time-based wakeup
257 264
    * events.
... ...
@@ -376,6 +413,15 @@ ungenerate_prefix (struct multi_instance *mi)
376 376
   set_prefix (mi);
377 377
 }
378 378
 
379
+static const char *
380
+mi_prefix (const struct multi_instance *mi)
381
+{
382
+  if (mi && mi->msg_prefix)
383
+    return mi->msg_prefix;
384
+  else
385
+    return "UNDEF_I";
386
+}
387
+
379 388
 /*
380 389
  * Tell the route helper about deleted iroutes so
381 390
  * that it can update its mask of currently used
... ...
@@ -439,6 +485,11 @@ multi_client_disconnect_script (struct multi_context *m,
439 439
 	  
440 440
 	  gc_free (&gc);
441 441
 	}
442
+#ifdef MANAGEMENT_DEF_AUTH
443
+      if (management)
444
+	management_notify_client_close (management, &mi->context.c2.mda_context, mi->context.c2.es);
445
+#endif
446
+
442 447
     }
443 448
 }
444 449
 
... ...
@@ -470,6 +521,12 @@ multi_close_instance (struct multi_context *m,
470 470
 	{
471 471
 	  ASSERT (hash_remove (m->iter, &mi->real));
472 472
 	}
473
+#ifdef MANAGEMENT_DEF_AUTH
474
+      if (mi->did_cid_hash)
475
+	{
476
+	  ASSERT (hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid));
477
+	}
478
+#endif
473 479
 
474 480
       schedule_remove_entry (m->schedule, (struct schedule_entry *) mi);
475 481
 
... ...
@@ -487,6 +544,10 @@ multi_close_instance (struct multi_context *m,
487 487
       mbuf_dereference_instance (m->mbuf, mi);
488 488
     }
489 489
 
490
+#ifdef MANAGEMENT_DEF_AUTH
491
+  set_cc_config (mi, NULL);
492
+#endif
493
+
490 494
   multi_client_disconnect_script (m, mi);
491 495
 
492 496
   if (mi->did_open_context)
... ...
@@ -538,6 +599,9 @@ multi_uninit (struct multi_context *m)
538 538
 	  hash_free (m->hash);
539 539
 	  hash_free (m->vhash);
540 540
 	  hash_free (m->iter);
541
+#ifdef MANAGEMENT_DEF_AUTH
542
+	  hash_free (m->cid_hash);
543
+#endif
541 544
 	  m->hash = NULL;
542 545
 
543 546
 	  schedule_free (m->schedule);
... ...
@@ -608,6 +672,13 @@ multi_create_instance (struct multi_context *m, const struct mroute_addr *real)
608 608
     }
609 609
   mi->did_iter = true;
610 610
 
611
+#ifdef MANAGEMENT_DEF_AUTH
612
+  do {
613
+    mi->context.c2.mda_context.cid = m->cid_counter++;
614
+  } while (!hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false));
615
+  mi->did_cid_hash = true;
616
+#endif
617
+
611 618
   mi->context.c2.push_reply_deferred = true;
612 619
 
613 620
   if (!multi_process_post (m, mi, MPP_PRE_SELECT))
... ...
@@ -983,7 +1054,8 @@ static struct multi_instance *
983 983
 multi_learn_in_addr_t (struct multi_context *m,
984 984
 		       struct multi_instance *mi,
985 985
 		       in_addr_t a,
986
-		       int netbits) /* -1 if host route, otherwise # of network bits in address */
986
+		       int netbits, /* -1 if host route, otherwise # of network bits in address */
987
+		       bool primary)
987 988
 {
988 989
   struct openvpn_sockaddr remote_si;
989 990
   struct mroute_addr addr;
... ...
@@ -998,7 +1070,15 @@ multi_learn_in_addr_t (struct multi_context *m,
998 998
       addr.type |= MR_WITH_NETBITS;
999 999
       addr.netbits = (uint8_t) netbits;
1000 1000
     }
1001
-  return multi_learn_addr (m, mi, &addr, 0);
1001
+
1002
+  {
1003
+    struct multi_instance *owner = multi_learn_addr (m, mi, &addr, 0);
1004
+#ifdef MANAGEMENT_DEF_AUTH
1005
+    if (management && owner)
1006
+      management_learn_addr (management, &mi->context.c2.mda_context, &addr, primary);
1007
+#endif
1008
+    return owner;
1009
+  }
1002 1010
 }
1003 1011
 
1004 1012
 /*
... ...
@@ -1028,7 +1108,7 @@ multi_add_iroutes (struct multi_context *m,
1028 1028
 
1029 1029
 	  mroute_helper_add_iroute (m->route_helper, ir);
1030 1030
       
1031
-	  multi_learn_in_addr_t (m, mi, ir->network, ir->netbits);
1031
+	  multi_learn_in_addr_t (m, mi, ir->network, ir->netbits, false);
1032 1032
 	}
1033 1033
     }
1034 1034
   gc_free (&gc);
... ...
@@ -1255,7 +1335,7 @@ multi_client_connect_post_plugin (struct multi_context *m,
1255 1255
       for (i = 0; i < config.n; ++i)
1256 1256
 	{
1257 1257
 	  if (config.list[i] && config.list[i]->value)
1258
-	    options_plugin_import (&mi->context.options,
1258
+	    options_string_import (&mi->context.options,
1259 1259
 				   config.list[i]->value,
1260 1260
 				   D_IMPORT_ERRORS|M_OPTERR,
1261 1261
 				   option_permissions_mask,
... ...
@@ -1276,6 +1356,46 @@ multi_client_connect_post_plugin (struct multi_context *m,
1276 1276
 
1277 1277
 #endif
1278 1278
 
1279
+#ifdef MANAGEMENT_DEF_AUTH
1280
+
1281
+/*
1282
+ * Called to load management-derived client-connect config
1283
+ */
1284
+static void
1285
+multi_client_connect_mda (struct multi_context *m,
1286
+			  struct multi_instance *mi,
1287
+			  const struct buffer_list *config,
1288
+			  unsigned int option_permissions_mask,
1289
+			  unsigned int *option_types_found)
1290
+{
1291
+  if (config)
1292
+    {
1293
+      struct buffer_entry *be;
1294
+  
1295
+      for (be = config->head; be != NULL; be = be->next)
1296
+	{
1297
+	  const char *opt = BSTR(&be->buf);
1298
+	  options_string_import (&mi->context.options,
1299
+				 opt,
1300
+				 D_IMPORT_ERRORS|M_OPTERR,
1301
+				 option_permissions_mask,
1302
+				 option_types_found,
1303
+				 mi->context.c2.es);
1304
+	}
1305
+
1306
+      /*
1307
+       * If the --client-connect script generates a config file
1308
+       * with an --ifconfig-push directive, it will override any
1309
+       * --ifconfig-push directive from the --client-config-dir
1310
+       * directory or any --ifconfig-pool dynamic address.
1311
+       */
1312
+      multi_select_virtual_addr (m, mi);
1313
+      multi_set_virtual_addr_env (m, mi);
1314
+    }
1315
+}
1316
+
1317
+#endif
1318
+
1279 1319
 static void
1280 1320
 multi_client_connect_setenv (struct multi_context *m,
1281 1321
 			     struct multi_instance *mi)
... ...
@@ -1469,6 +1589,17 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
1469 1469
 	}
1470 1470
 
1471 1471
       /*
1472
+       * Check for client-connect script left by management interface client
1473
+       */
1474
+#ifdef MANAGEMENT_DEF_AUTH
1475
+      if (cc_succeeded && mi->cc_config)
1476
+	{
1477
+	  multi_client_connect_mda (m, mi, mi->cc_config, option_permissions_mask, &option_types_found);
1478
+	  ++cc_succeeded_count;
1479
+	}
1480
+#endif
1481
+
1482
+      /*
1472 1483
        * Check for "disable" directive in client-config-dir file
1473 1484
        * or config file generated by --client-connect script.
1474 1485
        */
... ...
@@ -1515,7 +1646,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
1515 1515
 	    {
1516 1516
 	      if (mi->context.c2.push_ifconfig_defined)
1517 1517
 		{
1518
-		  multi_learn_in_addr_t (m, mi, mi->context.c2.push_ifconfig_local, -1);
1518
+		  multi_learn_in_addr_t (m, mi, mi->context.c2.push_ifconfig_local, -1, true);
1519 1519
 		  msg (D_MULTI_LOW, "MULTI: primary virtual IP for %s: %s",
1520 1520
 		       multi_instance_string (mi, false, &gc),
1521 1521
 		       print_in_addr_t (mi->context.c2.push_ifconfig_local, 0, &gc));
... ...
@@ -1553,6 +1684,11 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
1553 1553
       /* set flag so we don't get called again */
1554 1554
       mi->connection_established_flag = true;
1555 1555
 
1556
+#ifdef MANAGEMENT_DEF_AUTH
1557
+      if (management)
1558
+	management_connection_established (management, &mi->context.c2.mda_context);
1559
+#endif
1560
+
1556 1561
       gc_free (&gc);
1557 1562
     }
1558 1563
 
... ...
@@ -1606,10 +1742,11 @@ multi_unicast (struct multi_context *m,
1606 1606
 /*
1607 1607
  * Broadcast a packet to all clients.
1608 1608
  */
1609
-void
1609
+static void
1610 1610
 multi_bcast (struct multi_context *m,
1611 1611
 	     const struct buffer *buf,
1612
-	     struct multi_instance *omit)
1612
+	     const struct multi_instance *sender_instance,
1613
+	     const struct mroute_addr *sender_addr)
1613 1614
 {
1614 1615
   struct hash_iterator hi;
1615 1616
   struct hash_element *he;
... ...
@@ -1628,8 +1765,34 @@ multi_bcast (struct multi_context *m,
1628 1628
       while ((he = hash_iterator_next (&hi)))
1629 1629
 	{
1630 1630
 	  mi = (struct multi_instance *) he->value;
1631
-	  if (mi != omit && !mi->halt)
1632
-	    multi_add_mbuf (m, mi, mb);
1631
+	  if (mi != sender_instance && !mi->halt)
1632
+	    {
1633
+#ifdef ENABLE_PF
1634
+	      if (sender_instance)
1635
+		{
1636
+		  if (!pf_c2c_test (&sender_instance->context, &mi->context, "bcast_c2c"))
1637
+		    {
1638
+		      msg (D_PF_DROPPED_BCAST, "PF: client[%s] -> client[%s] packet dropped by BCAST packet filter",
1639
+			   mi_prefix (sender_instance),
1640
+			   mi_prefix (mi));
1641
+		      continue;
1642
+		    }
1643
+		}
1644
+	      if (sender_addr)
1645
+		{
1646
+		  if (!pf_addr_test (&mi->context, sender_addr, "bcast_src_addr"))
1647
+		    {
1648
+		      struct gc_arena gc = gc_new ();
1649
+		      msg (D_PF_DROPPED_BCAST, "PF: addr[%s] -> client[%s] packet dropped by BCAST packet filter",
1650
+			   mroute_addr_print_ex (sender_addr, MAPF_SHOW_ARP, &gc),
1651
+			   mi_prefix (mi));
1652
+		      gc_free (&gc);
1653
+		      continue;
1654
+		    }
1655
+		}
1656
+#endif
1657
+	      multi_add_mbuf (m, mi, mb);
1658
+	    }
1633 1659
 	}
1634 1660
 
1635 1661
       hash_iterator_free (&hi);
... ...
@@ -1789,6 +1952,8 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1789 1789
 	      /* extract packet source and dest addresses */
1790 1790
 	      mroute_flags = mroute_extract_addr_from_packet (&src,
1791 1791
 							      &dest,
1792
+							      NULL,
1793
+							      NULL,
1792 1794
 							      &c->c2.to_tun,
1793 1795
 							      DEV_TYPE_TUN);
1794 1796
 
... ...
@@ -1811,7 +1976,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1811 1811
 		  if (mroute_flags & MROUTE_EXTRACT_MCAST)
1812 1812
 		    {
1813 1813
 		      /* for now, treat multicast as broadcast */
1814
-		      multi_bcast (m, &c->c2.to_tun, m->pending);
1814
+		      multi_bcast (m, &c->c2.to_tun, m->pending, NULL);
1815 1815
 		    }
1816 1816
 		  else /* possible client to client routing */
1817 1817
 		    {
... ...
@@ -1822,10 +1987,10 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1822 1822
 		      if (mi)
1823 1823
 			{
1824 1824
 #ifdef ENABLE_PF
1825
-			  if (!pf_c2c_test (c, &mi->context))
1825
+			  if (!pf_c2c_test (c, &mi->context, "tun_c2c"))
1826 1826
 			    {
1827
-			      msg (D_PF, "PF: client -> [%s] packet dropped by packet filter",
1828
-				   np (mi->msg_prefix));
1827
+			      msg (D_PF_DROPPED, "PF: client -> client[%s] packet dropped by TUN packet filter",
1828
+				   mi_prefix (mi));
1829 1829
 			    }
1830 1830
 			  else
1831 1831
 #endif
... ...
@@ -1838,18 +2003,29 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1838 1838
 		    }
1839 1839
 		}
1840 1840
 #ifdef ENABLE_PF
1841
-	      else if (!pf_addr_test (c, &dest))
1841
+	      if (c->c2.to_tun.len && !pf_addr_test (c, &dest, "tun_dest_addr"))
1842 1842
 		{
1843
-		  msg (D_PF, "PF: client -> [%s] packet dropped by packet filter",
1844
-		       mroute_addr_print (&dest, &gc));
1843
+		  msg (D_PF_DROPPED, "PF: client -> addr[%s] packet dropped by TUN packet filter",
1844
+		       mroute_addr_print_ex (&dest, MAPF_SHOW_ARP, &gc));
1845
+		  c->c2.to_tun.len = 0;
1845 1846
 		}
1846 1847
 #endif
1847 1848
 	    }
1848 1849
 	  else if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TAP)
1849 1850
 	    {
1851
+#ifdef ENABLE_PF
1852
+	      struct mroute_addr edest;
1853
+	      mroute_addr_reset (&edest);
1854
+#endif
1850 1855
 	      /* extract packet source and dest addresses */
1851 1856
 	      mroute_flags = mroute_extract_addr_from_packet (&src,
1852 1857
 							      &dest,
1858
+							      NULL,
1859
+#ifdef ENABLE_PF
1860
+							      &edest,
1861
+#else
1862
+							      NULL,
1863
+#endif
1853 1864
 							      &c->c2.to_tun,
1854 1865
 							      DEV_TYPE_TAP);
1855 1866
 
... ...
@@ -1862,7 +2038,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1862 1862
 			{
1863 1863
 			  if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))
1864 1864
 			    {
1865
-			      multi_bcast (m, &c->c2.to_tun, m->pending);
1865
+			      multi_bcast (m, &c->c2.to_tun, m->pending, NULL);
1866 1866
 			    }
1867 1867
 			  else /* try client-to-client routing */
1868 1868
 			    {
... ...
@@ -1871,12 +2047,30 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
1871 1871
 			      /* if dest addr is a known client, route to it */
1872 1872
 			      if (mi)
1873 1873
 				{
1874
-				  multi_unicast (m, &c->c2.to_tun, mi);
1875
-				  register_activity (c, BLEN(&c->c2.to_tun));
1874
+#ifdef ENABLE_PF
1875
+				  if (!pf_c2c_test (c, &mi->context, "tap_c2c"))
1876
+				    {
1877
+				      msg (D_PF_DROPPED, "PF: client -> client[%s] packet dropped by TAP packet filter",
1878
+					   mi_prefix (mi));
1879
+				    }
1880
+				  else
1881
+#endif
1882
+				    {
1883
+				      multi_unicast (m, &c->c2.to_tun, mi);
1884
+				      register_activity (c, BLEN(&c->c2.to_tun));
1885
+				    }
1876 1886
 				  c->c2.to_tun.len = 0;
1877 1887
 				}
1878 1888
 			    }
1879 1889
 			}
1890
+#ifdef ENABLE_PF
1891
+		      if (c->c2.to_tun.len && !pf_addr_test (c, &edest, "tap_dest_addr"))
1892
+			{
1893
+			  msg (D_PF_DROPPED, "PF: client -> addr[%s] packet dropped by TAP packet filter",
1894
+			       mroute_addr_print_ex (&edest, MAPF_SHOW_ARP, &gc));
1895
+			  c->c2.to_tun.len = 0;
1896
+			}
1897
+#endif
1880 1898
 		    }
1881 1899
 		  else
1882 1900
 		    {
... ...
@@ -1918,6 +2112,20 @@ multi_process_incoming_tun (struct multi_context *m, const unsigned int mpp_flag
1918 1918
       struct mroute_addr src, dest;
1919 1919
       const int dev_type = TUNNEL_TYPE (m->top.c1.tuntap);
1920 1920
 
1921
+#ifdef ENABLE_PF
1922
+      struct mroute_addr esrc, *e1, *e2;
1923
+      if (dev_type == DEV_TYPE_TUN)
1924
+	{
1925
+	  e1 = NULL;
1926
+	  e2 = &src;
1927
+	}
1928
+      else
1929
+	{
1930
+	  e1 = e2 = &esrc;
1931
+	  mroute_addr_reset (&esrc);
1932
+	}
1933
+#endif
1934
+
1921 1935
 #ifdef MULTI_DEBUG_EVENT_LOOP
1922 1936
       printf ("TUN -> TCP/UDP [%d]\n", BLEN (&m->top.c2.buf));
1923 1937
 #endif
... ...
@@ -1932,6 +2140,12 @@ multi_process_incoming_tun (struct multi_context *m, const unsigned int mpp_flag
1932 1932
 
1933 1933
       mroute_flags = mroute_extract_addr_from_packet (&src,
1934 1934
 						      &dest,
1935
+#ifdef ENABLE_PF
1936
+						      e1,
1937
+#else
1938
+						      NULL,
1939
+#endif
1940
+						      NULL,
1935 1941
 						      &m->top.c2.buf,
1936 1942
 						      dev_type);
1937 1943
 
... ...
@@ -1943,7 +2157,11 @@ multi_process_incoming_tun (struct multi_context *m, const unsigned int mpp_flag
1943 1943
 	  if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))
1944 1944
 	    {
1945 1945
 	      /* for now, treat multicast as broadcast */
1946
-	      multi_bcast (m, &m->top.c2.buf, NULL);
1946
+#ifdef ENABLE_PF
1947
+	      multi_bcast (m, &m->top.c2.buf, NULL, e2);
1948
+#else
1949
+	      multi_bcast (m, &m->top.c2.buf, NULL, NULL);
1950
+#endif
1947 1951
 	    }
1948 1952
 	  else
1949 1953
 	    {
... ...
@@ -1957,10 +2175,10 @@ multi_process_incoming_tun (struct multi_context *m, const unsigned int mpp_flag
1957 1957
 		  set_prefix (m->pending);
1958 1958
 
1959 1959
 #ifdef ENABLE_PF
1960
-		  if (!pf_addr_test (c, &src))
1960
+		  if (!pf_addr_test (c, e2, "tun_tap_src_addr"))
1961 1961
 		    {
1962
-		      msg (D_PF, "PF: [%s] -> client packet dropped by packet filter",
1963
-			   mroute_addr_print (&src, &gc));
1962
+		      msg (D_PF_DROPPED, "PF: addr[%s] -> client packet dropped by packet filter",
1963
+			   mroute_addr_print_ex (&src, MAPF_SHOW_ARP, &gc));
1964 1964
 		      buf_reset_len (&c->c2.buf);
1965 1965
 		    }
1966 1966
 		  else
... ...
@@ -2111,7 +2329,7 @@ gremlin_flood_clients (struct multi_context *m)
2111 2111
 	ASSERT (buf_write_u8 (&buf, get_random () & 0xFF));
2112 2112
 
2113 2113
       for (i = 0; i < parm.n_packets; ++i)
2114
-	multi_bcast (m, &buf, NULL);
2114
+	multi_bcast (m, &buf, NULL, NULL);
2115 2115
 
2116 2116
       gc_free (&gc);
2117 2117
     }
... ...
@@ -2281,6 +2499,86 @@ management_delete_event (void *arg, event_t event)
2281 2281
 
2282 2282
 #endif
2283 2283
 
2284
+#ifdef MANAGEMENT_DEF_AUTH
2285
+
2286
+static struct multi_instance *
2287
+lookup_by_cid (struct multi_context *m, const unsigned long cid)
2288
+{
2289
+  if (m)
2290
+    {
2291
+      struct multi_instance *mi = (struct multi_instance *) hash_lookup (m->cid_hash, &cid);
2292
+      if (mi && !mi->halt)
2293
+	return mi;
2294
+    }
2295
+  return NULL;
2296
+}
2297
+
2298
+static bool
2299
+management_kill_by_cid (void *arg, const unsigned long cid)
2300
+{
2301
+  struct multi_context *m = (struct multi_context *) arg;
2302
+  struct multi_instance *mi = lookup_by_cid (m, cid);
2303
+  if (mi)
2304
+    {
2305
+      multi_signal_instance (m, mi, SIGTERM);
2306
+      return true;
2307
+    }
2308
+  else
2309
+    return false;
2310
+}
2311
+
2312
+static bool
2313
+management_client_auth (void *arg,
2314
+			const unsigned long cid,
2315
+			const unsigned int mda_key_id,
2316
+			const bool auth,
2317
+			const char *reason,
2318
+			struct buffer_list *cc_config) /* ownership transferred */
2319
+{
2320
+  struct multi_context *m = (struct multi_context *) arg;
2321
+  struct multi_instance *mi = lookup_by_cid (m, cid);
2322
+  bool cc_config_owned = true;
2323
+  bool ret = false;
2324
+
2325
+  if (mi)
2326
+    {
2327
+      ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth);
2328
+      if (ret)
2329
+	{
2330
+	  if (auth && !mi->connection_established_flag)
2331
+	    {
2332
+	      set_cc_config (mi, cc_config);
2333
+	      cc_config_owned = false;
2334
+	    }
2335
+	  if (!auth && reason)
2336
+	    msg (D_MULTI_LOW, "MULTI: connection rejected: %s", reason);
2337
+	}
2338
+    }
2339
+  if (cc_config_owned && cc_config)
2340
+    buffer_list_free (cc_config);
2341
+  return ret;
2342
+}
2343
+#endif
2344
+
2345
+#ifdef MANAGEMENT_PF
2346
+static bool
2347
+management_client_pf (void *arg,
2348
+		      const unsigned long cid,
2349
+		      struct buffer_list *pf_config) /* ownership transferred */
2350
+{
2351
+  struct multi_context *m = (struct multi_context *) arg;
2352
+  struct multi_instance *mi = lookup_by_cid (m, cid);
2353
+  bool ret = false;
2354
+
2355
+  if (mi && pf_config)
2356
+    ret = pf_load_from_buffer_list (&mi->context, pf_config);
2357
+
2358
+  if (pf_config)
2359
+    buffer_list_free (pf_config);
2360
+  return ret;
2361
+}
2362
+#endif
2363
+
2284 2364
 void
2285 2365
 init_management_callback_multi (struct multi_context *m)
2286 2366
 {
... ...
@@ -2295,6 +2593,13 @@ init_management_callback_multi (struct multi_context *m)
2295 2295
       cb.kill_by_cn = management_callback_kill_by_cn;
2296 2296
       cb.kill_by_addr = management_callback_kill_by_addr;
2297 2297
       cb.delete_event = management_delete_event;
2298
+#ifdef MANAGEMENT_DEF_AUTH
2299
+      cb.kill_by_cid = management_kill_by_cid;
2300
+      cb.client_auth = management_client_auth;
2301
+#endif
2302
+#ifdef MANAGEMENT_PF
2303
+      cb.client_pf = management_client_pf;
2304
+#endif
2298 2305
       management_set_callback (management, &cb);
2299 2306
     }
2300 2307
 #endif
... ...
@@ -77,6 +77,10 @@ struct multi_instance {
77 77
   bool did_open_context;
78 78
   bool did_real_hash;
79 79
   bool did_iter;
80
+#ifdef MANAGEMENT_DEF_AUTH
81
+  bool did_cid_hash;
82
+  struct buffer_list *cc_config;
83
+#endif
80 84
   bool connection_established_flag;
81 85
   bool did_iroutes;
82 86
 
... ...
@@ -111,6 +115,11 @@ struct multi_context {
111 111
   int tcp_queue_limit;
112 112
   int status_file_version;
113 113
 
114
+#ifdef MANAGEMENT_DEF_AUTH
115
+  struct hash *cid_hash;
116
+  unsigned long cid_counter;
117
+#endif
118
+
114 119
   struct multi_instance *pending;
115 120
   struct multi_instance *earliest_wakeup;
116 121
   struct multi_instance **mpp_touched;
... ...
@@ -143,10 +152,6 @@ void tunnel_server (struct context *top);
143 143
 
144 144
 const char *multi_instance_string (const struct multi_instance *mi, bool null, struct gc_arena *gc);
145 145
 
146
-void multi_bcast (struct multi_context *m,
147
-		  const struct buffer *buf,
148
-		  struct multi_instance *omit);
149
-
150 146
 /*
151 147
  * Called by mtcp.c, mudp.c, or other (to be written) protocol drivers
152 148
  */
... ...
@@ -179,6 +179,8 @@ openvpn \- secure IP tunnel daemon.
179 179
 [\ \fB\-\-log\fR\ \fIfile\fR\ ]
180 180
 [\ \fB\-\-suppress-timestamps\fR\ ]
181 181
 [\ \fB\-\-lport\fR\ \fIport\fR\ ]
182
+[\ \fB\-\-management\-client\-auth\fR\ ]
183
+[\ \fB\-\-management\-client\-pf\fR\ ]
182 184
 [\ \fB\-\-management\-forget\-disconnect\fR\ ]
183 185
 [\ \fB\-\-management\-hold\fR\ ]
184 186
 [\ \fB\-\-management\-log\-cache\fR\ \fIn\fR\ ]
... ...
@@ -2357,6 +2359,19 @@ lines of log file history for usage
2357 2357
 by the management channel.
2358 2358
 .\"*********************************************************
2359 2359
 .TP
2360
+.B --management-client-auth
2361
+Gives management interface client the responsibility
2362
+to authenticate clients after their client certificate
2363
+has been verified.  See management-notes.txt in OpenVPN
2364
+distribution for detailed notes.
2365
+.\"*********************************************************
2366
+.TP
2367
+.B --management-client-pf
2368
+Management interface clients must specify a packet
2369
+filter file for each connecting client.  See management-notes.txt
2370
+in OpenVPN distribution for detailed notes.
2371
+.\"*********************************************************
2372
+.TP
2360 2373
 .B --plugin module-pathname [init-string]
2361 2374
 Load plug-in module from the file
2362 2375
 .B module-pathname,
... ...
@@ -437,6 +437,10 @@ struct context_2
437 437
 #ifdef ENABLE_PF
438 438
   struct pf_context pf;
439 439
 #endif
440
+
441
+#ifdef MANAGEMENT_DEF_AUTH
442
+  struct man_def_auth_context mda_context;
443
+#endif
440 444
 };
441 445
 
442 446
 /*
... ...
@@ -316,6 +316,15 @@ static const char usage_message[] =
316 316
   "                                 event occurs.\n"
317 317
   "--management-log-cache n : Cache n lines of log file history for usage\n"
318 318
   "                  by the management channel.\n"
319
+#ifdef MANAGEMENT_DEF_AUTH
320
+  "--management-client-auth : gives management interface client the responsibility\n"
321
+  "                           to authenticate clients after their client certificate\n"
322
+  "			      has been verified.\n"
323
+#endif
324
+#ifdef MANAGEMENT_PF
325
+  "--management-client-pf : management interface clients must specify a packet\n"
326
+  "                         filter file for each connecting client.\n"
327
+#endif
319 328
 #endif
320 329
 #ifdef ENABLE_PLUGIN
321 330
   "--plugin m [str]: Load plug-in module m passing str as an argument\n"
... ...
@@ -1195,12 +1204,8 @@ show_settings (const struct options *o)
1195 1195
   SHOW_STR (management_user_pass);
1196 1196
   SHOW_INT (management_log_history_cache);
1197 1197
   SHOW_INT (management_echo_buffer_size);
1198
-  SHOW_BOOL (management_query_passwords);
1199
-  SHOW_BOOL (management_hold);
1200
-  SHOW_BOOL (management_client);
1201
-  SHOW_BOOL (management_signal);
1202
-  SHOW_BOOL (management_forget_disconnect);
1203 1198
   SHOW_STR (management_write_peer_info_file);
1199
+  SHOW_INT (management_flags);
1204 1200
 #endif
1205 1201
 #ifdef ENABLE_PLUGIN
1206 1202
   if (o->plugin_list)
... ...
@@ -1525,8 +1530,7 @@ options_postprocess (struct options *options, bool first_time)
1525 1525
    */
1526 1526
 #ifdef ENABLE_MANAGEMENT
1527 1527
   if (!options->management_addr &&
1528
-      (options->management_query_passwords || options->management_hold || options->management_signal
1529
-       || options->management_forget_disconnect || options->management_client
1528
+      (options->management_flags
1530 1529
        || options->management_write_peer_info_file
1531 1530
        || options->management_log_history_cache != defaults.management_log_history_cache))
1532 1531
     msg (M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified");
... ...
@@ -1672,12 +1676,15 @@ options_postprocess (struct options *options, bool first_time)
1672 1672
       if (options->key_method != 2)
1673 1673
 	msg (M_USAGE, "--mode server requires --key-method 2");
1674 1674
 
1675
-      if (PLUGIN_OPTION_LIST (options) == NULL)
1676 1675
 	{
1677
-	  if (options->client_cert_not_required && !options->auth_user_pass_verify_script)
1678
-	    msg (M_USAGE, "--client-cert-not-required must be used with an --auth-user-pass-verify script");
1679
-	  if (options->username_as_common_name && !options->auth_user_pass_verify_script)
1680
-	    msg (M_USAGE, "--username-as-common-name must be used with an --auth-user-pass-verify script");
1676
+	  const bool ccnr = (options->auth_user_pass_verify_script
1677
+			     || PLUGIN_OPTION_LIST (options)
1678
+			     || MAN_CLIENT_AUTH_ENABLED (options));
1679
+	  const char *postfix = "must be used with --management-client-auth, an --auth-user-pass-verify script, or plugin";
1680
+	  if (options->client_cert_not_required && !ccnr)
1681
+	    msg (M_USAGE, "--client-cert-not-required %s", postfix);
1682
+	  if (options->username_as_common_name && !ccnr)
1683
+	    msg (M_USAGE, "--username-as-common-name %s", postfix);
1681 1684
 	}
1682 1685
     }
1683 1686
   else
... ...
@@ -2983,9 +2990,7 @@ options_server_import (struct options *o,
2983 2983
 		    es);
2984 2984
 }
2985 2985
 
2986
-#ifdef ENABLE_PLUGIN
2987
-
2988
-void options_plugin_import (struct options *options,
2986
+void options_string_import (struct options *options,
2989 2987
 			    const char *config,
2990 2988
 			    const int msglevel,
2991 2989
 			    const unsigned int permission_mask,
... ...
@@ -2995,8 +3000,6 @@ void options_plugin_import (struct options *options,
2995 2995
   read_config_string (options, config, msglevel, permission_mask, option_types_found, es);
2996 2996
 }
2997 2997
 
2998
-#endif
2999
-
3000 2998
 #if P2MP
3001 2999
 
3002 3000
 #define VERIFY_PERMISSION(mask) { if (!verify_permission(p[0], (mask), permission_mask, option_types_found, msglevel)) goto err; }
... ...
@@ -3144,29 +3147,43 @@ add_option (struct options *options,
3144 3144
   else if (streq (p[0], "management-query-passwords"))
3145 3145
     {
3146 3146
       VERIFY_PERMISSION (OPT_P_GENERAL);
3147
-      options->management_query_passwords = true;
3147
+      options->management_flags |= MF_QUERY_PASSWORDS;
3148 3148
     }
3149 3149
   else if (streq (p[0], "management-hold"))
3150 3150
     {
3151 3151
       VERIFY_PERMISSION (OPT_P_GENERAL);
3152
-      options->management_hold = true;
3152
+      options->management_flags |= MF_HOLD;
3153 3153
     }
3154 3154
   else if (streq (p[0], "management-signal"))
3155 3155
     {
3156 3156
       VERIFY_PERMISSION (OPT_P_GENERAL);
3157
-      options->management_signal = true;
3157
+      options->management_flags |= MF_SIGNAL;
3158 3158
     }
3159 3159
   else if (streq (p[0], "management-forget-disconnect"))
3160 3160
     {
3161 3161
       VERIFY_PERMISSION (OPT_P_GENERAL);
3162
-      options->management_forget_disconnect = true;
3162
+      options->management_flags |= MF_FORGET_DISCONNECT;
3163 3163
     }
3164 3164
   else if (streq (p[0], "management-client"))
3165 3165
     {
3166 3166
       VERIFY_PERMISSION (OPT_P_GENERAL);
3167
-      options->management_client = true;
3167
+      options->management_flags |= MF_CONNECT_AS_CLIENT;
3168 3168
       options->management_write_peer_info_file = p[1];
3169 3169
     }
3170
+#ifdef MANAGEMENT_DEF_AUTH
3171
+  else if (streq (p[0], "management-client-auth"))
3172
+    {
3173
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3174
+      options->management_flags |= MF_CLIENT_AUTH;
3175
+    }
3176
+#endif
3177
+#ifdef MANAGEMENT_PF
3178
+  else if (streq (p[0], "management-client-pf"))
3179
+    {
3180
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3181
+      options->management_flags |= (MF_CLIENT_PF | MF_CLIENT_AUTH);
3182
+    }
3183
+#endif
3170 3184
   else if (streq (p[0], "management-log-cache") && p[1])
3171 3185
     {
3172 3186
       int cache;
... ...
@@ -281,12 +281,10 @@ struct options
281 281
   int management_log_history_cache;
282 282
   int management_echo_buffer_size;
283 283
   int management_state_buffer_size;
284
-  bool management_query_passwords;
285
-  bool management_hold;
286
-  bool management_signal;
287
-  bool management_forget_disconnect;
288
-  bool management_client;
289 284
   const char *management_write_peer_info_file;
285
+
286
+  /* Mask of MF_ values of manage.h */
287
+  unsigned int management_flags;
290 288
 #endif
291 289
 
292 290
 #ifdef ENABLE_PLUGIN
... ...
@@ -537,6 +535,12 @@ struct options
537 537
 #define PLUGIN_OPTION_LIST(opt) (NULL)
538 538
 #endif
539 539
 
540
+#ifdef MANAGEMENT_DEF_AUTH
541
+#define MAN_CLIENT_AUTH_ENABLED(opt) ((opt)->management_flags & MF_CLIENT_AUTH)
542
+#else
543
+#define MAN_CLIENT_AUTH_ENABLED(opt) (false)
544
+#endif
545
+
540 546
 void parse_argv (struct options *options,
541 547
 		 const int argc,
542 548
 		 char *argv[],
... ...
@@ -632,9 +636,7 @@ const char *auth_retry_print (void);
632 632
 
633 633
 #endif
634 634
 
635
-#ifdef ENABLE_PLUGIN
636
-
637
-void options_plugin_import (struct options *options,
635
+void options_string_import (struct options *options,
638 636
 			    const char *config,
639 637
 			    const int msglevel,
640 638
 			    const unsigned int permission_mask,
... ...
@@ -642,5 +644,3 @@ void options_plugin_import (struct options *options,
642 642
 			    struct env_set *es);
643 643
 
644 644
 #endif
645
-
646
-#endif
647 645
new file mode 100644
... ...
@@ -0,0 +1,59 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+#if defined(ENABLE_PF) && !defined(PF_INLINE_H)
25
+#define PF_INLINE_H
26
+
27
+/*
28
+ * Inline functions
29
+ */
30
+
31
+#define PCT_SRC  1
32
+#define PCT_DEST 2
33
+static inline bool
34
+pf_c2c_test (const struct context *src, const struct context *dest, const char *prefix)
35
+{
36
+  bool pf_cn_test (struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix);
37
+  return  (!src->c2.pf.enabled  || pf_cn_test (src->c2.pf.pfs,  dest->c2.tls_multi, PCT_DEST, prefix))
38
+       && (!dest->c2.pf.enabled || pf_cn_test (dest->c2.pf.pfs, src->c2.tls_multi,  PCT_SRC,  prefix));
39
+}
40
+
41
+static inline bool
42
+pf_addr_test (const struct context *src, const struct mroute_addr *dest, const char *prefix)
43
+{
44
+  bool pf_addr_test_dowork (const struct context *src, const struct mroute_addr *dest, const char *prefix);
45
+
46
+  if (src->c2.pf.enabled)
47
+    return pf_addr_test_dowork (src, dest, prefix);
48
+  else
49
+    return true;
50
+}
51
+
52
+static inline bool
53
+pf_kill_test (const struct pf_set *pfs)
54
+{
55
+  return pfs->kill;
56
+}
57
+
58
+#endif
... ...
@@ -32,6 +32,8 @@
32 32
 
33 33
 #include "memdbg.h"
34 34
 
35
+#include "pf-inline.h"
36
+
35 37
 static void
36 38
 pf_destroy (struct pf_set *pfs)
37 39
 {
... ...
@@ -64,7 +66,7 @@ pf_destroy (struct pf_set *pfs)
64 64
 }
65 65
 
66 66
 static bool
67
-add_client (const char *line, const char *fn, const int line_num, struct pf_cn_elem ***next, const bool exclude)
67
+add_client (const char *line, const char *prefix, const int line_num, struct pf_cn_elem ***next, const bool exclude)
68 68
 {
69 69
   struct pf_cn_elem *e;
70 70
   ALLOC_OBJ_CLEAR (e, struct pf_cn_elem);
... ...
@@ -76,34 +78,44 @@ add_client (const char *line, const char *fn, const int line_num, struct pf_cn_e
76 76
 }
77 77
 
78 78
 static bool
79
-add_subnet (const char *line, const char *fn, const int line_num, struct pf_subnet ***next, const bool exclude)
79
+add_subnet (const char *line, const char *prefix, const int line_num, struct pf_subnet ***next, const bool exclude)
80 80
 {
81 81
   struct in_addr network;
82 82
   in_addr_t netmask = 0;
83
-  int netbits = 32;
84
-  char *div = strchr (line, '/');
85 83
 
86
-  if (div)
84
+  if (strcmp (line, "unknown"))
87 85
     {
88
-      *div++ = '\0';
89
-      if (sscanf (div, "%d", &netbits) != 1)
86
+      int netbits = 32;
87
+      char *div = strchr (line, '/');
88
+
89
+      if (div)
90 90
 	{
91
-	  msg (D_PF, "PF: %s/%d: bad '/n' subnet specifier: '%s'", fn, line_num, div);
92
-	  return false;
91
+	  *div++ = '\0';
92
+	  if (sscanf (div, "%d", &netbits) != 1)
93
+	    {
94
+	      msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div);
95
+	      return false;
96
+	    }
97
+	  if (netbits < 0 || netbits > 32)
98
+	    {
99
+	      msg (D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div);
100
+	      return false;
101
+	    }
93 102
 	}
94
-      if (netbits < 0 || netbits > 32)
103
+
104
+      if (openvpn_inet_aton (line, &network) != OIA_IP)
95 105
 	{
96
-	  msg (D_PF, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", fn, line_num, div);
106
+	  msg (D_PF_INFO, "PF: %s/%d: bad network address: '%s'", prefix, line_num, line);
97 107
 	  return false;
98 108
 	}
109
+      netmask = netbits_to_netmask (netbits);
99 110
     }
100
-
101
-  if (openvpn_inet_aton (line, &network) != OIA_IP)
111
+  else
102 112
     {
103
-      msg (D_PF, "PF: %s/%d: bad network address: '%s'", fn, line_num, line);
104
-      return false;
113
+      /* match special "unknown" tag for addresses unrecognized by mroute */
114
+      network.s_addr = htonl(0);
115
+      netmask = ~0;
105 116
     }
106
-  netmask = netbits_to_netmask (netbits);
107 117
 
108 118
   {
109 119
     struct pf_subnet *e;
... ...
@@ -130,7 +142,7 @@ cn_compare_function (const void *key1, const void *key2)
130 130
 }
131 131
 
132 132
 static bool
133
-genhash (struct pf_cn_set *cns, const char *fn, const int n_clients)
133
+genhash (struct pf_cn_set *cns, const char *prefix, const int n_clients)
134 134
 {
135 135
   struct pf_cn_elem *e;
136 136
   bool status = true;
... ...
@@ -143,7 +155,7 @@ genhash (struct pf_cn_set *cns, const char *fn, const int n_clients)
143 143
     {
144 144
       if (!hash_add (cns->hash_table, e->rule.cn, &e->rule, false))
145 145
 	{
146
-	  msg (D_PF, "PF: %s: duplicate common name in [clients] section: '%s'", fn, e->rule.cn);
146
+	  msg (D_PF_INFO, "PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn);
147 147
 	  status = false;
148 148
 	}
149 149
     }
... ...
@@ -152,7 +164,7 @@ genhash (struct pf_cn_set *cns, const char *fn, const int n_clients)
152 152
 }
153 153
 
154 154
 static struct pf_set *
155
-pf_init (const char *fn)
155
+pf_init (const struct buffer_list *bl, const char *prefix, const bool allow_kill)
156 156
 {
157 157
 # define MODE_UNDEF   0
158 158
 # define MODE_CLIENTS 1
... ...
@@ -163,18 +175,19 @@ pf_init (const char *fn)
163 163
   int n_subnets = 0;
164 164
   int n_errors = 0;
165 165
   struct pf_set *pfs = NULL;
166
-  char line[256];
166
+  char line[PF_MAX_LINE_LEN];
167 167
 
168 168
   ALLOC_OBJ_CLEAR (pfs, struct pf_set);
169
-  FILE *fp = fopen (fn, "r");
170
-  if (fp)
169
+  if (bl)
171 170
     {
172 171
       struct pf_cn_elem **cl = &pfs->cns.list;
173 172
       struct pf_subnet **sl = &pfs->sns.list;
173
+      struct buffer_entry *be;
174 174
 
175
-      while (fgets (line, sizeof (line), fp) != NULL)
175
+      for (be = bl->head; be != NULL; be = be->next)
176 176
 	{
177 177
 	  ++line_num;
178
+	  strncpynt (line, BSTR(&be->buf), sizeof(line));
178 179
 	  rm_trailing_chars (line, "\r\n\t ");
179 180
 	  if (line[0] == '\0' || line[0] == '#')
180 181
 	    ;
... ...
@@ -184,19 +197,19 @@ pf_init (const char *fn)
184 184
 
185 185
 	      if (line[1] =='\0')
186 186
 		{
187
-		  msg (D_PF, "PF: %s/%d: no data after +/-: '%s'", fn, line_num, line);
187
+		  msg (D_PF_INFO, "PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line);
188 188
 		  ++n_errors;
189 189
 		}
190 190
 	      else if (mode == MODE_CLIENTS)
191 191
 		{
192
-		  if (add_client (&line[1], fn, line_num, &cl, exclude))
192
+		  if (add_client (&line[1], prefix, line_num, &cl, exclude))
193 193
 		    ++n_clients;
194 194
 		  else
195 195
 		    ++n_errors;
196 196
 		}
197 197
 	      else if (mode == MODE_SUBNETS)
198 198
 		{
199
-		  if (add_subnet (&line[1], fn, line_num, &sl, exclude))
199
+		  if (add_subnet (&line[1], prefix, line_num, &sl, exclude))
200 200
 		    ++n_subnets;
201 201
 		  else
202 202
 		    ++n_errors;
... ...
@@ -232,41 +245,40 @@ pf_init (const char *fn)
232 232
 		}
233 233
 	      else if (!strcasecmp (line, "[end]"))
234 234
 		goto done;
235
-	      else if (!strcasecmp (line, "[kill]"))
235
+	      else if (allow_kill && !strcasecmp (line, "[kill]"))
236 236
 		goto kill;
237 237
 	      else
238 238
 		{
239 239
 		  mode = MODE_UNDEF;
240
-		  msg (D_PF, "PF: %s/%d unknown tag: '%s'", fn, line_num, line);
240
+		  msg (D_PF_INFO, "PF: %s/%d unknown tag: '%s'", prefix, line_num, line);
241 241
 		  ++n_errors;
242 242
 		}
243 243
 	    }
244 244
 	  else
245 245
 	    {
246
-	      msg (D_PF, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", fn, line_num, line);
246
+	      msg (D_PF_INFO, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line);
247 247
 	      ++n_errors;
248 248
 	    }
249 249
 	}
250 250
       ++n_errors;
251
-      msg (D_PF, "PF: %s: missing [end]", fn);
251
+      msg (D_PF_INFO, "PF: %s: missing [end]", prefix);
252 252
     }
253 253
   else
254 254
     {
255
-      msg (D_PF|M_ERRNO, "PF: %s: cannot open", fn);
255
+      msg (D_PF_INFO, "PF: %s: cannot open", prefix);
256 256
       ++n_errors;
257 257
     }
258 258
 
259 259
  done:
260
-  if (fp)
260
+  if (bl)
261 261
     {
262
-      fclose (fp);
263 262
       if (!n_errors)
264 263
 	{
265
-	  if (!genhash (&pfs->cns, fn, n_clients))
264
+	  if (!genhash (&pfs->cns, prefix, n_clients))
266 265
 	    ++n_errors;
267 266
 	}
268 267
       if (n_errors)
269
-	msg (D_PF, "PF: %s rejected due to %d error(s)", fn, n_errors);
268
+	msg (D_PF_INFO, "PF: %s rejected due to %d error(s)", prefix, n_errors);
270 269
     }
271 270
   if (n_errors)
272 271
     {
... ...
@@ -276,15 +288,32 @@ pf_init (const char *fn)
276 276
   return pfs;
277 277
   
278 278
  kill:
279
-  if (fp)
280
-    fclose (fp);
281 279
   pf_destroy (pfs);
282 280
   ALLOC_OBJ_CLEAR (pfs, struct pf_set);
283 281
   pfs->kill = true;
284 282
   return pfs;
285 283
 }
286 284
 
287
-#if PF_DEBUG >= 1
285
+#ifdef PLUGIN_PF
286
+static struct pf_set *
287
+pf_init_from_file (const char *fn)
288
+{
289
+  struct buffer_list *bl = buffer_list_file (fn, PF_MAX_LINE_LEN);
290
+  if (bl)
291
+    {
292
+      struct pf_set *pfs = pf_init (bl, fn, true);
293
+      buffer_list_free (bl);
294
+      return pfs;
295
+    }
296
+  else
297
+    {
298
+      msg (D_PF_INFO|M_ERRNO, "PF: %s: cannot open", fn);
299
+      return NULL;
300
+    }
301
+}
302
+#endif
303
+
304
+#ifdef ENABLE_DEBUG
288 305
 
289 306
 static const char *
290 307
 drop_accept (const bool accept)
... ...
@@ -292,31 +321,46 @@ drop_accept (const bool accept)
292 292
   return accept ? "ACCEPT" : "DROP"; 
293 293
 }
294 294
 
295
-#endif
296
-
297
-#if PF_DEBUG >= 2
295
+static const char *
296
+pct_name (const int type)
297
+{
298
+  switch (type)
299
+    {
300
+    case PCT_SRC:
301
+      return "SRC";
302
+    case PCT_DEST:
303
+      return "DEST";
304
+    default:
305
+      return "???";
306
+    }
307
+}
298 308
 
299 309
 static void
300 310
 pf_cn_test_print (const char *prefix,
311
+		  const int type,
312
+		  const char *prefix2,
301 313
 		  const char *cn,
302 314
 		  const bool allow,
303 315
 		  const struct pf_cn *rule)
304 316
 {
305 317
   if (rule)
306 318
     {
307
-      msg (D_PF, "PF: %s %s %s rule=[%s %s]",
308
-	   prefix, cn, drop_accept (allow),
319
+      dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s rule=[%s %s]",
320
+	   prefix, prefix2, pct_name (type),
321
+	   cn, drop_accept (allow),
309 322
 	   rule->cn, drop_accept (!rule->exclude));
310 323
     }
311 324
   else
312 325
     {
313
-      msg (D_PF, "PF: %s %s %s",
314
-	   prefix, cn, drop_accept (allow));
326
+      dmsg (D_PF_DEBUG, "PF: %s/%s/%s %s %s",
327
+	   prefix, prefix2, pct_name (type),
328
+	   cn, drop_accept (allow));
315 329
     }
316 330
 }
317 331
 
318 332
 static void
319 333
 pf_addr_test_print (const char *prefix,
334
+		    const char *prefix2,
320 335
 		    const struct context *src,
321 336
 		    const struct mroute_addr *dest,
322 337
 		    const bool allow,
... ...
@@ -325,10 +369,11 @@ pf_addr_test_print (const char *prefix,
325 325
   struct gc_arena gc = gc_new ();
326 326
   if (rule)
327 327
     {
328
-      msg (D_PF, "PF: %s %s %s %s rule=[%s/%s %s]",
328
+      dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
329 329
 	   prefix,
330
+	   prefix2,
330 331
 	   tls_common_name (src->c2.tls_multi, false),
331
-	   mroute_addr_print (dest, &gc),
332
+	   mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc),
332 333
 	   drop_accept (allow),
333 334
 	   print_in_addr_t (rule->network, 0, &gc),
334 335
 	   print_in_addr_t (rule->netmask, 0, &gc),
... ...
@@ -336,10 +381,11 @@ pf_addr_test_print (const char *prefix,
336 336
     }
337 337
   else
338 338
     {
339
-      msg (D_PF, "PF: %s %s %s %s",
339
+      dmsg (D_PF_DEBUG, "PF: %s/%s %s %s %s",
340 340
 	   prefix,
341
+	   prefix2,
341 342
 	   tls_common_name (src->c2.tls_multi, false),
342
-	   mroute_addr_print (dest, &gc),
343
+	   mroute_addr_print_ex (dest, MAPF_SHOW_ARP, &gc),
343 344
 	   drop_accept (allow));
344 345
     }
345 346
   gc_free (&gc);
... ...
@@ -357,8 +403,8 @@ lookup_cn_rule (struct hash *h, const char *cn, const uint32_t cn_hash)
357 357
     return NULL;
358 358
 }
359 359
 
360
-static inline bool
361
-cn_test (struct pf_set *pfs, const struct tls_multi *tm)
360
+bool
361
+pf_cn_test (struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix)
362 362
 {
363 363
   if (!pfs->kill)
364 364
     {
... ...
@@ -369,8 +415,9 @@ cn_test (struct pf_set *pfs, const struct tls_multi *tm)
369 369
 	  const struct pf_cn *rule = lookup_cn_rule (pfs->cns.hash_table, cn, cn_hash);
370 370
 	  if (rule)
371 371
 	    {
372
-#if PF_DEBUG >= 2
373
-	      pf_cn_test_print ("PF_CN_MATCH", cn, !rule->exclude, rule);
372
+#ifdef ENABLE_DEBUG
373
+	      if (check_debug_level (D_PF_DEBUG))
374
+		pf_cn_test_print ("PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule);
374 375
 #endif
375 376
 	      if (!rule->exclude)
376 377
 		return true;
... ...
@@ -379,8 +426,9 @@ cn_test (struct pf_set *pfs, const struct tls_multi *tm)
379 379
 	    }
380 380
 	  else
381 381
 	    {
382
-#if PF_DEBUG >= 2
383
-	      pf_cn_test_print ("PF_CN_DEFAULT", cn, pfs->cns.default_allow, NULL);
382
+#ifdef ENABLE_DEBUG
383
+	      if (check_debug_level (D_PF_DEBUG))
384
+		pf_cn_test_print ("PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL);
384 385
 #endif
385 386
 	      if (pfs->cns.default_allow)
386 387
 		return true;
... ...
@@ -389,59 +437,50 @@ cn_test (struct pf_set *pfs, const struct tls_multi *tm)
389 389
 	    }
390 390
 	}
391 391
     }
392
-#if PF_DEBUG >= 2
393
-  pf_cn_test_print ("PF_CN_FAULT", tls_common_name (tm, false), false, NULL);
392
+#ifdef ENABLE_DEBUG
393
+  if (check_debug_level (D_PF_DEBUG))
394
+    pf_cn_test_print ("PF_CN_FAULT", type, prefix, tls_common_name (tm, false), false, NULL);
394 395
 #endif
395 396
   return false;
396 397
 }
397 398
 
398 399
 bool
399
-pf_c2c_test (const struct context *src, const struct context *dest)
400
+pf_addr_test_dowork (const struct context *src, const struct mroute_addr *dest, const char *prefix)
400 401
 {
401
-  return  (!src->c2.pf.filename  || cn_test (src->c2.pf.pfs,  dest->c2.tls_multi))
402
-       && (!dest->c2.pf.filename || cn_test (dest->c2.pf.pfs, src->c2.tls_multi));
403
-}
404
-
405
-bool
406
-pf_addr_test (const struct context *src, const struct mroute_addr *dest)
407
-{
408
-  if (src->c2.pf.filename)
402
+  struct pf_set *pfs = src->c2.pf.pfs;
403
+  if (pfs && !pfs->kill)
409 404
     {
410
-      struct pf_set *pfs = src->c2.pf.pfs;
411
-      if (pfs && !pfs->kill)
405
+      const in_addr_t addr = in_addr_t_from_mroute_addr (dest);
406
+      const struct pf_subnet *se = pfs->sns.list;
407
+      while (se)
412 408
 	{
413
-	  const in_addr_t addr = in_addr_t_from_mroute_addr (dest);
414
-	  const struct pf_subnet *se = pfs->sns.list;
415
-	  while (se)
409
+	  if ((addr & se->rule.netmask) == se->rule.network)
416 410
 	    {
417
-	      if ((addr & se->rule.netmask) == se->rule.network)
418
-		{
419
-#if PF_DEBUG >= 2
420
-		  pf_addr_test_print ("PF_ADDR_MATCH", src, dest, !se->rule.exclude, &se->rule);
411
+#ifdef ENABLE_DEBUG
412
+	      if (check_debug_level (D_PF_DEBUG))
413
+		pf_addr_test_print ("PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule);
421 414
 #endif
422
-		  return !se->rule.exclude;
423
-		}
424
-	      se = se->next;
415
+	      return !se->rule.exclude;
425 416
 	    }
426
-#if PF_DEBUG >= 2
427
-	  pf_addr_test_print ("PF_ADDR_DEFAULT", src, dest, pfs->sns.default_allow, NULL);
428
-#endif
429
-	  return pfs->sns.default_allow;
417
+	  se = se->next;
430 418
 	}
431
-      else
432
-	{
433
-#if PF_DEBUG >= 2
434
-	  pf_addr_test_print ("PF_ADDR_FAULT", src, dest, false, NULL);
419
+#ifdef ENABLE_DEBUG
420
+      if (check_debug_level (D_PF_DEBUG))
421
+	pf_addr_test_print ("PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL);
435 422
 #endif
436
-	  return false;
437
-	}
423
+      return pfs->sns.default_allow;
438 424
     }
439 425
   else
440 426
     {
441
-      return true;
427
+#ifdef ENABLE_DEBUG
428
+      if (check_debug_level (D_PF_DEBUG))
429
+	pf_addr_test_print ("PF_ADDR_FAULT", prefix, src, dest, false, NULL);
430
+#endif
431
+      return false;
442 432
     }
443 433
 }
444 434
 
435
+#ifdef PLUGIN_PF
445 436
 void
446 437
 pf_check_reload (struct context *c)
447 438
 {
... ...
@@ -450,14 +489,16 @@ pf_check_reload (struct context *c)
450 450
   const int wakeup_transition = 60;
451 451
   bool reloaded = false;
452 452
 
453
-  if (c->c2.pf.filename && event_timeout_trigger (&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT))
453
+  if (c->c2.pf.enabled
454
+      && c->c2.pf.filename
455
+      && event_timeout_trigger (&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT))
454 456
     {
455 457
       struct stat s;
456 458
       if (!stat (c->c2.pf.filename, &s))
457 459
 	{
458 460
 	  if (s.st_mtime > c->c2.pf.file_last_mod)
459 461
 	    {
460
-	      struct pf_set *pfs = pf_init (c->c2.pf.filename);
462
+	      struct pf_set *pfs = pf_init_from_file (c->c2.pf.filename);
461 463
 	      if (pfs)
462 464
 		{
463 465
 		  if (c->c2.pf.pfs)
... ...
@@ -482,16 +523,35 @@ pf_check_reload (struct context *c)
482 482
 	c->c2.pf.n_check_reload++;
483 483
       }
484 484
     }
485
-#if PF_DEBUG >= 1
486
-  if (reloaded)
487
-    pf_context_print (&c->c2.pf, "pf_check_reload", M_INFO);
485
+#ifdef ENABLE_DEBUG
486
+  if (reloaded && check_debug_level (D_PF_DEBUG))
487
+    pf_context_print (&c->c2.pf, "pf_check_reload", D_PF_DEBUG);
488 488
 #endif
489 489
 }
490
+#endif
491
+
492
+#ifdef MANAGEMENT_PF
493
+bool
494
+pf_load_from_buffer_list (struct context *c, const struct buffer_list *config)
495
+{
496
+  struct pf_set *pfs = pf_init (config, "[SERVER-PF]", false);
497
+  if (pfs)
498
+    {
499
+      if (c->c2.pf.pfs)
500
+	pf_destroy (c->c2.pf.pfs);
501
+      c->c2.pf.pfs = pfs;
502
+      return true;
503
+    }
504
+  else
505
+    return false;
506
+}
507
+#endif
490 508
 
491 509
 void
492 510
 pf_init_context (struct context *c)
493 511
 {
494 512
   struct gc_arena gc = gc_new ();
513
+#ifdef PLUGIN_PF
495 514
   if (plugin_defined (c->plugins, OPENVPN_PLUGIN_ENABLE_PF))
496 515
     {
497 516
       const char *pf_file = create_temp_filename (c->options.tmp_dir, "pf", &gc);
... ...
@@ -502,8 +562,10 @@ pf_init_context (struct context *c)
502 502
 	{
503 503
 	  event_timeout_init (&c->c2.pf.reload, 1, now);
504 504
 	  c->c2.pf.filename = string_alloc (pf_file, NULL);
505
-#if PF_DEBUG >= 1
506
-	  pf_context_print (&c->c2.pf, "pf_init_context", M_INFO);
505
+	  c->c2.pf.enabled = true;
506
+#ifdef ENABLE_DEBUG
507
+	  if (check_debug_level (D_PF_DEBUG))
508
+	    pf_context_print (&c->c2.pf, "pf_init_context#1", D_PF_DEBUG);
507 509
 #endif
508 510
 	}
509 511
       else
... ...
@@ -511,22 +573,35 @@ pf_init_context (struct context *c)
511 511
 	  msg (M_WARN, "WARNING: OPENVPN_PLUGIN_ENABLE_PF disabled");
512 512
 	}
513 513
     }
514
+#endif
515
+#ifdef MANAGEMENT_PF
516
+  if (!c->c2.pf.enabled && management_enable_pf (management))
517
+    {
518
+      c->c2.pf.enabled = true;
519
+#ifdef ENABLE_DEBUG
520
+      if (check_debug_level (D_PF_DEBUG))
521
+	pf_context_print (&c->c2.pf, "pf_init_context#2", D_PF_DEBUG);
522
+#endif
523
+    }
524
+#endif
514 525
   gc_free (&gc);
515 526
 }
516 527
 
517 528
 void
518 529
 pf_destroy_context (struct pf_context *pfc)
519 530
 {
531
+#ifdef PLUGIN_PF
520 532
   if (pfc->filename)
521 533
     {
522 534
       delete_file (pfc->filename);
523 535
       free (pfc->filename);
524 536
     }
537
+#endif
525 538
   if (pfc->pfs)
526 539
     pf_destroy (pfc->pfs);
527 540
 }
528 541
 
529
-#if PF_DEBUG >= 1
542
+#ifdef ENABLE_DEBUG
530 543
 
531 544
 static void
532 545
 pf_subnet_set_print (const struct pf_subnet_set *s, const int lev)
... ...
@@ -613,10 +688,13 @@ pf_context_print (const struct pf_context *pfc, const char *prefix, const int le
613 613
   msg (lev, "----- %s : struct pf_context -----", prefix);
614 614
   if (pfc)
615 615
     {
616
+      msg (lev, "enabled=%d", pfc->enabled);
617
+#ifdef PLUGIN_PF
616 618
       msg (lev, "filename='%s'", np(pfc->filename));
617 619
       msg (lev, "file_last_mod=%u", (unsigned int)pfc->file_last_mod);
618 620
       msg (lev, "n_check_reload=%u", pfc->n_check_reload);
619 621
       msg (lev, "reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (unsigned int)pfc->reload.last);
622
+#endif
620 623
       pf_set_print (pfc->pfs, lev);
621 624
     }
622 625
   msg (lev, "--------------------");
... ...
@@ -30,7 +30,7 @@
30 30
 #include "list.h"
31 31
 #include "mroute.h"
32 32
 
33
-#define PF_DEBUG 0
33
+#define PF_MAX_LINE_LEN 256
34 34
 
35 35
 struct context;
36 36
 
... ...
@@ -73,30 +73,29 @@ struct pf_set {
73 73
 };
74 74
 
75 75
 struct pf_context {
76
+  bool enabled;
77
+  struct pf_set *pfs;
78
+#ifdef PLUGIN_PF
76 79
   char *filename;
77 80
   time_t file_last_mod;
78 81
   unsigned int n_check_reload;
79 82
   struct event_timeout reload;
80
-  struct pf_set *pfs;
83
+#endif
81 84
 };
82 85
 
83 86
 void pf_init_context (struct context *c);
84 87
 
85 88
 void pf_destroy_context (struct pf_context *pfc);
86 89
 
90
+#ifdef PLUGIN_PF
87 91
 void pf_check_reload (struct context *c);
92
+#endif
88 93
 
89
-bool pf_c2c_test (const struct context *src, const struct context *dest);
90
-
91
-bool pf_addr_test (const struct context *src, const struct mroute_addr *dest);
92
-
93
-static inline bool
94
-pf_kill_test (const struct pf_set *pfs)
95
-{
96
-  return pfs->kill;
97
-}
94
+#ifdef MANAGEMENT_PF
95
+bool pf_load_from_buffer_list (struct context *c, const struct buffer_list *config);
96
+#endif
98 97
 
99
-#if PF_DEBUG >= 1
98
+#ifdef ENABLE_DEBUG
100 99
 void pf_context_print (const struct pf_context *pfc, const char *prefix, const int lev);
101 100
 #endif
102 101
 
... ...
@@ -28,6 +28,8 @@
28 28
 #include "common.h"
29 29
 #include "buffer.h"
30 30
 
31
+#pragma pack(1)
32
+
31 33
 /*
32 34
  * Tunnel types
33 35
  */
... ...
@@ -62,6 +64,24 @@ struct openvpn_ethhdr
62 62
   uint16_t proto;                     /* packet type ID field */
63 63
 };
64 64
 
65
+struct openvpn_arp {
66
+# define ARP_MAC_ADDR_TYPE 0x0001
67
+  uint16_t mac_addr_type;       // 0x0001
68
+
69
+  uint16_t proto_addr_type;     // 0x0800
70
+  uint8_t  mac_addr_size;       // 0x06
71
+  uint8_t  proto_addr_size;     // 0x04
72
+
73
+# define ARP_REQUEST 0x0001
74
+# define ARP_REPLY   0x0002
75
+  uint16_t arp_command;         // 0x0001 for ARP request, 0x0002 for ARP reply
76
+
77
+  uint8_t   mac_src[OPENVPN_ETH_ALEN];
78
+  in_addr_t ip_src;
79
+  uint8_t   mac_dest[OPENVPN_ETH_ALEN];
80
+  in_addr_t ip_dest;
81
+};
82
+
65 83
 struct openvpn_iphdr {
66 84
 # define OPENVPN_IPH_GET_VER(v) (((v) >> 4) & 0x0F)
67 85
 # define OPENVPN_IPH_GET_LEN(v) (((v) & 0x0F) << 2)
... ...
@@ -129,6 +149,8 @@ struct openvpn_tcphdr {
129 129
 #define	OPENVPN_TCPOPT_MAXSEG  2
130 130
 #define OPENVPN_TCPOLEN_MAXSEG 4
131 131
 
132
+#pragma pack()
133
+
132 134
 /*
133 135
  * The following macro is used to update an
134 136
  * internet checksum.  "acc" is a 32-bit
... ...
@@ -860,6 +860,26 @@ tls_lock_common_name (struct tls_multi *multi)
860 860
 }
861 861
 
862 862
 #ifdef ENABLE_DEF_AUTH
863
+/* key_state_test_auth_control_file return values,
864
+   NOTE: acf_merge indexing depends on these values */
865
+#define ACF_UNDEFINED 0
866
+#define ACF_SUCCEEDED 1
867
+#define ACF_DISABLED  2
868
+#define ACF_FAILED    3
869
+#endif
870
+
871
+#ifdef MANAGEMENT_DEF_AUTH
872
+static inline unsigned int
873
+man_def_auth_test (const struct key_state *ks)
874
+{
875
+  if (management_enable_def_auth (management))
876
+    return ks->mda_status;
877
+  else
878
+    return ACF_DISABLED;
879
+}
880
+#endif
881
+
882
+#ifdef PLUGIN_DEF_AUTH
863 883
 
864 884
 /*
865 885
  * auth_control_file functions
... ...
@@ -890,17 +910,12 @@ key_state_gen_auth_control_file (struct key_state *ks, const struct tls_options
890 890
   gc_free (&gc);					  
891 891
 }
892 892
 
893
-/* key_state_test_auth_control_file return values */
894
-#define ACF_UNDEFINED 0
895
-#define ACF_SUCCEEDED 1
896
-#define ACF_DISABLED  2
897
-#define ACF_FAILED    3
898
-static int
893
+static unsigned int
899 894
 key_state_test_auth_control_file (struct key_state *ks)
900 895
 {
901 896
   if (ks && ks->auth_control_file)
902 897
     {
903
-      int ret = ks->auth_control_status;
898
+      unsigned int ret = ks->auth_control_status;
904 899
       if (ret == ACF_UNDEFINED)
905 900
 	{
906 901
 	  FILE *fp = fopen (ks->auth_control_file, "r");
... ...
@@ -935,14 +950,37 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
935 935
   bool active = false;
936 936
 
937 937
 #ifdef ENABLE_DEF_AUTH
938
-  if (latency && multi->tas_last && multi->tas_last + latency >= now)
939
-    return TLS_AUTHENTICATION_UNDEFINED;
940
-  multi->tas_last = now;
938
+  static const unsigned char acf_merge[] =
939
+    {
940
+      ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_UNDEFINED */
941
+      ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_SUCCEEDED */
942
+      ACF_UNDEFINED, /* s1=ACF_UNDEFINED s2=ACF_DISABLED */
943
+      ACF_FAILED,    /* s1=ACF_UNDEFINED s2=ACF_FAILED */
944
+      ACF_UNDEFINED, /* s1=ACF_SUCCEEDED s2=ACF_UNDEFINED */
945
+      ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_SUCCEEDED */
946
+      ACF_SUCCEEDED, /* s1=ACF_SUCCEEDED s2=ACF_DISABLED */
947
+      ACF_FAILED,    /* s1=ACF_SUCCEEDED s2=ACF_FAILED */
948
+      ACF_UNDEFINED, /* s1=ACF_DISABLED  s2=ACF_UNDEFINED */
949
+      ACF_SUCCEEDED, /* s1=ACF_DISABLED  s2=ACF_SUCCEEDED */
950
+      ACF_DISABLED,  /* s1=ACF_DISABLED  s2=ACF_DISABLED */
951
+      ACF_FAILED,    /* s1=ACF_DISABLED  s2=ACF_FAILED */
952
+      ACF_FAILED,    /* s1=ACF_FAILED    s2=ACF_UNDEFINED */
953
+      ACF_FAILED,    /* s1=ACF_FAILED    s2=ACF_SUCCEEDED */
954
+      ACF_FAILED,    /* s1=ACF_FAILED    s2=ACF_DISABLED */
955
+      ACF_FAILED     /* s1=ACF_FAILED    s2=ACF_FAILED */
956
+    };
941 957
 #endif
942 958
 
943 959
   if (multi)
944 960
     {
945 961
       int i;
962
+
963
+#ifdef ENABLE_DEF_AUTH
964
+      if (latency && multi->tas_last && multi->tas_last + latency >= now)
965
+	return TLS_AUTHENTICATION_UNDEFINED;
966
+      multi->tas_last = now;
967
+#endif
968
+
946 969
       for (i = 0; i < KEY_SCAN_SIZE; ++i)
947 970
 	{
948 971
 	  struct key_state *ks = multi->key_scan[i];
... ...
@@ -952,7 +990,16 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
952 952
 	      if (ks->authenticated)
953 953
 		{
954 954
 #ifdef ENABLE_DEF_AUTH
955
-		  switch (key_state_test_auth_control_file (ks))
955
+		  unsigned int s1 = ACF_DISABLED;
956
+		  unsigned int s2 = ACF_DISABLED;
957
+#ifdef PLUGIN_DEF_AUTH
958
+		  s1 = key_state_test_auth_control_file (ks); 
959
+#endif
960
+#ifdef MANAGEMENT_DEF_AUTH
961
+		  s2 = man_def_auth_test (ks);
962
+#endif
963
+		  ASSERT (s1 < 4 && s2 < 4);
964
+		  switch (acf_merge[(s1<<2) + s2])
956 965
 		    {
957 966
 		    case ACF_SUCCEEDED:
958 967
 		    case ACF_DISABLED:
... ...
@@ -989,6 +1036,28 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
989 989
     return TLS_AUTHENTICATION_FAILED;
990 990
 }
991 991
 
992
+#ifdef MANAGEMENT_DEF_AUTH
993
+bool
994
+tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth)
995
+{
996
+  bool ret = false;
997
+  if (multi)
998
+    {
999
+      int i;
1000
+      for (i = 0; i < KEY_SCAN_SIZE; ++i)
1001
+	{
1002
+	  struct key_state *ks = multi->key_scan[i];
1003
+	  if (ks->mda_key_id == mda_key_id)
1004
+	    {
1005
+	      ks->mda_status = auth ? ACF_SUCCEEDED : ACF_FAILED;
1006
+	      ret = true;
1007
+	    }
1008
+	}
1009
+    }
1010
+  return ret;
1011
+}
1012
+#endif
1013
+
992 1014
 void
993 1015
 tls_deauthenticate (struct tls_multi *multi)
994 1016
 {
... ...
@@ -1458,7 +1527,7 @@ init_ssl (const struct options *options)
1458 1458
 #if P2MP_SERVER
1459 1459
   if (options->client_cert_not_required)
1460 1460
     {
1461
-      msg (M_WARN, "WARNING: This configuration may accept clients which do not present a certificate");
1461
+      msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION --client-cert-not-required may accept clients which do not present a certificate");
1462 1462
     }
1463 1463
   else
1464 1464
 #endif
... ...
@@ -1976,6 +2045,10 @@ key_state_init (struct tls_session *session, struct key_state *ks)
1976 1976
   packet_id_init (&ks->packet_id,
1977 1977
 		  session->opt->replay_window,
1978 1978
 		  session->opt->replay_time);
1979
+
1980
+#ifdef MANAGEMENT_DEF_AUTH
1981
+  ks->mda_key_id = session->opt->mda_context->mda_key_id_counter++;
1982
+#endif
1979 1983
 }
1980 1984
 
1981 1985
 static void
... ...
@@ -2018,7 +2091,7 @@ key_state_free (struct key_state *ks, bool clear)
2018 2018
 
2019 2019
   packet_id_free (&ks->packet_id);
2020 2020
 
2021
-#ifdef ENABLE_DEF_AUTH
2021
+#ifdef PLUGIN_DEF_AUTH
2022 2022
   key_state_rm_auth_control_file (ks);
2023 2023
 #endif
2024 2024
 
... ...
@@ -2933,7 +3006,7 @@ verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up
2933 2933
       /* setenv client real IP address */
2934 2934
       setenv_untrusted (session);
2935 2935
 
2936
-#ifdef ENABLE_DEF_AUTH
2936
+#ifdef PLUGIN_DEF_AUTH
2937 2937
       /* generate filename for deferred auth control file */
2938 2938
       key_state_gen_auth_control_file (ks, session->opt);
2939 2939
 #endif
... ...
@@ -2941,7 +3014,7 @@ verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up
2941 2941
       /* call command */
2942 2942
       retval = plugin_call (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, NULL, NULL, session->opt->es);
2943 2943
 
2944
-#ifdef ENABLE_DEF_AUTH
2944
+#ifdef PLUGIN_DEF_AUTH
2945 2945
       /* purge auth control filename (and file itself) for non-deferred returns */
2946 2946
       if (retval != OPENVPN_PLUGIN_FUNC_DEFERRED)
2947 2947
 	key_state_rm_auth_control_file (ks);
... ...
@@ -2952,13 +3025,57 @@ verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up
2952 2952
     }
2953 2953
   else
2954 2954
     {
2955
-      msg (D_TLS_ERRORS, "TLS Auth Error: peer provided a blank username");
2955
+      msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_plugin): peer provided a blank username");
2956 2956
     }
2957 2957
 
2958 2958
   return retval;
2959 2959
 }
2960 2960
 
2961 2961
 /*
2962
+ * MANAGEMENT_DEF_AUTH internal ssl.c status codes
2963
+ */
2964
+#define KMDA_ERROR   0
2965
+#define KMDA_SUCCESS 1
2966
+#define KMDA_UNDEF   2
2967
+#define KMDA_DEF     3
2968
+
2969
+#ifdef MANAGEMENT_DEF_AUTH
2970
+static int
2971
+verify_user_pass_management (struct tls_session *session, const struct user_pass *up, const char *raw_username)
2972
+{
2973
+  int retval = KMDA_ERROR;
2974
+
2975
+  /* Is username defined? */
2976
+  if (strlen (up->username))
2977
+    {
2978
+      /* set username/password in private env space */
2979
+      setenv_str (session->opt->es, "username", raw_username);
2980
+      setenv_str (session->opt->es, "password", up->password);
2981
+
2982
+      /* setenv incoming cert common name for script */
2983
+      setenv_str (session->opt->es, "common_name", session->common_name);
2984
+
2985
+      /* setenv client real IP address */
2986
+      setenv_untrusted (session);
2987
+
2988
+      if (management)
2989
+	management_notify_client_needing_auth (management, ks->mda_key_id, session->opt->mda_context, session->opt->es);
2990
+
2991
+      setenv_del (session->opt->es, "password");
2992
+      setenv_str (session->opt->es, "username", up->username);
2993
+
2994
+      retval = KMDA_SUCCESS;
2995
+    }
2996
+  else
2997
+    {
2998
+      msg (D_TLS_ERRORS, "TLS Auth Error (verify_user_pass_management): peer provided a blank username");
2999
+    }
3000
+
3001
+  return retval;
3002
+}
3003
+#endif
3004
+
3005
+/*
2962 3006
  * Handle the reading and writing of key data to and from
2963 3007
  * the TLS control channel (cleartext).
2964 3008
  */
... ...
@@ -3134,6 +3251,13 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3134 3134
   char *options;
3135 3135
   struct user_pass *up;
3136 3136
 
3137
+  bool man_def_auth = KMDA_UNDEF;
3138
+
3139
+#ifdef MANAGEMENT_DEF_AUTH
3140
+  if (management_enable_def_auth (management))
3141
+    man_def_auth = KMDA_DEF;
3142
+#endif
3143
+
3137 3144
   ASSERT (session->opt->key_method == 2);
3138 3145
 
3139 3146
   /* allocate temporary objects */
... ...
@@ -3169,7 +3293,8 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3169 3169
   /* should we check username/password? */
3170 3170
   ks->authenticated = false;
3171 3171
   if (session->opt->auth_user_pass_verify_script
3172
-      || plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY))
3172
+      || plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
3173
+      || man_def_auth == KMDA_DEF)
3173 3174
     {
3174 3175
       int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS;
3175 3176
       bool s2 = true;
... ...
@@ -3195,6 +3320,10 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3195 3195
       string_mod (up->password, CC_PRINT, CC_CRLF, '_');
3196 3196
 
3197 3197
       /* call plugin(s) and/or script */
3198
+#ifdef MANAGEMENT_DEF_AUTH
3199
+      if (man_def_auth == KMDA_DEF)
3200
+	man_def_auth = verify_user_pass_management (session, up, raw_username);
3201
+#endif
3198 3202
       if (plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY))
3199 3203
 	s1 = verify_user_pass_plugin (session, up, raw_username);
3200 3204
       if (session->opt->auth_user_pass_verify_script)
... ...
@@ -3202,16 +3331,21 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3202 3202
       
3203 3203
       /* auth succeeded? */
3204 3204
       if ((s1 == OPENVPN_PLUGIN_FUNC_SUCCESS
3205
-#ifdef ENABLE_DEF_AUTH
3205
+#ifdef PLUGIN_DEF_AUTH
3206 3206
 	   || s1 == OPENVPN_PLUGIN_FUNC_DEFERRED
3207 3207
 #endif
3208
-	   ) && s2)
3208
+	   ) && s2 && man_def_auth != KMDA_ERROR)
3209 3209
 	{
3210 3210
 	  ks->authenticated = true;
3211
-#ifdef ENABLE_DEF_AUTH
3211
+#ifdef PLUGIN_DEF_AUTH
3212 3212
 	  if (s1 == OPENVPN_PLUGIN_FUNC_DEFERRED)
3213 3213
 	    ks->auth_deferred = true;
3214 3214
 #endif
3215
+#ifdef MANAGEMENT_DEF_AUTH
3216
+	  if (man_def_auth != KMDA_UNDEF)
3217
+	    ks->auth_deferred = true;
3218
+#endif
3219
+	    
3215 3220
 	  if (session->opt->username_as_common_name)
3216 3221
 	    set_common_name (session, up->username);
3217 3222
 	  msg (D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s",
... ...
@@ -375,9 +375,15 @@ struct key_state
375 375
 #ifdef ENABLE_DEF_AUTH
376 376
   /* If auth_deferred is true, authentication is being deferred */
377 377
   bool auth_deferred;
378
+#ifdef MANAGEMENT_DEF_AUTH
379
+  unsigned int mda_key_id;
380
+  unsigned int mda_status;
381
+#endif
382
+#ifdef PLUGIN_DEF_AUTH
383
+  unsigned int auth_control_status;
378 384
   time_t acf_last_mod;
379 385
   char *auth_control_file;
380
-  int auth_control_status;
386
+#endif
381 387
 #endif
382 388
 };
383 389
 
... ...
@@ -459,6 +465,10 @@ struct tls_options
459 459
   struct env_set *es;
460 460
   const struct plugin_list *plugins;
461 461
 
462
+#ifdef MANAGEMENT_DEF_AUTH
463
+  struct man_def_auth_context *mda_context;
464
+#endif
465
+
462 466
   /* --gremlin bits */
463 467
   int gremlin;
464 468
 };
... ...
@@ -679,6 +689,10 @@ void tls_lock_common_name (struct tls_multi *multi);
679 679
 int tls_authentication_status (struct tls_multi *multi, const int latency);
680 680
 void tls_deauthenticate (struct tls_multi *multi);
681 681
 
682
+#ifdef MANAGEMENT_DEF_AUTH
683
+bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth);
684
+#endif
685
+
682 686
 /*
683 687
  * inline functions
684 688
  */
... ...
@@ -471,20 +471,41 @@ socket_defined (const socket_descriptor_t sd)
471 471
 #endif
472 472
 
473 473
 /*
474
- * Enable deferred authentication
474
+ * Enable deferred authentication?
475 475
  */
476
-#if defined(ENABLE_PLUGIN) && P2MP_SERVER
476
+#define CONFIGURE_DEF_AUTH /* this should be set by autoconf and config.h */
477
+#if defined(CONFIGURE_DEF_AUTH) && defined(P2MP_SERVER) && defined(ENABLE_PLUGIN)
478
+#define PLUGIN_DEF_AUTH
479
+#endif
480
+#if defined(CONFIGURE_DEF_AUTH) && defined(P2MP_SERVER) && defined(ENABLE_MANAGEMENT)
481
+#define MANAGEMENT_DEF_AUTH
482
+#endif
483
+#if defined(PLUGIN_DEF_AUTH) || defined(MANAGEMENT_DEF_AUTH)
477 484
 #define ENABLE_DEF_AUTH
478 485
 #endif
479 486
 
480 487
 /*
481
- * Enable packet filter
488
+ * Enable packet filter?
482 489
  */
483
-#if defined(ENABLE_PLUGIN) && P2MP_SERVER && defined(HAVE_STAT)
490
+#define CONFIGURE_PF /* this should be set by autoconf and config.h */
491
+#if defined(CONFIGURE_PF) && defined(P2MP_SERVER) && defined(ENABLE_PLUGIN) && defined(HAVE_STAT)
492
+#define PLUGIN_PF
493
+#endif
494
+#if defined(CONFIGURE_PF) && defined(P2MP_SERVER) && defined(MANAGEMENT_DEF_AUTH)
495
+#define MANAGEMENT_PF
496
+#endif
497
+#if defined(PLUGIN_PF) || defined(MANAGEMENT_PF)
484 498
 #define ENABLE_PF
485 499
 #endif
486 500
 
487 501
 /*
502
+ * Don't compile the struct buffer_list code unless something needs it
503
+ */
504
+#if defined(ENABLE_MANAGEMENT) || defined(ENABLE_PF)
505
+#define ENABLE_BUFFER_LIST
506
+#endif
507
+
508
+/*
488 509
  * Do we have pthread capability?
489 510
  */
490 511
 #ifdef USE_PTHREAD
... ...
@@ -1248,7 +1248,7 @@ close_tun (struct tuntap *tt)
1248 1248
 #endif
1249 1249
 
1250 1250
 	    msg (M_INFO, "%s", command_line);
1251
-	    system_check (command_line, NULL, S_FATAL, "Linux ip addr del failed");
1251
+	    system_check (command_line, NULL, 0, "Linux ip addr del failed");
1252 1252
 
1253 1253
 	    gc_free (&gc);
1254 1254
 	  }
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc7d])
2
+define(PRODUCT_VERSION,[2.1_rc7e])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])