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 examine the username/password provided by a client,
27  * and make an accept/deny determination.  Will run
28  * on Windows or *nix.
29  *
30  * See the README file for build instructions.
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 
37 #include "openvpn-plugin.h"
38 
39 /*
40  * Our context, where we keep our state.
41  */
42 struct plugin_context {
43     const char *username;
44     const char *password;
45 };
46 
47 /*
48  * Given an environmental variable name, search
49  * the envp array for its value, returning it
50  * if found or NULL otherwise.
51  */
52 static const char *
get_env(const char * name,const char * envp[])53 get_env(const char *name, const char *envp[])
54 {
55     if (envp)
56     {
57         int i;
58         const int namelen = strlen(name);
59         for (i = 0; envp[i]; ++i)
60         {
61             if (!strncmp(envp[i], name, namelen))
62             {
63                 const char *cp = envp[i] + namelen;
64                 if (*cp == '=')
65                 {
66                     return cp + 1;
67                 }
68             }
69         }
70     }
71     return NULL;
72 }
73 
74 OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v1(unsigned int * type_mask,const char * argv[],const char * envp[])75 openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
76 {
77     struct plugin_context *context;
78 
79     /*
80      * Allocate our context
81      */
82     context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
83     if (context == NULL)
84     {
85         printf("PLUGIN: allocating memory for context failed\n");
86         return NULL;
87     }
88 
89     /*
90      * Set the username/password we will require.
91      */
92     context->username = "foo";
93     context->password = "bar";
94 
95     /*
96      * We are only interested in intercepting the
97      * --auth-user-pass-verify callback.
98      */
99     *type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);
100 
101     return (openvpn_plugin_handle_t) context;
102 }
103 
104 OPENVPN_EXPORT int
openvpn_plugin_func_v1(openvpn_plugin_handle_t handle,const int type,const char * argv[],const char * envp[])105 openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
106 {
107     struct plugin_context *context = (struct plugin_context *) handle;
108 
109     /* get username/password from envp string array */
110     const char *username = get_env("username", envp);
111     const char *password = get_env("password", envp);
112 
113     /* check entered username/password against what we require */
114     if (username && !strcmp(username, context->username)
115         && password && !strcmp(password, context->password))
116     {
117         return OPENVPN_PLUGIN_FUNC_SUCCESS;
118     }
119     else
120     {
121         return OPENVPN_PLUGIN_FUNC_ERROR;
122     }
123 }
124 
125 OPENVPN_EXPORT void
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)126 openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
127 {
128     struct plugin_context *context = (struct plugin_context *) handle;
129     free(context);
130 }
131