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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "init.h"
33 #include "forward.h"
34 #include "multi.h"
35 #include "win32.h"
36 #include "platform.h"
37 
38 #include "memdbg.h"
39 
40 #define P2P_CHECK_SIG() EVENT_LOOP_CHECK_SIGNAL(c, process_signal_p2p, c);
41 
42 static bool
process_signal_p2p(struct context * c)43 process_signal_p2p(struct context *c)
44 {
45     remap_signal(c);
46     return process_signal(c);
47 }
48 
49 
50 /**************************************************************************/
51 /**
52  * Main event loop for OpenVPN in client mode, where only one VPN tunnel
53  * is active.
54  * @ingroup eventloop
55  *
56  * @param c - The context structure of the single active VPN tunnel.
57  */
58 static void
tunnel_point_to_point(struct context * c)59 tunnel_point_to_point(struct context *c)
60 {
61     context_clear_2(c);
62 
63     /* set point-to-point mode */
64     c->mode = CM_P2P;
65 
66     /* initialize tunnel instance */
67     init_instance_handle_signals(c, c->es, CC_HARD_USR1_TO_HUP);
68     if (IS_SIG(c))
69     {
70         return;
71     }
72 
73     /* main event loop */
74     while (true)
75     {
76         perf_push(PERF_EVENT_LOOP);
77 
78         /* process timers, TLS, etc. */
79         pre_select(c);
80         P2P_CHECK_SIG();
81 
82         /* set up and do the I/O wait */
83         io_wait(c, p2p_iow_flags(c));
84         P2P_CHECK_SIG();
85 
86         /* timeout? */
87         if (c->c2.event_set_status == ES_TIMEOUT)
88         {
89             perf_pop();
90             continue;
91         }
92 
93         /* process the I/O which triggered select */
94         process_io(c);
95         P2P_CHECK_SIG();
96 
97         perf_pop();
98     }
99 
100     uninit_management_callback();
101 
102     /* tear down tunnel instance (unless --persist-tun) */
103     close_instance(c);
104 }
105 
106 #undef PROCESS_SIGNAL_P2P
107 
108 
109 /**************************************************************************/
110 /**
111  * OpenVPN's main init-run-cleanup loop.
112  * @ingroup eventloop
113  *
114  * This function contains the two outer OpenVPN loops.  Its structure is
115  * as follows:
116  *  - Once-per-process initialization.
117  *  - Outer loop, run at startup and then once per \c SIGHUP:
118  *    - Level 1 initialization
119  *    - Inner loop, run at startup and then once per \c SIGUSR1:
120  *      - Call event loop function depending on client or server mode:
121  *        - \c tunnel_point_to_point()
122  *        - \c tunnel_server()
123  *    - Level 1 cleanup
124  *  - Once-per-process cleanup.
125  *
126  * @param argc - Commandline argument count.
127  * @param argv - Commandline argument values.
128  */
129 static
130 int
openvpn_main(int argc,char * argv[])131 openvpn_main(int argc, char *argv[])
132 {
133     struct context c;
134 
135 #if PEDANTIC
136     fprintf(stderr, "Sorry, I was built with --enable-pedantic and I am incapable of doing any real work!\n");
137     return 1;
138 #endif
139 
140 #ifdef _WIN32
141     SetConsoleOutputCP(CP_UTF8);
142 #endif
143 
144     CLEAR(c);
145 
146     /* signify first time for components which can
147      * only be initialized once per program instantiation. */
148     c.first_time = true;
149 
150     /* initialize program-wide statics */
151     if (init_static())
152     {
153         /*
154          * This loop is initially executed on startup and then
155          * once per SIGHUP.
156          */
157         do
158         {
159             /* enter pre-initialization mode with regard to signal handling */
160             pre_init_signal_catch();
161 
162             /* zero context struct but leave first_time member alone */
163             context_clear_all_except_first_time(&c);
164 
165             /* static signal info object */
166             CLEAR(siginfo_static);
167             c.sig = &siginfo_static;
168 
169             /* initialize garbage collector scoped to context object */
170             gc_init(&c.gc);
171 
172             /* initialize environmental variable store */
173             c.es = env_set_create(NULL);
174 #ifdef _WIN32
175             set_win_sys_path_via_env(c.es);
176 #endif
177 
178 #ifdef ENABLE_MANAGEMENT
179             /* initialize management subsystem */
180             init_management();
181 #endif
182 
183             /* initialize options to default state */
184             init_options(&c.options, true);
185 
186             /* parse command line options, and read configuration file */
187             parse_argv(&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, c.es);
188 
189 #ifdef ENABLE_PLUGIN
190             /* plugins may contribute options configuration */
191             init_verb_mute(&c, IVM_LEVEL_1);
192             init_plugins(&c);
193             open_plugins(&c, true, OPENVPN_PLUGIN_INIT_PRE_CONFIG_PARSE);
194 #endif
195 
196             net_ctx_init(&c, &c.net_ctx);
197 
198             /* init verbosity and mute levels */
199             init_verb_mute(&c, IVM_LEVEL_1);
200 
201             /* set dev options */
202             init_options_dev(&c.options);
203 
204             /* openssl print info? */
205             if (print_openssl_info(&c.options))
206             {
207                 break;
208             }
209 
210             /* --genkey mode? */
211             if (do_genkey(&c.options))
212             {
213                 break;
214             }
215 
216             /* tun/tap persist command? */
217             if (do_persist_tuntap(&c.options, &c.net_ctx))
218             {
219                 break;
220             }
221 
222             /* sanity check on options */
223             options_postprocess(&c.options);
224 
225             /* show all option settings */
226             show_settings(&c.options);
227 
228             /* print version number */
229             msg(M_INFO, "%s", title_string);
230 #ifdef _WIN32
231             show_windows_version(M_INFO);
232 #endif
233             show_library_versions(M_INFO);
234 
235             /* misc stuff */
236             pre_setup(&c.options);
237 
238             /* test crypto? */
239             if (do_test_crypto(&c.options))
240             {
241                 break;
242             }
243 
244             /* Query passwords before becoming a daemon if we don't use the
245              * management interface to get them. */
246 #ifdef ENABLE_MANAGEMENT
247             if (!(c.options.management_flags & MF_QUERY_PASSWORDS))
248 #endif
249             init_query_passwords(&c);
250 
251             /* become a daemon if --daemon */
252             if (c.first_time)
253             {
254                 c.did_we_daemonize = possibly_become_daemon(&c.options);
255                 write_pid_file(c.options.writepid, c.options.chroot_dir);
256             }
257 
258 #ifdef ENABLE_MANAGEMENT
259             /* open management subsystem */
260             if (!open_management(&c))
261             {
262                 break;
263             }
264             /* query for passwords through management interface, if needed */
265             if (c.options.management_flags & MF_QUERY_PASSWORDS)
266             {
267                 init_query_passwords(&c);
268             }
269 #endif
270 
271             /* set certain options as environmental variables */
272             setenv_settings(c.es, &c.options);
273 
274             /* finish context init */
275             context_init_1(&c);
276 
277             do
278             {
279                 /* run tunnel depending on mode */
280                 switch (c.options.mode)
281                 {
282                     case MODE_POINT_TO_POINT:
283                         tunnel_point_to_point(&c);
284                         break;
285 
286                     case MODE_SERVER:
287                         tunnel_server(&c);
288                         break;
289 
290                     default:
291                         ASSERT(0);
292                 }
293 
294                 /* indicates first iteration -- has program-wide scope */
295                 c.first_time = false;
296 
297                 /* any signals received? */
298                 if (IS_SIG(&c))
299                 {
300                     print_signal(c.sig, NULL, M_INFO);
301                 }
302 
303                 /* pass restart status to management subsystem */
304                 signal_restart_status(c.sig);
305             }
306             while (c.sig->signal_received == SIGUSR1);
307 
308             env_set_destroy(c.es);
309             uninit_options(&c.options);
310             gc_reset(&c.gc);
311             net_ctx_free(&c.net_ctx);
312         }
313         while (c.sig->signal_received == SIGHUP);
314     }
315 
316     context_gc_free(&c);
317 
318 #ifdef ENABLE_MANAGEMENT
319     /* close management interface */
320     close_management();
321 #endif
322 
323     /* uninitialize program-wide statics */
324     uninit_static();
325 
326     openvpn_exit(OPENVPN_EXIT_STATUS_GOOD); /* exit point */
327     return 0;                               /* NOTREACHED */
328 }
329 
330 #ifdef _WIN32
331 int
wmain(int argc,wchar_t * wargv[])332 wmain(int argc, wchar_t *wargv[])
333 {
334     char **argv;
335     int ret;
336     int i;
337 
338     if ((argv = calloc(argc+1, sizeof(char *))) == NULL)
339     {
340         return 1;
341     }
342 
343     for (i = 0; i < argc; i++)
344     {
345         int n = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL);
346         argv[i] = malloc(n);
347         WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], n, NULL, NULL);
348     }
349 
350     ret = openvpn_main(argc, argv);
351 
352     for (i = 0; i < argc; i++)
353     {
354         free(argv[i]);
355     }
356     free(argv);
357 
358     return ret;
359 }
360 #else  /* ifdef _WIN32 */
361 int
main(int argc,char * argv[])362 main(int argc, char *argv[])
363 {
364     return openvpn_main(argc, argv);
365 }
366 #endif /* ifdef _WIN32 */
367