/*
area manager for gtic, experimental, 17 March 1998
updated 27 May 1998
accepts standard rfc message via stdin
should be sgid to somegroup for writing to areas_file and users_file
[also read INSTALL file please]
usually called by MTA from /etc/aliases:
filefix: "|/path/gtic -m"
*/
#include <stdio.h>
#include <string.h>
#include "config.h"
void swap_uid_gid();
void area_manager(void)
{
node_t addr;
char *from=NULL,*subj=NULL,*ftn,*ro_ftn,*tmp,*p,*real_address=NULL;
user_t *user; int i; list_t *ltmp; area_t *atmp;
int strtonode_res;
FILE *resp_fp,*help_fp;
char buff[BUFSIZE];
/* find From and Subject */
while(1)
{
if(fgets(buff,sizeof(buff)-1,stdin)==NULL) break;
delcrlf(buff);
/* accept correct RFC message - \n at end of headers */
if(buff[0]==0) break;
if(!strncmp(buff,"From: ",6))
{
if(!from)
{
if(strchr(buff,'<') && strchr(buff,'>'))
{
from=xstrcpy(strchr(buff,'<')+1);
if(strchr(from,'>'))
strchr(from,'>')[0]=0;
}
else
{
from=xstrcpy(buff+6);
}
}
}
else if(!strncmp(buff,"Subject: ",9))
{
subj=xstrcpy(buff+9);
subj=xstrcpy(strtok(buff+9," \t"));
/* xstrcpy return NULL when parameter is NULL -> all ok */
real_address=xstrcpy(strtok(NULL," \t"));
/* TODO: work with non-RFC address here! */
/* break; don't break here */
}
}
if(from==NULL)
{
l_printf("no From in area_manager");
return;
}
if(subj==NULL)
{
l_printf("no Subject in area_manager (From=%s)",from);
/* TODO: write response about "no subject" here */
return;
}
/* determine rfc-ftn-address and convert it to ftn-address */
if(strchr(from,'@')==NULL && strchr(from,'!')==NULL)
{
/* TODO: work with $HOSTNAME here */
l_printf("incorrect address in area_manager (From=%s)",from);
return;
}
if(real_address==NULL)
{
if(strchr(from,'@'))
real_address=strchr(from,'@')+1;
else
real_address=strchr(from,'!')+1;
}
if((strtonode_res=strtonode(&addr,real_address,NULL))!=0)
{
l_printf("parse error in address \"%s\" (%d)\n",
from,strtonode_res);
/* return; */
}
/*printf("DBG: %d:%d/%d.%d\n",addr.zone,addr.net,addr.node,addr.point);
*/
ftn=xstrcpy(nodetoftn(NULL,&addr));
ro_ftn=xstrcat("!",xstrcpy(ftn));
if(response_exec)
{
tmp=xstrcpy(response_exec);
tmp=xstrcat(tmp," \"");
tmp=xstrcat(tmp,from);
tmp=xstrcat(tmp,"\"");
/*printf("DBG: tmp=%s\n",tmp);
*/
swap_uid_gid();
resp_fp=popen(tmp,"w");
swap_uid_gid();
if(resp_fp==NULL)
{
/* TODO: maybe process query with resp_fp == NULL */
e_printf("unable to popen(%s)",tmp);
return;
}
}
fprintf(resp_fp,"Subject: gtic response\n\n");
l_printf("area_manager: processing %s (%s)",ftn,from);
if(resp_fp)
fprintf(resp_fp,"gtic response for \"%s\" (%s)\n\n",from,ftn);
user=list_find_entry(users,ftn);
if(user==NULL)
{
if(resp_fp)
fprintf(resp_fp,"sorry, you absent in our users list\n");
l_printf("link absent in users_file");
}
else if(!strcmp(user->passwd,"*"))
{
if(resp_fp)
fprintf(resp_fp,"sorry, but you rejected from area manager\n");
l_printf("link has \"*\" password - rejected");
}
else if(strcasecmp(user->passwd,subj))
{
if(resp_fp)
fprintf(resp_fp,"sorry, your password is incorrect\n");
l_printf("link give incorrect password");
}
else
{
if(resp_fp)
{
fprintf(resp_fp,"Your current status is: ");
write_flag_tab_to_FILE(resp_fp,user->flags,
(struct flag_tab*)&user_flag_tab);
fprintf(resp_fp,"\n\n");
}
while(1)
{
if(fgets(buff,sizeof(buff)-1,stdin)==NULL) break;
delcrlf(buff);
if(buff[0]==0) continue;
if(strncmp(buff,"--",strlen("--"))==0) break; /* FIXME ? ;-) */
/* skip Message-ID: and X-FTN-* and some ... FIXME (fixed ;-)
if(strncmp(buff,"Message-ID: ",strlen("Message-ID: "))==0) continue;
if(strncmp(buff,"X-FTN-",strlen("X-FTN-"))==0) continue;
if(strncmp(buff,"In-Reply-To:",strlen("In-Reply-To:"))==0) continue;
*/
/* HELP */
if(strcasecmp(buff,"%HELP")==0)
{
if(resp_fp) fprintf(resp_fp,"> %%HELP\n");
if(help_file==NULL)
{
l_printf("%%HELP - help_file not defined in config");
if(resp_fp)
fprintf(resp_fp,"sorry, help file not available on server\n");
}
else
{
l_printf("%%HELP");
if(resp_fp)
{
help_fp=fopen(help_file,"rb");
if(help_fp==NULL)
{
l_printf("%%HELP - unable to open help_file");
fprintf(resp_fp,"sorry, unable to open help file on server\n");
}
else
{
/* yes, we can use buff here */
while(fgets(buff,sizeof(buff)-1,help_fp)!=NULL)
{
/* help_fp may contain text in DOS format, need to convert to
* UNIX format.
*/
delcrlf(buff);
fprintf(resp_fp,"%s\n",buff);
}
fclose(help_fp);
}
}
}
}
/* PAUSE */
else if(strcasecmp(buff,"%PAUSE")==0)
{
l_printf("%%PAUSE");
if(resp_fp) fprintf(resp_fp,"> %%PAUSE\nok\n");
user->flags|=USER_PAUSE;
}
/* RESUME */
else if(strcasecmp(buff,"%RESUME")==0)
{
l_printf("%%RESUME");
if(resp_fp) fprintf(resp_fp,"> %%RESUME\nok\n");
user->flags&=~USER_PAUSE;
}
/* PASSWD */
else if(strncasecmp(buff,"%PASSWD",7)==0)
{
l_printf("%%PASSWD");
if(resp_fp) fprintf(resp_fp,"> %%PASSWD\n");
p=strschr(buff," \t");
if(p)
{
if(user->passwd)
xfree(user->passwd);
user->passwd=xstrcpy(p);
if(resp_fp)
fprintf(resp_fp,"ok\n");
}
else
{
l_printf("EMPTY %%PASSWD string");
if(resp_fp) fprintf(resp_fp,"failed, empty password not allowed\n");
}
}
/* LINKED */
else if(strcasecmp(buff,"%LINKED")==0)
{
l_printf("%%LINKED");
if(resp_fp) fprintf(resp_fp,"> %%LINKED\n");
if(resp_fp) fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
"AREA","WRITE","GROUP","DESCRIPTION");
if(resp_fp) fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
"----","-----","-----","-----------");
for(i=0;i<list_head_max(areas);i++)
{
atmp=list_get_entry(areas,i);
ass(atmp!=NULL);
ltmp=atmp->users;
ass(ltmp!=NULL);
if(list_find(ltmp,ftn))
{
l_printf("[%s]",atmp->name);
if(resp_fp)
{
fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
atmp->name,"yes",atmp->group?atmp->group:"",
atmp->desc?atmp->desc:"");
}
}
else if(list_find(ltmp,ro_ftn))
{
l_printf("[%s]",atmp->name);
if(resp_fp)
{
fprintf(resp_fp,"%-20s %-6s %-10s %s\n",atmp->name,
"",atmp->group?atmp->group:"",atmp->desc?atmp->desc:"");
}
}
}
}
/* LIST and UNLINKED */
else if(strcasecmp(buff,"%LIST")==0 || strcasecmp(buff,"%UNLINKED")==0)
{
int fulllist,linked_mode;
linked_mode=0; /* 0 - unlinked, 1 - readonly, 2 - readwrite */
fulllist=strcasecmp(buff,"%LIST")?0:1;
l_printf("%s",fulllist?"%LIST":"%UNLINKED");
if(resp_fp) fprintf(resp_fp,"> %s\n",fulllist?"%LIST":"%UNLINKED");
if(resp_fp) fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
"AREA","WRITE","GROUP","DESCRIPTION");
if(resp_fp) fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
"----","-----","-----","-----------");
for(i=0;i<list_head_max(areas);i++)
{
atmp=list_get_entry(areas,i);
ass(atmp!=NULL);
ltmp=atmp->users;
ass(ltmp!=NULL);
linked_mode=list_find(ltmp,ro_ftn)?1:0;
if(linked_mode==0) linked_mode=list_find(ltmp,ftn)?2:0;
if(fulllist==0 && linked_mode!=0)
continue;
if(validate_group(atmp,user)==FALSE) continue;
l_printf("[%s]",atmp->name);
if(resp_fp)
{
fprintf(resp_fp,"%-20s %-6s %-10s %s\n",
atmp->name,linked_mode==2?"yes":linked_mode==1?"":
atmp->flags&AREA_READONLY?"":"yes",atmp->group?atmp->group:"",
atmp->desc?atmp->desc:"");
}
}
}
/* unlink from area */
else if(buff[0]=='-')
{
l_printf("%s",buff);
if(resp_fp) fprintf(resp_fp,"> %s\n",buff);
atmp=list_find_entry(areas,buff+1);
if(atmp==NULL)
{
l_printf("not found",buff);
if(resp_fp) fprintf(resp_fp,"area not found\n");
continue;
}
ltmp=atmp->users;
ass(ltmp!=NULL);
if(list_find(ltmp,ftn) || list_find(ltmp,ro_ftn))
{
if(list_find(ltmp,ftn))
list_remove(ltmp,ftn);
else if(list_find(ltmp,ro_ftn))
list_remove(ltmp,ro_ftn);
if(resp_fp) fprintf(resp_fp,"unlinked\n");
}
else
{
l_printf("don't connected");
if(resp_fp) fprintf(resp_fp,"you don't connected to this area\n");
}
}
else
/* link to area */
{
l_printf("%s",buff);
if(resp_fp) fprintf(resp_fp,"> %s\n",buff);
atmp=list_find_entry(areas,buff[0]=='+'?buff+1:buff);
if(atmp==NULL)
{
l_printf("not found",buff);
if(resp_fp) fprintf(resp_fp,"area not found\n");
continue;
}
if(validate_group(atmp,user)==FALSE)
{
l_printf("invalid group",buff);
if(resp_fp) fprintf(resp_fp,"access violation\n");
continue;
}
ltmp=atmp->users;
ass(ltmp!=NULL);
if(list_find(ltmp,ftn) || list_find(ltmp,ro_ftn))
{
l_printf("already connected",buff);
if(resp_fp) fprintf(resp_fp,"already connected\n");
continue;
}
if(atmp->flags & AREA_READONLY)
{
/* link readonly */
list_add(ltmp,ro_ftn,user);
l_printf("(readonly)");
if(resp_fp) fprintf(resp_fp,"connected in readonly mode\n");
}
else
{
/* link read-write */
list_add(ltmp,ftn,user);
l_printf("(read-write)");
if(resp_fp) fprintf(resp_fp,"connected in read-write mode\n");
}
}
}
}
if(resp_fp) pclose(resp_fp);
}
syntax highlighted by Code2HTML, v. 0.9.1