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