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