/[projects]/openvpn/openvpn-auth_mysql/auth-mysql.c
ViewVC logotype

Contents of /openvpn/openvpn-auth_mysql/auth-mysql.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 113 - (show annotations) (download)
Wed Oct 29 19:45:52 2008 UTC (15 years, 6 months ago) by torben
File MIME type: text/plain
File size: 8130 byte(s)
Added openvpn tools

1 /*
2 * Copyright (C) 2006 Torben H. Nielsen<torben@t-hoerup.dk>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program (see the file COPYING included with this
15 * distribution); if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <mysql.h>
24 #include <time.h>
25
26 #include "openvpn-plugin.h"
27
28 #define ERR_ADMINLOCK 1
29 #define ERR_EXPIRED 2
30 #define ERR_ZEROPASS 3
31 #define ERR_WRONGPASS 4
32 #define ERR_NOSUCHUSER 5
33 #define ERR_AUTOLOCKED 6
34
35
36 /*
37 * Our context, where we keep our state.
38 */
39 struct plugin_context {
40 char *host;
41 char *username;
42 char *password;
43 char *db;
44 char *table;
45 char *log;
46 int port;
47 };
48
49 /*
50 * Given an environmental variable name, search
51 * the envp array for its value, returning it
52 * if found or NULL otherwise.
53 */
54 static const char *
55 get_arg (const char *name, const char *envp[])
56 {
57 if (envp)
58 {
59 int i;
60 const int namelen = strlen (name);
61 for (i = 0; envp[i]; ++i)
62 {
63 if (!strncmp (envp[i], name, namelen))
64 {
65 const char *cp = envp[i] + namelen;
66 if (*cp == '=')
67 return cp + 1;
68 }
69 }
70 }
71 return NULL;
72 }
73
74 OPENVPN_EXPORT openvpn_plugin_handle_t
75 openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
76 {
77 struct plugin_context *context;
78 const char *tmp;
79
80 /*
81 * Allocate our context
82 */
83 context = (struct plugin_context *) calloc (1, sizeof (struct plugin_context));
84
85 /*
86 * Set the sql connection info
87 */
88
89 tmp = get_arg("host", argv);
90 if (tmp == NULL)
91 context->host = "localhost";
92 else {
93 context->host = malloc(strlen(tmp)+1);
94 strcpy(context->host, tmp);
95 }
96
97 tmp = get_arg("username", argv);
98 if (tmp == NULL)
99 context->username = "vpnauth";
100 else {
101 context->username = malloc(strlen(tmp)+1);
102 strcpy(context->username, tmp);
103 }
104
105 tmp = get_arg("password", argv);
106 if (tmp == NULL)
107 context->password = "vpnauth";
108 else {
109 context->password = malloc(strlen(tmp)+1);
110 strcpy(context->password, tmp);
111 }
112
113 tmp = get_arg("db", argv);
114 if (tmp == NULL)
115 context->db = "vpnauth";
116 else {
117 context->db = malloc(strlen(tmp)+1);
118 strcpy(context->db, tmp);
119 }
120
121 tmp = get_arg("table", argv);
122 if (tmp == NULL)
123 context->table = "vpnauth";
124 else {
125 context->table = malloc(strlen(tmp)+1);
126 strcpy(context->table, tmp);
127 }
128
129 tmp = get_arg("log", argv);
130 if (tmp == NULL)
131 context->log = "";
132 else {
133 context->log = malloc(strlen(tmp)+1);
134 strcpy(context->log, tmp);
135 }
136
137 tmp = get_arg("port", argv);
138 if (tmp != NULL)
139 context->port = atol(tmp);
140 else
141 context->port = 3306;
142
143 /* stdout is redirected to openvpn's logfile - so normal printf is ok */
144 printf("auth-mysql: connect to %s:%i/%s.%s as %s\n", context->host, context->port, context->db, context->table, context->username);
145
146
147 /*
148 * We are only interested in intercepting the
149 * --auth-user-pass-verify callback.
150 */
151 *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);
152
153
154 return (openvpn_plugin_handle_t) context;
155 }
156
157 OPENVPN_EXPORT int
158 openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
159 {
160 MYSQL *authdb=0;
161 MYSQL_RES *res=0;
162 MYSQL_ROW row=0;
163 int fail = 0;
164 char *sql;
165 char *escaped_user;
166 char *escaped_pass;
167 int failcount=0;
168 int locked;
169 long expire;
170 struct plugin_context *context;
171
172 context = (struct plugin_context *) handle;
173
174 /* get username/password from envp string array */
175 const char *username = get_arg ("username", envp);
176 const char *password = get_arg ("password", envp);
177
178 printf("auth-mysql: authenticating %s\n", username);
179
180 authdb = mysql_init( authdb );
181 if (! mysql_real_connect(authdb, context->host, context->username, context->password, context->db, context->port, NULL,0)) {
182 printf("auth-mysql: ERROR, could not connect to database: %s\n", mysql_error(authdb) );
183 return OPENVPN_PLUGIN_FUNC_ERROR;
184 }
185
186 escaped_user = malloc( (strlen(username)*2)+1);
187 if (escaped_user == 0) { /* could not allocate memory */
188 return OPENVPN_PLUGIN_FUNC_ERROR;
189 }
190
191 escaped_pass = malloc( (strlen(password)*2)+1);
192 if (escaped_pass == 0) { /* could not allocate memory */
193 return OPENVPN_PLUGIN_FUNC_ERROR;
194 free (escaped_user);
195 }
196
197 mysql_real_escape_string ( authdb, escaped_user, username, strlen(username) );
198 mysql_real_escape_string ( authdb, escaped_pass, password, strlen(password) );
199
200
201 sql = malloc( strlen(escaped_user) + strlen(context->table) + strlen(escaped_user)+ 120 );
202 if (sql == 0) { /* could not allocate memory */
203 free (escaped_user);
204 free (escaped_pass);
205 return OPENVPN_PLUGIN_FUNC_ERROR;
206 }
207
208 sprintf(sql, "SELECT id,user,pass=md5('%s') as passcheck,locked, UNIX_TIMESTAMP(expires),failcount FROM %s WHERE user='%s'", escaped_pass, context->table, escaped_user);
209 printf("auth-mysql: sql=%s\n", sql);
210
211 if ( mysql_query( authdb, sql)) { /*mysql error */
212 printf("auth-mysql: error: %s\n", mysql_error(authdb));
213 mysql_close (authdb);
214 free(escaped_user);
215 free(escaped_pass);
216 free(sql);
217 return OPENVPN_PLUGIN_FUNC_ERROR;
218 }
219
220 res = mysql_store_result( authdb );
221 if (res == 0) { /* could not allocate res */
222 mysql_close( authdb);
223 free(escaped_user);
224 free(escaped_pass);
225 return OPENVPN_PLUGIN_FUNC_ERROR;
226 }
227
228
229 if (strlen(password) == 0) {
230 printf("auth-mysql: zero length password (%s)\n", username);
231 fail = ERR_ZEROPASS;
232 }
233
234 if ( fail==0 && mysql_num_rows(res) == 0) {
235 printf("auth-mysql: user does not exist (%s)\n", username);
236 fail = ERR_NOSUCHUSER;
237 }
238
239 if (fail==0)
240 row = mysql_fetch_row(res);
241
242 if (fail==0) {
243 if ( atol(row[2])==0 ) {
244 fail = ERR_WRONGPASS;
245 printf("auth-mysql: user provided wrong password (%s)\n", username);
246 }
247 }
248
249 if (fail==0) {
250 locked = atol( row[3] );
251 if (locked != 0) {
252 fail = ERR_ADMINLOCK;
253 printf("auth-mysql: account is locked (%s)\n", username);
254 }
255 }
256
257 if (fail==0) {
258 expire = atol( row[4] );
259 if (expire != 0) {
260 if ( (expire-time(0))<0) {
261 fail = ERR_EXPIRED;
262 printf("auth-mysql: account has expired (%s)\n", username);
263 }
264 }
265 }
266
267 if (fail==0) {
268 failcount = atol( row[5] );
269 if (failcount >= 3 && fail==0) {
270 fail = ERR_AUTOLOCKED;
271 printf("auth-mysql: account failcount was larger than or equal 3 (%s)\n", username);
272 }
273 }
274
275
276 /* if user/pass is ok - reset failcount, and set lastlogin to now() */
277 if ( fail == 0 ) {
278 sprintf(sql, "UPDATE %s SET failcount=0,lastlogin=now() WHERE user='%s'", context->table, escaped_user);
279 mysql_query( authdb, sql);
280 }
281
282 /* if user entered wrong password, increment failcount */
283 if ( fail == ERR_WRONGPASS ) {
284 failcount++;
285 sprintf(sql, "UPDATE %s SET failcount=%i WHERE user='%s'", context->table, failcount, escaped_user);
286 mysql_query( authdb, sql);
287 }
288
289 if ( strlen(context->log)>0) { /* enable log table */
290 sprintf(sql, "INSERT INTO %s (username,time,msgid) VALUES ('%s',now(), %d)", context->log, escaped_user, fail);
291 mysql_query( authdb, sql);
292 }
293
294 free(sql);
295 free(escaped_user);
296 free(escaped_pass);
297 mysql_free_result(res);
298 mysql_close( authdb );
299
300 return (fail == 0) ? OPENVPN_PLUGIN_FUNC_SUCCESS : OPENVPN_PLUGIN_FUNC_ERROR;
301 }
302
303 OPENVPN_EXPORT void
304 openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
305 {
306 struct plugin_context *context = (struct plugin_context *) handle;
307 free (context);
308 }

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20