i am use openvpn 2.0.7,and use *auth-user-pass-verify to auth userlogin.*
*but i have a problems!*
**
*if openvpn server "use auth-user-pass-verify ",can't disable a user
name duplicate
login in same time.*
**
*my auth plugin src is below:*
**

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _XOPEN_SOURCE
#include <unistd.h>
#include <crypt.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "openvpn-plugin.h"

#define MAX_USER_LEN    15
#define MAX_PASS_LEN    47
#define MAX_USERS       100

struct user
{
   char name[MAX_USER_LEN + 1];
   char pass[MAX_PASS_LEN + 1];
   int  online;
};

/*
* Our context, where we keep our state.
*/
struct plugin_context
{
   const char *file_path;
   time_t mtime;
   int num_users;
   struct user users[MAX_USERS];
   int fs;
};


/**
* 检验客户端输入的用户名和密码是否正确
*
* @return 非 0 正确;0 错误
*/
static int valid_login(struct plugin_context *ct,const char *user,const char
*pass)
{
   int i;
   FILE *fp;
   struct user *users = ct->users;

   if ( user == NULL || pass == NULL )
   {
       return 0;
   }

   for (i=0; i < ct->num_users; i++)
   {
       if ( strcmp(user,users[i].name) == 0 ) // && ( users[i].online ==
0))
       {
           //char *result = crypt(pass,users[i].pass);
           //return (strcmp(result,users[i].pass) == 0);
           //users[i].online =1;
           fp = fopen("/home/wsgtrsys/openvpn/log/login","a");

           if (ct->fs == 0)
            {
             fclose(fp);
             fp = fopen("/home/wsgtrsys/openvpn/log/login","w");
             ct->fs = 1;
            }
           fprintf(fp,user name is:%s\n,user);
           fclose(fp);

           return 1;
       }
   }

   return 0;
}


/*
* Given an environmental variable name, search
* the envp array for its value, returning it
* if found or NULL otherwise.
*/
static const char *
get_env (const char *name, const char *envp[])
{
   if (envp)
   {
       int i;
       const int namelen = strlen (name);

       for (i = 0; envp[i]; ++i)
       {
           if (!strncmp (envp[i], name, namelen))
           {
               const char *cp = envp[i] + namelen;

               if (*cp == '=')
                   return cp + 1;
           }
       }
   }

   return NULL;
}


/**
* 读入帐号文件中的帐号
*/
static int read_users(struct plugin_context *ct)
{
   int num;
   FILE *fp;
   struct stat st;
   char buf[256];

   if (ct == NULL || ct->file_path == NULL)
   {
       fprintf(stderr,"Arg check failed\n");
       return -1;
   }

   if ( stat(ct->file_path,&st) < 0 )
   {
       perror("stat");
       return -1;
   }

   if ( st.st_mtime <= ct->mtime )
   {
       return 0;
   }

   fp = fopen(ct->file_path,"r");
   if (fp == NULL)
   {
       perror("fopen");
       return -1;
   }

   num = 0;
   while( fgets(buf,sizeof(buf),fp) )
   {
       char *p = strchr(buf,':');

       if (p == NULL)
           continue;

       *p++ = '\0';
       if ( strlen(buf) > MAX_USER_LEN )
       {
           fprintf(stderr,"Too long user: %s\n",buf);
           continue;
       }
       if ( strlen(p) > MAX_PASS_LEN )
       {
           fprintf(stderr,"Too long pass: %s\n",p);
           continue;
       }

       strcpy(ct->users[num].name,buf);
       strcpy(ct->users[num].pass,p);

       while ( (p = strrchr(ct->users[num].pass,'\n')) )
           *p = '\0';

       num++;
       if (num >= MAX_USERS)
           break;
   }
   fclose(fp);

   ct->mtime = st.st_mtime;
   ct->num_users = num;

   return num;
}


OPENVPN_EXPORT openvpn_plugin_handle_t
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const
char *envp[])
{
   struct plugin_context *context;

   if ( argv[1] == NULL )
   {
       fprintf(stderr,"Need u/p file argument\n");
       return NULL;
   }

   /*
    * Allocate our context
    */
   context = (struct plugin_context *) calloc (1, sizeof (struct
plugin_context));
   memset(context,0,sizeof(struct plugin_context));
   context->file_path = argv[1];

   if ( read_users(context) < 0 )
   {
       free(context);
       fprintf(stderr,"Get users failed\n");
       return NULL;
   }

   context->file_path = strdup(argv[1]);

   /*
    * We are only interested in intercepting the
    * --auth-user-pass-verify callback.
    */
   *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);

   return (openvpn_plugin_handle_t) context;
}


OPENVPN_EXPORT int
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type,
const char *argv[], const char *envp[])
{
   struct plugin_context *context = (struct plugin_context *) handle;

   /* get username/password from envp string array */
   const char *username = get_env ("username", envp);
   const char *password = get_env ("password", envp);

   read_users(context);

   /* check entered username/password against what we require */
   if ( valid_login(context,username,password) )
       return OPENVPN_PLUGIN_FUNC_SUCCESS;
   else
       return OPENVPN_PLUGIN_FUNC_ERROR;
}


OPENVPN_EXPORT void
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
{
   struct plugin_context *context = (struct plugin_context *) handle;

   free((void*)context->file_path);
   free (context);
}


#ifdef TEST
int main(int argc,const char **argv,const char **envp)
{
   unsigned int type = 0;
   openvpn_plugin_handle_t h;

   h = openvpn_plugin_open_v1(&type,&argv[1],envp);
   if (h == NULL)
   {
       fprintf(stderr,"openvpn_plugin_open_v1\n");
       return -1;
   }

   if ( openvpn_plugin_func_v1(h,type,NULL,envp) ==
OPENVPN_PLUGIN_FUNC_SUCCESS )
   {
       puts("OK");
   }

   openvpn_plugin_close_v1(h);
   return 0;
}
#endif

Reply via email to