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 
69 struct plugin_context {
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  if (context == NULL)
145  {
146  printf("PLUGIN: allocating memory for context failed\n");
147  return NULL;
148  }
149 
150  context->test_deferred_auth = atoi_null0(get_env("test_deferred_auth", envp));
151  printf("TEST_DEFERRED_AUTH %d\n", context->test_deferred_auth);
152 
153  context->test_packet_filter = atoi_null0(get_env("test_packet_filter", envp));
154  printf("TEST_PACKET_FILTER %d\n", context->test_packet_filter);
155 
156  /*
157  * Which callbacks to intercept.
158  */
159  *type_mask =
171 
172  return (openvpn_plugin_handle_t) context;
173 }
174 
175 static int
176 auth_user_pass_verify(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
177 {
178  if (context->test_deferred_auth)
179  {
180  /* get username/password from envp string array */
181  const char *username = get_env("username", envp);
182  const char *password = get_env("password", envp);
183 
184  /* get auth_control_file filename from envp string array*/
185  const char *auth_control_file = get_env("auth_control_file", envp);
186 
187  printf("DEFER u='%s' p='%s' acf='%s'\n",
188  np(username),
189  np(password),
190  np(auth_control_file));
191 
192  /* Authenticate asynchronously in n seconds */
193  if (auth_control_file)
194  {
195  char buf[256];
196  int auth = 2;
197  sscanf(username, "%d", &auth);
198  snprintf(buf, sizeof(buf), "( sleep %d ; echo AUTH %s %d ; echo %d >%s ) &",
199  context->test_deferred_auth,
200  auth_control_file,
201  auth,
202  pcc->n_calls < auth,
203  auth_control_file);
204  printf("%s\n", buf);
205  system(buf);
206  pcc->n_calls++;
208  }
209  else
210  {
212  }
213  }
214  else
215  {
217  }
218 }
219 
220 static int
221 tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
222 {
223  if (context->test_packet_filter)
224  {
225  if (!pcc->generated_pf_file)
226  {
227  const char *pff = get_env("pf_file", envp);
228  const char *cn = get_env("username", envp);
229  if (pff && cn)
230  {
231  char buf[256];
232  snprintf(buf, sizeof(buf), "( sleep %d ; echo PF %s/%s ; cp \"%s.pf\" \"%s\" ) &",
233  context->test_packet_filter, cn, pff, cn, pff);
234  printf("%s\n", buf);
235  system(buf);
236  pcc->generated_pf_file = true;
238  }
239  else
240  {
242  }
243  }
244  else
245  {
247  }
248  }
249  else
250  {
252  }
253 }
254 
255 OPENVPN_EXPORT int
257  const int type,
258  const char *argv[],
259  const char *envp[],
260  void *per_client_context,
261  struct openvpn_plugin_string_list **return_list)
262 {
263  struct plugin_context *context = (struct plugin_context *) handle;
264  struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
265  switch (type)
266  {
267  case OPENVPN_PLUGIN_UP:
268  printf("OPENVPN_PLUGIN_UP\n");
270 
271  case OPENVPN_PLUGIN_DOWN:
272  printf("OPENVPN_PLUGIN_DOWN\n");
274 
276  printf("OPENVPN_PLUGIN_ROUTE_UP\n");
278 
280  printf("OPENVPN_PLUGIN_IPCHANGE\n");
282 
284  printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
286 
288  printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
289  return auth_user_pass_verify(context, pcc, argv, envp);
290 
292  printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
294 
296  printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
298 
300  printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
302 
304  printf("OPENVPN_PLUGIN_TLS_FINAL\n");
305  return tls_final(context, pcc, argv, envp);
306 
308  printf("OPENVPN_PLUGIN_ENABLE_PF\n");
309  if (context->test_packet_filter)
310  {
312  }
313  else
314  {
316  }
317 
318  default:
319  printf("OPENVPN_PLUGIN_?\n");
321  }
322 }
323 
324 OPENVPN_EXPORT void *
326 {
327  printf("FUNC: openvpn_plugin_client_constructor_v1\n");
328  return calloc(1, sizeof(struct plugin_per_client_context));
329 }
330 
331 OPENVPN_EXPORT void
333 {
334  printf("FUNC: openvpn_plugin_client_destructor_v1\n");
335  free(per_client_context);
336 }
337 
338 OPENVPN_EXPORT void
340 {
341  struct plugin_context *context = (struct plugin_context *) handle;
342  printf("FUNC: openvpn_plugin_close_v1\n");
343  free(context);
344 }
OPENVPN_EXPORT void openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *per_client_context)
Definition: simple.c:332
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:176
const char * password
Definition: log.c:42
Contains all state information for one tunnel.
Definition: openvpn.h:503
#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:133
#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:221
#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:256
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition: simple.c:339
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:325
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)