这个bbssnd.c是我改过的,将email post直接跳过了,直接调用写文件.
可以判断权限和封Post的情况,能记录错误的密码输入.不过这样
的话要求CGI程序对BBS目录有写权限,是不是容易出安全性的漏洞啊?
  在程序前面有#include bbs.h和chat.h,需要写出正确路径.
  在Redhhat下编译需要-lcrypt.呵呵
/*
    WWW Interface for Firebird Bulletin Board System
    Copyright (C) 1996,1997 Computer Application Studio.
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "bbs2www.h"
#include "/home/bbsadm/bbs_adm/bbs_src/bbs.h"
#include "/home/bbsadm/bbs_adm/bbs_src/chat.h"
struct userec currentuser;
struct boardheader fh;
int
report(str)
char* str;
{
}
char *
Ctime(clock)
time_t *clock;
{
    char *foo;
    char *ptr = ctime(clock);
    if (foo = strchr(ptr, '\n')) *foo = '\0';
    return (ptr);
}
/* define for WWW Chat password attempt */
#define BADLOGINFILE    "logins.bad"
char *
sethomefile( buf, userid, filename )
char    *buf, *userid, *filename;
{
    sprintf( buf, BBSHOME "home/%c/%s/%s", toupper(userid[0]), userid, filename );
    return buf;
}
void
logattempt( uid, frm )
char *uid, *frm;
{
    char        fname[ STRLEN ];
    int         fd, len;
    char        genbuf[255];
    time_t      now=time(0);
    sprintf( genbuf, "%-12.12s  %-30s %s  WWW-POST\n",
                uid, Ctime( &now ), frm );
    len = strlen( genbuf );
    if( (fd = open( BBSHOME BADLOGINFILE, O_WRONLY|O_CREAT|O_APPEND, 0644 )) > 0 ) {
        write( fd, genbuf, len );
        close( fd );
    }
    sethomefile( fname, uid, BADLOGINFILE );
    if( (fd = open( fname, O_WRONLY|O_CREAT|O_APPEND, 0644 )) > 0 ) {
        write( fd, genbuf, len );
        close( fd );
    }
}
char *crypt();
int
checkpasswd(passwd, test)
char *passwd, *test;
{
    static char pwbuf[14];
    char *pw;
        
    strncpy(pwbuf, test, 14);
    pw = crypt(pwbuf, passwd);  
    return (!strcmp(pw, passwd));
}
int
check_userpasswd(user,passwd,fromip)
char *user,*passwd,*fromip;
{
        FILE *rec;
        int found=0;
        char buf[256];
        if((rec=fopen(BBSHOME PASSFILE,"rb"))==NULL)
                return -1;
        while(1)
        {
                if(fread(¤tuser,sizeof(currentuser),1,rec)<=0) break;
                if(currentuser.numlogins<=0)
                        continue;
                if(strcasecmp(user,currentuser.userid))
                        continue;
                else
                {
                        found=1;
                        break;
                }
        }
        fclose(rec);
        if(!found)
                return -1;
        if (checkpasswd(currentuser.passwd, passwd))
                return 1;
        else
        {
                logattempt(currentuser.userid,fromip);
                return -2;
        }
}
char *
setbfile( buf, boardname, filename )
char *buf, *boardname, *filename;
{
    sprintf( buf, BBSHOME "boards/%s/%s", boardname, filename );
    return buf;
}
char *
setbdir( buf, boardname )
char *buf, *boardname;
{
    char dir[STRLEN];
//    strncpy(dir,DOT_DIR,STRLEN);
    dir[STRLEN-1] = '\0';
    sprintf( buf, BBSHOME "boards/%s/.DIR", boardname, dir);
    return buf;
}
int
getcross(filepath,uname,str,nboard,posttitle,fromip)
char *filepath,*uname,*str,*nboard,*posttitle,*fromip;
{
    FILE        *of;
    char        buf[256];
    char        owner[248];
    int         count;
    time_t      now;
    now=time(0);
    of = fopen( filepath, "w" );
        
    if(of ==NULL)
    {
        report("Cross Post error");
        return -1;
    }
    fprintf(of,"发信人: %s (%s), 信区: %s\n",currentuser.userid,currentuser.username,nboard) ;
    fprintf(of,"标  题: %s\n",posttitle) ;
    fprintf(of,"发信站: %s (%24.24s)",STATIONNAME,ctime(&now)) ;
    fprintf(of,", %s\n","转信  ;36mWWW-POST m") ; 
    fprintf(of,"\n");  
    fprintf( of, "%s", str );
    fprintf(of, "\nm;32m※ 来源:." MY_BBS_IP MY_BBS_DOMAIN ".[FROM: %-.20s]m\n",
                fromip);
    fclose( of);
    return 0;
}
int
post_cross(str,nboard,posttitle,owner,fromip)
char* str,*nboard,*posttitle,*owner,*fromip;
{
    struct fileheader postfile ;
    struct shortfile *bp;
    char        filepath[STRLEN], fname[STRLEN];
    char        buf[256],buf4[STRLEN];
    int         fp, count;
    time_t      now;
    memset(&postfile,0,sizeof(postfile)) ;
    now=time(0);
    sprintf(fname,"M.%d.A",now) ;
    setbfile( filepath, nboard, fname );
    count=0;
    while((fp = open(filepath,O_CREAT|O_EXCL|O_WRONLY,0770)) == -1) {
        now++;
        sprintf(fname,"M.%d.A",now) ;
        setbfile( filepath, nboard, fname );
        if (count++ > MAX_POSTRETRY) {
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>post retry failed%s</p>\n",filepath);
        return -1;
        }
    }
    close(fp) ;
    strcpy(postfile.filename,fname) ;
    strncpy(postfile.owner,owner,STRLEN);
    strncpy(postfile.title,posttitle,STRLEN);
    
    setbfile( filepath, nboard, postfile.filename );
    if (getcross( filepath ,owner,str, nboard,posttitle,fromip)==-1) return -1;
    setbdir( buf, nboard );
    if (append_record( buf, &postfile, sizeof(postfile)) == -1) {       
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>post recored fail!</p>\n");
        sprintf(buf,"rm -rf %s",filepath);
        system(buf);
        return -1;
    }
    printf("post sucessful\n");
    return 1;
}
int
cmpbnames( bname, brec)
char *bname;
struct fileheader *brec;
{
    if (!strncmp( bname, brec->filename, sizeof(brec->filename)))
        return 1;
    else
        return 0;
}
int
seek_in_file(filename,seekstr)
char filename[STRLEN],seekstr[STRLEN];
{
    FILE *fp;
    char buf[STRLEN];
    char *namep;
    if ((fp = fopen(filename, "r")) == NULL)
        return 0;
    while (fgets(buf, STRLEN, fp) != NULL) {
        namep = (char *)strtok( buf, ": \n\r\t" );
        if (namep != NULL && strcasecmp(namep, seekstr) == 0 ) {
            fclose(fp);
            return 1;
        }
    }
    fclose(fp);
    return 0;
}
int
usercanpost(bname)
char* bname;
{
    if( strcmp( bname, DEFAULTBOARD ) == 0 )  return 1;
    if (!(currentuser.userlevel&PERM_POST)) return 0;
    if (((fh.level&~PERM_NOZAP) & ~PERM_POSTMASK)==0) return 1;
    return (currentuser.userlevel&((fh.level&~PERM_NOZAP) & ~PERM_POSTMASK));
}
int
deny_me(currboard)
char* currboard;
{
   char buf[STRLEN];
   setbfile(buf,currboard,"deny_users");
   return seek_in_file(buf,currentuser.userid);
}
int
postfile(str,owner,passwd,nboard,posttitle,fromip)
char *str,*owner,*passwd,*nboard,*posttitle,*fromip;
{
    char dbname[STRLEN];
    if (check_userpasswd(owner,passwd,fromip)!=1)
    {
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>用户名或者密码不正确</p>");
        return -1;
    }
    if(search_record(BBSHOME ".BOARDS", &fh, sizeof(fh), cmpbnames, nboard)<=0)
    {
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>%s 讨论区找不到</p>",nboard);
        return -1;
    }
    if (!usercanpost(nboard))
    {
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>你无权力在本讨论区发表文章%x,%x</p>",currentuser.userlevel,fh.level);
        return -1;
    }
    if (deny_me(nboard))
    {
        printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbspst?%s\">\n", nboard);
        printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
        printf("<p>很抱歉,你被板主停止 POST 的权力。</p>");
        return -1;
    }
    return post_cross(str,nboard,posttitle,currentuser.userid,fromip); 
}               
void plustospace(char *str) {
    register int x;
    for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
}
char x2c(char *what) {
    register char digit;
    digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
    return(digit);
}
void unescape_url(char *url) {
    register int x,y;
    for(x=0,y=0;url[y];++x,++y) {
        if((url[x] = url[y]) == '%') {
            url[x] = x2c(&url[y+1]);
            y+=2;
        }
    }
    url[x] = '\0';
}
char *read_form(char *buf, char *str, char *match, int length)
{
   int i;
   buf = strstr(buf, match); 
   if(buf != NULL) 
      buf += strlen(match); 
   else 
   { 
      printf("Error input!\n"); 
      exit(1); 
   }
   for(i = 0; buf[i] != '&'; i++)
   {
      if(i == length -1)
         break;
      str[i] = buf[i];
   }
   str[i] = '\0';    
   plustospace(str);
   unescape_url(str);
}
void main (int argc, char *argv[])
{
   char *buf, *ptr, *iptemp;
   FILE *fout;
   int i, length, exchange = 1;
   char board[15], title[100], username[20], passwd[20];
   char *userip;
   
   userip = (char *)malloc( STRLEN );
   iptemp = (char *)malloc( STRLEN );
   strncpy(userip, getenv("REMOTE_ADDR"), sizeof(char) * STRLEN);
   length = atoi(getenv("CONTENT_LENGTH"));
   ptr = buf = (char *)malloc(length + 1);
   buf[length] = '\0';
   fread(buf, sizeof(char), length, stdin);
   read_form(buf, board, "board=", 15); 
   if(strstr(buf, "exchange=N") != NULL)
      exchange = 0;
   read_form(buf, title, "title=", 100); 
   read_form(buf, username, "username=", 20); 
   read_form(buf, passwd, "passwd=", 20); 
   if((buf = strstr(buf, "text=")) == NULL)
   { 
      printf("Input error!\n"); 
      exit(1); 
   } 
   else 
      buf += 5;
   plustospace(buf);
   unescape_url(buf);
   printf("Content-type: text/html\n\n\n");
   printf("<html>\n");
   printf("<head><title>Welcome to %sBBS</title>\n", SCHOOLSHORT);
   if (username[0] != '\0' && passwd[0] != '\0')
   {  
/*      strcpy(iptemp , "/usr/lib/sendmail -f user@[");
      strcat(iptemp , userip);
      strcat(iptemp , "] bbs");
//      fout = popen("/usr/lib/sendmail -f userip bbs", "w");
      fout = popen(iptemp, "w");
      fprintf(fout, "#name: %s\n", username);
      fprintf(fout, "#password: %s\n", passwd);
      fprintf(fout, "#board: %s\n", board);
      fprintf(fout, "#title: %s\n", title);   
      if(exchange == 0)
         fprintf(fout, "#localpost: \n");
      fprintf(fout, "\n");
      fprintf(fout, "%s\n", userip);
   
      fputs(buf, fout);
      pclose(fout);
*/
        if (postfile(buf,username,passwd,board,title,userip)<0)
        {
           printf("<P>Post Failed!</P>\n");
           printf("</body></html>");
           return;
        }
   }
   free(ptr);
   free(userip);
   free(iptemp);
   printf("<meta http-equiv=Refresh content=\"5; url=/cgi-bin/bbsdoc?N%s\">\n", board);
   printf("<body background=\"%sbackground.gif\">\n", GIFSHOME);
   printf("<P>您的文章现在正被送往BBS系统中,请等待片刻... </P>\n");
   printf("</body></html>");
}
--
FROM 166.111.2.7