3proxy/src/plugins/LdapPlugin/ldapauth.c
2014-04-08 13:03:21 +04:00

576 lines
16 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ldap.h>
#ifndef _WIN32
#include <ctype.h>
#endif
#include "../../proxy.h"
#include "../../structures.h"
struct counter_record
{
unsigned long traf;
unsigned long trafgb;
time_t cleared;
time_t updated;
};
int already_loaded = 0;
static struct auth myalwaysauth;
static struct commands ldap_serv_auth_handler;
static struct commands ldap_access_handler;
static struct commands ldap_sbase_handler;
static struct commands ldap_userenv_handler;
static struct commands ldap_trafgroup_handler;
static struct commands ldap_attrsgroup_handler;
static struct commands ldap_dircount_handler;
static char *attrs[] = { NULL, NULL};
static char *ldap_group_attr;
static char *ldap_access;
static char *ldap_sbase;
static char *ldap_serv;
static char *ldap_user;
static char *ldap_pass;
static char *ldap_userenv;
int ldap_userenv_size;
static char *ldap_trafgroup;
static char *ldap_dircount;
static int usercaselow = 0;
struct pluginlink * mypluginlink;
struct schedule myschedule;
#ifndef _WIN32
void lower (char *string)
{
int length, i;
length = strlen(string);
for (i=0; i<length; i++)
{
string[i] = tolower(string[i]);
}
}
#endif
/* -------------------------------------------------------------------------- */
int savecouters(void)
{
struct trafcount *tc=mypluginlink->conf->trafcounter;
struct trafcount *tcd;
struct counter_record wcounter;
FILE *f;
unsigned char *tmpbuf,pat_file[]="%s%s.lc";
/* timetoexit !=0 - áóäåì çàâåðøàòüñÿ.*/
while (tc != NULL)
{
tcd = tc;
tc = tc->next;
f=NULL;
if(strcmp(tcd->comment,"ldapcounters")==0) {
tmpbuf=mypluginlink->myalloc(strlen(pat_file)+strlen(ldap_dircount)+strlen(tcd->ace->users->user));
sprintf(tmpbuf,pat_file,ldap_dircount,tcd->ace->users->user);
f=fopen(tmpbuf,"w+b");
fseek(f,0,SEEK_SET);
fprintf(f,"%10lu %10lu %lu %lu\n",tcd->trafgb,tcd->traf,
tcd->cleared,tcd->updated);
fclose(f);
mypluginlink->myfree(tmpbuf);
}
}
/*return 1 delete job , return 0 no delete job*/
if (mypluginlink->conf->needreload !=0 )
{
return (0);
}
return (0);
}
/*--------------------------------------------------------------------------*/
#ifdef _WIN32
__declspec(dllexport) int start(struct pluginlink * pluginlink,
int argc, char** argv);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
#else
int start(struct pluginlink * pluginlink,
int argc, char** argv);
#endif
/* --------------------------------------------------------------------------*/
static int ldapfunc(struct clientparam *param)
{
LDAP *ld = NULL;
LDAPMessage *res = NULL;
int rc = -1;
char tmpbuf[1024];
/* init ldap ---------------------- */
ld = ldap_init( ldap_serv, 389 );
if ( ld == NULL )
{
param->srv->logfunc(param,"Error ldap_init: No init lib ldap");
/*ldap_perror( ld, "Error ldap_init" ); */
return 7;
}
/* test proxy user auth ------------------------*/
if(!param->username || !param->password) return 4;
if(strlen(param->password)==0) return 4;
/* this code for Active Directory LDAP catalog :(
detail see documentation for plugin */
if (usercaselow > 0)
#ifdef _WIN32
{ CharLower(param->username); }
#else
{ lower(param->username); }
#endif
/* create user for test auth */
sprintf(tmpbuf,"%.200s=%.200s,%.200s",attrs[0],param->username,ldap_userenv);
rc = ldap_bind_s( ld, tmpbuf, param->password, LDAP_AUTH_SIMPLE );
if ( rc != LDAP_SUCCESS )
{
param->srv->logfunc(param,"Error ldap_bind: No connect ldap catalog");
ldap_unbind_s(ld);
return 7;
}
ldap_unbind_s(ld);
ld = ldap_init( ldap_serv, 389 );
rc = ldap_bind_s( ld, ldap_user, ldap_pass, LDAP_AUTH_SIMPLE );
if ( rc != LDAP_SUCCESS )
{
param->srv->logfunc(param, "Error ldap_bind: Not authorize in ldap\
catalog, checked option \'ldapconnect\' ");
ldap_unbind_s(ld);
return 7;
}
/* test enter user in filter ------------------------------
create filter for search*/
sprintf(tmpbuf,"(&(%.200s=%.200s)(%.200s=%.200s))",attrs[0],param->username,
ldap_group_attr,ldap_access);
/* search */
rc = ldap_search_s( ld, ldap_sbase, LDAP_SCOPE_SUBTREE,
tmpbuf, attrs, 0, &res );
rc=ldap_count_entries(ld,res);
ldap_msgfree(res);
ldap_unbind_s(ld);
/* user not found */
if (rc == 0)
{ return 5; }
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapserv */
int h_ldapconnect(int argc, unsigned char ** argv)
{
LDAP *ld = NULL;
if (argc < 2)
{
fprintf(stderr, "Error in ldapconnect: See documentation of ldapauth plugin.\n");
return 1;
}
ldap_serv=mypluginlink->mystrdup(argv[1]);
ldap_user=mypluginlink->mystrdup(argv[2]);
ld = ldap_init( ldap_serv, 389 );
ldap_unbind_s(ld);
if (argc == 4)
{
ldap_pass= mypluginlink->mystrdup(argv[3]);
}
else
{
ldap_pass=NULL;
}
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapaccess */
int h_access(int argc, unsigned char ** argv)
{
if (argc < 1)
{
fprintf(stderr, "Error in ldapaccess: See documentation of ldapauth plugin.\n");
return 1;
}
ldap_access=mypluginlink->mystrdup(argv[1]);
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapsbase
searching base */
int h_sbase(int argc, unsigned char ** argv)
{
if (argc < 1)
{
fprintf(stderr, "Error in ldapsbase: See documentation of ldapauth plugin.\n");
return 1;
}
ldap_sbase=mypluginlink->mystrdup(argv[1]);
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapuserenv */
int h_userenv(int argc, unsigned char ** argv)
{
if (argc < 1)
{
fprintf(stderr, "Error in ldapsbase: See documentation of ldapauth plugin.\n");
return 1;
}
ldap_userenv=mypluginlink->mystrdup(argv[1]);
return 0;
}
/* --------------------------------------------------------------------------
handle command ldaptrafgroup */
int h_trafgroup(int argc, unsigned char ** argv)
{
struct trafcount *newtrafcount;
struct bandlim *newbandlim;
static struct ace *newace;
static struct userlist *newuserlist;
struct counter_record rcounter;
LDAP *ld = NULL;
LDAPMessage *res = NULL;
LDAPMessage *msg = NULL;
BerElement *ber = NULL;
int rc = -1;
char *tmpbuf,pat_file[]="%s%s.lc",pat_group[]="(%s=%s)";
char *getattr,**vals,buf[256];
ROTATION rtype;
unsigned long traflimit;
int bandwidth ;
FILE *f;
if (argc < 3)
{
fprintf(stderr, "Error in ldaptrafgroup: See documentation of ldapauth plugin.\n");
return 1;
}
ld = ldap_init( ldap_serv, 389 );
if ( ld == NULL )
{
fprintf(stderr,"Error in ldaptrafgroup: ldap_init: No init lib ldap");
return 7;
}
rc = ldap_bind_s( ld, ldap_user, ldap_pass, LDAP_AUTH_SIMPLE );
if ( rc != LDAP_SUCCESS )
{
fprintf(stderr, "Error in ldaptrafgroup: ldap_bind: Not authorize in ldap\
catalog, checked option \'ldapconnect\' ");
ldap_unbind_s(ld);
return 7;
}
/* type traf limit */
if(strcmp(argv[2],"MONTHLY")==0||strcmp(argv[2],"monthly")==0)
{rtype=MONTHLY;}
if(strcmp(argv[2],"DAILY")==0||strcmp(argv[2],"daily")==0)
{rtype=DAILY;}
if(strcmp(argv[2],"WEEKLY")==0||strcmp(argv[2],"weekly")==0)
{rtype=WEEKLY;}
traflimit = atol((char *)argv[3]);
bandwidth = atoi((char *)argv[4]);
/* name ldap group */
tmpbuf=mypluginlink->myalloc(strlen(pat_group)+strlen(ldap_group_attr)+strlen(argv[1]));
sprintf(tmpbuf,pat_group,ldap_group_attr,argv[1]);
rc = ldap_search_s( ld, ldap_sbase, LDAP_SCOPE_SUBTREE,
tmpbuf, attrs, 0, &res );
mypluginlink->myfree(tmpbuf);
rc=ldap_count_entries(ld,res);
/* users found */
if (rc > 0)
{
msg=ldap_first_entry(ld, res);
getattr=ldap_first_attribute(ld, msg, &ber);
while (rc > 0)
{
vals=ldap_get_values(ld, msg, getattr);
if (vals != NULL && vals[0] != NULL )
{
/* -------------bandlim----------
create user list */
newuserlist = (*mypluginlink->myalloc)(sizeof (struct userlist));
if (usercaselow > 0)
#ifdef _WIN32
{ CharLower(vals[0]); }
#else
{ lower(vals[0]); }
#endif
newuserlist->user = (*mypluginlink->mystrdup)(vals[0]);
newuserlist->next = NULL;
/*create user rule */
newace = (*mypluginlink->myalloc)(sizeof (struct ace));
memset(newace, 0, sizeof(struct ace));
newace->users = newuserlist;
newace->action = BANDLIM;
/*create user bandlim */
newbandlim =(*mypluginlink->myalloc)(sizeof (struct bandlim));
memset(newbandlim, 0, sizeof(struct bandlim));
newbandlim->rate = bandwidth;
newbandlim->ace = newace;
newbandlim->next = mypluginlink->conf->bandlimiter;
mypluginlink->conf->bandlimiter = newbandlim;
/* -------------counters----------
create user list */
newuserlist = (*mypluginlink->myalloc)(sizeof (struct userlist));
if (usercaselow > 0)
#ifdef _WIN32
{ CharLower(vals[0]); }
#else
{ lower(vals[0]); }
#endif
newuserlist->user = (*mypluginlink->mystrdup)(vals[0]);
newuserlist->next = NULL;
/*create user rule */
newace = (*mypluginlink->myalloc)(sizeof (struct ace));
memset(newace, 0, sizeof(struct ace));
newace->users = newuserlist;
newace->action = COUNTIN;
/*create user counter */
newtrafcount =(*mypluginlink->myalloc)(sizeof (struct trafcount));
memset(newtrafcount, 0, sizeof(struct trafcount));
newtrafcount->ace = newace;
newtrafcount->type=rtype;
newtrafcount->traflimgb =(traflimit/(1024*4));
newtrafcount->traflim = ((traflimit - (newtrafcount->traflimgb*(1024*4)))*(1024*1024));
newtrafcount->comment=(*mypluginlink->mystrdup)("ldapcounters");
newtrafcount->number=0;
tmpbuf=(*mypluginlink->myalloc)(strlen(pat_file)+strlen(ldap_dircount)+strlen(vals[0]));
sprintf(tmpbuf,pat_file,ldap_dircount,vals[0]);
f=NULL;
f=fopen(tmpbuf,"rb");
if(f!=NULL)
{
fseek(f,0,SEEK_SET);
fgets(buf, 256, f);
sscanf(buf,"%10lu %10lu %lu %lu\n",&rcounter.trafgb, &rcounter.traf,
&rcounter.cleared, &rcounter.updated);
newtrafcount->trafgb=rcounter.trafgb;
newtrafcount->traf=rcounter.traf;
newtrafcount->cleared=rcounter.cleared;
newtrafcount->updated=rcounter.updated;
fclose(f);
}
mypluginlink->myfree(tmpbuf);
newtrafcount->next = mypluginlink->conf->trafcounter;
mypluginlink->conf->trafcounter = newtrafcount;
ldap_value_free(vals);
}
msg=ldap_next_entry(ld, msg);
rc--;
}
}/* end if (rc > 0) */
ldap_unbind_s(ld);
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapattrsgroup */
int h_attrsgroup(int argc, unsigned char ** argv)
{
if (argc < 1)
{
fprintf(stderr, "Error in ldapattr: See documentation of ldapauth plugin.\n");
return 1;
}
attrs[0]=mypluginlink->mystrdup(argv[1]);
ldap_group_attr=mypluginlink->mystrdup(argv[2]);
if(argc == 4)
{ usercaselow=atoi(argv[3]); }
return 0;
}
/* --------------------------------------------------------------------------
handle command ldapdircount */
int h_dircount(int argc, unsigned char ** argv)
{
if (argc < 1)
{
fprintf(stderr, "Error in ldapdircount: See documentation of ldapauth plugin.\n");
return 1;
}
ldap_dircount=mypluginlink->mystrdup(argv[1]);
return 0;
}
/*------------------------------- MAIN --------------------------------------
start plugin init */
int start(struct pluginlink * pluginlink, int argc, char** argv)
{
if (already_loaded != 0)
{
pluginlink->myfree(ldap_access);
pluginlink->myfree(ldap_sbase);
pluginlink->myfree(ldap_serv);
pluginlink->myfree(ldap_user);
pluginlink->myfree(ldap_pass);
pluginlink->myfree(ldap_userenv);
pluginlink->myfree(ldap_dircount);
pluginlink->myfree(ldap_group_attr);
pluginlink->myfree(attrs[0]);
return (0);
}
already_loaded = 1;
mypluginlink=pluginlink;
ldap_access=NULL;
ldap_sbase=NULL;
ldap_serv=NULL;
ldap_user=NULL;
ldap_pass=NULL;
ldap_userenv=NULL;
ldap_trafgroup=NULL;
ldap_dircount=NULL;
ldap_group_attr=NULL;
myalwaysauth.authenticate = ldapfunc;
myalwaysauth.authorize = pluginlink->checkACL;
myalwaysauth.desc = "ldap";
myalwaysauth.next = pluginlink->authfuncs->next;
pluginlink->authfuncs->next = &myalwaysauth;
/* add command: ldapconnect ipserv user_serv pass_serv */
ldap_serv_auth_handler.minargs = 3;
ldap_serv_auth_handler.maxargs = 4;
ldap_serv_auth_handler.command = "ldapconnect";
ldap_serv_auth_handler.handler = h_ldapconnect;
ldap_serv_auth_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_serv_auth_handler;
/* add command: ldapaccess cn=internet,cn=users,dc=domain,dc=ru */
ldap_access_handler.minargs = 2;
ldap_access_handler.maxargs = 2;
ldap_access_handler.command = "ldapaccess";
ldap_access_handler.handler = h_access;
ldap_access_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_access_handler;
/* add command: ldapsbase cn=users,dc=domain,dc=ru */
ldap_sbase_handler.minargs = 2;
ldap_sbase_handler.maxargs = 2;
ldap_sbase_handler.command = "ldapsbase";
ldap_sbase_handler.handler = h_sbase;
ldap_sbase_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_sbase_handler;
/* add command: ldapuserenv (cn=users,dc=domain,dc=ru) */
ldap_userenv_handler.minargs = 2;
ldap_userenv_handler.maxargs = 2;
ldap_userenv_handler.command = "ldapuserenv";
ldap_userenv_handler.handler = h_userenv;
ldap_userenv_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_userenv_handler;
/* add command: ldaptrafgroup cn=traf500,cn=users,dc=domain,dc=ru M 500 333 */
ldap_trafgroup_handler.minargs = 5;
ldap_trafgroup_handler.maxargs = 5;
ldap_trafgroup_handler.command = "ldaptrafgroup";
ldap_trafgroup_handler.handler = h_trafgroup;
ldap_trafgroup_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_trafgroup_handler;
/* add command: ldapattr cn memberOf usercaselow=1 */
ldap_attrsgroup_handler.minargs = 3;
ldap_attrsgroup_handler.maxargs = 4;
ldap_attrsgroup_handler.command = "ldapattr";
ldap_attrsgroup_handler.handler = h_attrsgroup;
ldap_attrsgroup_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_attrsgroup_handler;
/* add command: ldapdircount c:\3proxy\ */
ldap_dircount_handler.minargs = 2;
ldap_dircount_handler.maxargs = 2;
ldap_dircount_handler.command = "ldapdircount";
ldap_dircount_handler.handler = h_dircount;
ldap_dircount_handler.next = pluginlink->commandhandlers->next;
pluginlink->commandhandlers->next = &ldap_dircount_handler;
/*create job shedule for processing reload, save counters to file */
memset(&myschedule,0,sizeof(struct schedule));
myschedule.type=MINUTELY;
myschedule.function=savecouters;
myschedule.next = *pluginlink->schedule;
*pluginlink->schedule=&myschedule;
return 0;
}