1 /*
2  * testplugin.c vi:ts=4:sw=4:expandtab:
3  * OpenVPN LDAP Authentication Plugin Test Driver
4  *
5  * Copyright (c) 2005 - 2007 Landon Fuller <landonf@threerings.net>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of Landon Fuller nor the names of any contributors
17  *    may be used to endorse or promote products derived from this
18  *    software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <err.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <errno.h>
39 
40 #include <openvpn-plugin.h>
41 
42 /* Argument / environment templates */
43 const char username_template[] = "username=";
44 const char password_template[] = "password=";
45 const char conf_template[] = "/tmp/openvpn-auth-ldap-test.XXXXXXXXXXXXX";
46 
47 /* Configuration data */
48 typedef struct {
49     /* User name and password environmental variables */
50     char *username;
51     char *password;
52 
53     /* Path to config file */
54     const char *config_file;
55 
56     /* OpenVPN plugin environment */
57     const char **envp;
58 
59     /* OpenVPN plugin open/close arguments */
60     const char **argp;
61 
62     /* OpenVPN 'command line' script arguments */
63     const char **argp_script;
64 } plugin_data;
65 
66 /**
67  * Initialize the plugin data structure. This function is not thread-safe; it
68  * interacts with the user on stdin, and calls other non-reentrant functions (eg getpass()).
69  */
plugin_data_init(const char * config_file)70 static plugin_data *plugin_data_init (const char *config_file) {
71     plugin_data *data;
72     char username[128];
73     char *password;
74 
75     /* Alloc and zero-initialize a new data structure */
76     data = calloc(1, sizeof(plugin_data));
77 
78     /* Fetch the username and password */
79     printf("Username: ");
80     if (fgets(username, sizeof(username), stdin) == NULL) {
81         errx(1, "Failed to read username");
82     }
83 
84     password = getpass("Password: ");
85 
86     /* Strip off the trailing \n */
87     username[strlen(username) - 1] = '\0';
88 
89     /* Assemble the username env variable */
90     data->username = malloc(sizeof(username_template) + strlen(username));
91     strcpy(data->username, username_template);
92     strcat(data->username, username);
93 
94     /* Assemble the password env variable */
95     data->password = malloc(sizeof(password_template) + strlen(password));
96     strcpy(data->password, password_template);
97     strcat(data->password, password);
98 
99     /* Set up the plugin environment array -- username, password, ifconfig_pool_remote_ip, NULL */
100     data->envp = calloc(4, sizeof(char *));
101     data->envp[0] = data->username;
102     data->envp[1] = data->password;
103     data->envp[2] = "ifconfig_pool_remote_ip=10.0.50.1";
104     data->envp[3] = NULL;
105 
106     /* Set up the plugin argument array -- plugin path, config file, NULL */
107     data->argp = calloc(3, sizeof(char *));
108     data->argp[0] = "plugin.so";
109     data->argp[1] = config_file;
110     data->argp[2] = NULL;
111 
112     /* Set up the plugin "script" argument array -- plugin path, dynamic config file, NULL */
113     // TODO: wire up dynamic config file support.
114     data->argp_script = calloc(3, sizeof(char *));
115     data->argp_script[0] = "plugin.so";
116     data->argp_script[1] = NULL;
117     data->argp_script[2] = NULL;
118 
119     return data;
120 }
121 
plugin_data_free(plugin_data * data)122 static void plugin_data_free (plugin_data *data) {
123     if (data->username)
124         free(data->username);
125 
126     if (data->password)
127         free(data->password);
128 
129     if (data->envp)
130         free(data->envp);
131 
132     if (data->argp)
133         free(data->argp);
134 
135     if (data->argp_script)
136         free(data->argp_script);
137 
138     free(data);
139 }
140 
main(int argc,const char * argv[])141 int main(int argc, const char *argv[]) {
142     openvpn_plugin_handle_t handle;
143     plugin_data *data;
144     const char *config_file;
145     unsigned int plugin_type;
146     int retval = 1;
147     int err;
148 
149     if (argc != 2) {
150         errx(1, "Usage: %s <config file>", argv[0]);
151     } else {
152         config_file = argv[1];
153     }
154 
155     /* Configure the plugin environment */
156     data = plugin_data_init(config_file);
157 
158     handle = openvpn_plugin_open_v1(&plugin_type, data->argp, data->envp);
159 
160     if (!handle) {
161         printf("Initialization Failed!\n");
162         goto cleanup;
163     }
164 
165     /* Authenticate */
166     err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, data->argp_script, data->envp);
167     if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) {
168         printf("Authorization Failed!\n");
169         goto cleanup;
170     } else {
171         printf("Authorization Succeed!\n");
172     }
173 
174     /* Client Connect */
175     err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_CLIENT_CONNECT, data->argp_script, data->envp);
176     if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) {
177         printf("client-connect failed!\n");
178         goto cleanup;
179     } else {
180         printf("client-connect succeed!\n");
181     }
182 
183     /* Client Disconnect */
184     err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_CLIENT_DISCONNECT, data->argp, data->envp);
185     if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) {
186         printf("client-disconnect failed!\n");
187         goto cleanup;
188     } else {
189         printf("client-disconnect succeed!\n");
190     }
191 
192     /* Everything worked. Set our return value accordingly. */
193     retval = 0;
194 
195 cleanup:
196     openvpn_plugin_close_v1(handle);
197     plugin_data_free(data);
198 
199     exit(retval);
200 }
201