这个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