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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 113 - (hide 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 torben 113 /*
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