OpenVPN
simple.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * This file implements a simple OpenVPN plugin module which
26  * will test deferred authentication and packet filtering.
27  *
28  * Will run on Windows or *nix.
29  *
30  * Sample usage:
31  *
32  * setenv test_deferred_auth 20
33  * setenv test_packet_filter 10
34  * plugin plugin/defer/simple.so
35  *
36  * This will enable deferred authentication to occur 20
37  * seconds after the normal TLS authentication process,
38  * and will cause a packet filter file to be generated 10
39  * seconds after the initial TLS negotiation, using
40  * {common-name}.pf as the source.
41  *
42  * Sample packet filter configuration:
43  *
44  * [CLIENTS DROP]
45  * +otherclient
46  * [SUBNETS DROP]
47  * +10.0.0.0/8
48  * -10.10.0.8
49  * [END]
50  *
51  * See the README file for build instructions.
52  */
53 
54 #include <stdio.h>
55 #include <string.h>
56 #include <stdlib.h>
57 
58 #include "openvpn-plugin.h"
59 
60 /* bool definitions */
61 #define bool int
62 #define true 1
63 #define false 0
64 
65 /*
66  * Our context, where we keep our state.
67  */
68 
72 };
73 
75  int n_calls;
77 };
78 
79 /*
80  * Given an environmental variable name, search
81  * the envp array for its value, returning it
82  * if found or NULL otherwise.
83  */
84 static const char *
85 get_env(const char *name, const char *envp[])
86 {
87  if (envp)
88  {
89  int i;
90  const int namelen = strlen(name);
91  for (i = 0; envp[i]; ++i)
92  {
93  if (!strncmp(envp[i], name, namelen))
94  {
95  const char *cp = envp[i] + namelen;
96  if (*cp == '=')
97  {
98  return cp + 1;
99  }
100  }
101  }
102  }
103  return NULL;
104 }
105 
106 /* used for safe printf of possible NULL strings */
107 static const char *
108 np(const char *str)
109 {
110  if (str)
111  {
112  return str;
113  }
114  else
115  {
116  return "[NULL]";
117  }
118 }
119 
120 static int
121 atoi_null0(const char *str)
122 {
123  if (str)
124  {
125  return atoi(str);
126  }
127  else
128  {
129  return 0;
130  }
131 }
132 
134 openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
135 {
136  struct plugin_context *context;
137 
138  printf("FUNC: openvpn_plugin_open_v1\n");
139 
140  /*
141  * Allocate our context
142  */
143  context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
144 
145  context->test_deferred_auth = atoi_null0(get_env("test_deferred_auth", envp));
146  printf("TEST_DEFERRED_AUTH %d\n", context->test_deferred_auth);
147 
148  context->test_packet_filter = atoi_null0(get_env("test_packet_filter", envp));
149  printf("TEST_PACKET_FILTER %d\n", context->test_packet_filter);
150 
151  /*
152  * Which callbacks to intercept.
153  */
154  *type_mask =
166 
167  return (openvpn_plugin_handle_t) context;
168 }
169 
170 static int
171 auth_user_pass_verify(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
172 {
173  if (context->test_deferred_auth)
174  {
175  /* get username/password from envp string array */
176  const char *username = get_env("username", envp);
177  const char *password = get_env("password", envp);
178 
179  /* get auth_control_file filename from envp string array*/
180  const char *auth_control_file = get_env("auth_control_file", envp);
181 
182  printf("DEFER u='%s' p='%s' acf='%s'\n",
183  np(username),
184  np(password),
185  np(auth_control_file));
186 
187  /* Authenticate asynchronously in n seconds */
188  if (auth_control_file)
189  {
190  char buf[256];
191  int auth = 2;
192  sscanf(username, "%d", &auth);
193  snprintf(buf, sizeof(buf), "( sleep %d ; echo AUTH %s %d ; echo %d >%s ) &",
194  context->test_deferred_auth,
195  auth_control_file,
196  auth,
197  pcc->n_calls < auth,
198  auth_control_file);
199  printf("%s\n", buf);
200  system(buf);
201  pcc->n_calls++;
203  }
204  else
205  {
207  }
208  }
209  else
210  {
212  }
213 }
214 
215 static int
216 tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
217 {
218  if (context->test_packet_filter)
219  {
220  if (!pcc->generated_pf_file)
221  {
222  const char *pff = get_env("pf_file", envp);
223  const char *cn = get_env("username", envp);
224  if (pff && cn)
225  {
226  char buf[256];
227  snprintf(buf, sizeof(buf), "( sleep %d ; echo PF %s/%s ; cp \"%s.pf\" \"%s\" ) &",
228  context->test_packet_filter, cn, pff, cn, pff);
229  printf("%s\n", buf);
230  system(buf);
231  pcc->generated_pf_file = true;
233  }
234  else
235  {
237  }
238  }
239  else
240  {
242  }
243  }
244  else
245  {
247  }
248 }
249 
250 OPENVPN_EXPORT int
252  const int type,
253  const char *argv[],
254  const char *envp[],
255  void *per_client_context,
256  struct openvpn_plugin_string_list **return_list)
257 {
258  struct plugin_context *context = (struct plugin_context *) handle;
259  struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
260  switch (type)
261  {
262  case OPENVPN_PLUGIN_UP:
263  printf("OPENVPN_PLUGIN_UP\n");
265 
266  case OPENVPN_PLUGIN_DOWN:
267  printf("OPENVPN_PLUGIN_DOWN\n");
269 
271  printf("OPENVPN_PLUGIN_ROUTE_UP\n");
273 
275  printf("OPENVPN_PLUGIN_IPCHANGE\n");
277 
279  printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
281 
283  printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
284  return auth_user_pass_verify(context, pcc, argv, envp);
285 
287  printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
289 
291  printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
293 
295  printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
297 
299  printf("OPENVPN_PLUGIN_TLS_FINAL\n");
300  return tls_final(context, pcc, argv, envp);
301 
303  printf("OPENVPN_PLUGIN_ENABLE_PF\n");
304  if (context->test_packet_filter)
305  {
307  }
308  else
309  {
311  }
312 
313  default:
314  printf("OPENVPN_PLUGIN_?\n");
316  }
317 }
318 
319 OPENVPN_EXPORT void *
321 {
322  printf("FUNC: openvpn_plugin_client_constructor_v1\n");
323  return calloc(1, sizeof(struct plugin_per_client_context));
324 }
325 
326 OPENVPN_EXPORT void
328 {
329  printf("FUNC: openvpn_plugin_client_destructor_v1\n");
330  free(per_client_context);
331 }
332 
333 OPENVPN_EXPORT void
335 {
336  struct plugin_context *context = (struct plugin_context *) handle;
337  printf("FUNC: openvpn_plugin_close_v1\n");
338  free(context);
339 }
OPENVPN_EXPORT void openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *per_client_context)
Definition: simple.c:327
static const char * get_env(const char *name, const char *envp[])
Definition: simple.c:85
static int auth_user_pass_verify(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
Definition: simple.c:171
const char * password
Definition: log.c:42
Contains all state information for one tunnel.
Definition: openvpn.h:500
#define OPENVPN_PLUGIN_DOWN
#define OPENVPN_PLUGIN_ROUTE_UP
OPENVPN_EXPORT openvpn_plugin_handle_t openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
Definition: simple.c:134
int test_deferred_auth
Definition: simple.c:70
#define OPENVPN_EXPORT
#define OPENVPN_PLUGIN_ENABLE_PF
#define OPENVPN_PLUGIN_FUNC_SUCCESS
#define snprintf
Definition: config-msvc.h:97
#define OPENVPN_PLUGIN_LEARN_ADDRESS
const char * username
Definition: log.c:41
#define OPENVPN_PLUGIN_IPCHANGE
static int tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
Definition: simple.c:216
#define OPENVPN_PLUGIN_FUNC_DEFERRED
#define OPENVPN_PLUGIN_TLS_VERIFY
#define OPENVPN_PLUGIN_FUNC_ERROR
static const char * np(const char *str)
Definition: simple.c:108
#define OPENVPN_PLUGIN_TLS_FINAL
#define OPENVPN_PLUGIN_CLIENT_DISCONNECT
void * openvpn_plugin_handle_t
OPENVPN_EXPORT int openvpn_plugin_func_v2(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[], void *per_client_context, struct openvpn_plugin_string_list **return_list)
Definition: simple.c:251
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition: simple.c:334
static int atoi_null0(const char *str)
Definition: simple.c:121
#define OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
OPENVPN_EXPORT void * openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
Definition: simple.c:320
int test_packet_filter
Definition: simple.c:71
#define free
Definition: cmocka.c:1850
Definition: argv.h:35
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2
#define OPENVPN_PLUGIN_UP
#define OPENVPN_PLUGIN_MASK(x)