Newer
Older
if (sess == -1) {
sockprintf(sock,sess,"533 Not in TLS mode");
continue;
}
sockprintf(sock,sess,"200 Accepted");
cryptDestroySession(sess);
sess = -1;
continue;
}
sockprintf(sock,sess,"530 Please login with USER and PASS.");
if(!(user.rest&FLAG('G')))
getuserdat(&scfg, &user); /* get current user data */
if((timeleft=(long)gettimeleft(&scfg,&user,logintime))<1L) {
lprintf(LOG_WARNING,"%04d Out of time, disconnecting",sock);
break;
}
/********************************/
/* These commands require login */
/********************************/
if(!stricmp(cmd, "REIN")) {
lprintf(LOG_INFO,"%04d %s reinitialized control session",sock,user.alias);
user.number=0;
sysop=FALSE;
filepos=0;
sockprintf(sock,sess,"220 Control session re-initialized. Ready for re-login.");
if (sess != -1) {
cryptDestroySession(sess);
sess = -1;
}
got_pbsz = FALSE;
protection = FALSE;
continue;
}
if(!stricmp(cmd, "SITE WHO")) {
for(i=0;i<scfg.sys_nodes && i<scfg.sys_lastnode;i++) {
if((result=getnodedat(&scfg, i+1, &node, 0))!=0) {
sockprintf(sock,sess," Error %d getting data for Telnet Node %d",result,i+1);
continue;
}
if(node.status==NODE_INUSE)
sockprintf(sock,sess," Node %3d: %s",i+1, username(&scfg,node.useron,str));
sockprintf(sock,sess,"211 End (%d active FTP clients)", protected_uint32_value(active_clients));
continue;
}
if(!stricmp(cmd, "SITE VER")) {
if(!stricmp(cmd, "SITE UPTIME")) {
sockprintf(sock,sess,"211 %s (%lu served)",sectostr((uint)(time(NULL)-uptime),str),served);
continue;
}
if(!stricmp(cmd, "SITE RECYCLE") && user.level>=SYSOP_LEVEL) {
startup->recycle_now=TRUE;
sockprintf(sock,sess,"211 server will recycle when not in-use");
continue;
}
if(!stricmp(cmd, "SITE RECYCLE ALL") && user.level>=SYSOP_LEVEL) {
refresh_cfg(&scfg);
sockprintf(sock,sess,"211 ALL servers/nodes will recycle when not in-use");
continue;
}
if(!strnicmp(cmd,"SITE EXEC ",10) && sysop) {
p=cmd+10;
SKIP_WHITESPACE(p);
#ifdef __unix__
fp=popen(p,"r");
if(fp==NULL)
sockprintf(sock,sess,"500 Error %d opening pipe to: %s",errno,p);
else {
while(!feof(fp)) {
if(fgets(str,sizeof(str),fp)==NULL)
break;
}
#else
sockprintf(sock,sess,"200 system(%s) returned %d",p,system(p));
if(!stricmp(cmd, "SITE DEBUG")) {
for(i=0;i<sizeof(socket_debug);i++)
if(socket_debug[i]!=0)
sockprintf(sock,sess,"211-socket %d = 0x%X",i,socket_debug[i]);
sockprintf(sock,sess,"211 End");
continue;
}
if(strnicmp(cmd, "PORT ",5)==0 || strnicmp(cmd, "EPRT ",5)==0 || strnicmp(cmd, "LPRT ",5)==0) {
if(pasv_sock!=INVALID_SOCKET) {
ftp_close_socket(&pasv_sock,&pasv_sess,__LINE__);
}
SKIP_WHITESPACE(p);
if(strnicmp(cmd, "PORT ",5)==0) {
sscanf(p,"%u,%u,%u,%u,%hd,%hd",&h1,&h2,&h3,&h4,&p1,&p2);
data_addr.in.sin_family=AF_INET;
data_addr.in.sin_addr.s_addr=htonl((h1<<24)|(h2<<16)|(h3<<8)|h4);
char delim = *p;
int prot;
memset(&data_addr, 0, sizeof(data_addr));
if(*p)
p++;
prot=strtol(p,NULL,/* base: */10);
switch(prot) {
case 1:
FIND_CHAR(p,delim);
if(*p)
p++;
ap = p;
old_char = *p;
*p = 0;
data_addr.in.sin_addr.s_addr=inet_addr(ap);
*p = old_char;
if (*p)
p++;
data_port=atoi(p);
data_addr.in.sin_family=AF_INET;
break;
case 2:
FIND_CHAR(p,delim);
if(*p)
p++;
strncpy(addr_str, p, sizeof(addr_str));
addr_str[sizeof(addr_str)-1]=0;
tp=addr_str;
FIND_CHAR(tp, delim);
*tp=0;
if(inet_ptoaddr(addr_str, &data_addr, sizeof(data_addr))==NULL) {
lprintf(LOG_WARNING,"%04d Unable to parse IPv6 address %s",sock,addr_str);
sockprintf(sock,sess,"522 Unable to parse IPv6 address (1)");
continue;
}
FIND_CHAR(p,delim);
if(*p)
p++;
data_port=atoi(p);
data_addr.in6.sin6_family=AF_INET6;
break;
default:
lprintf(LOG_WARNING,"%04d UNSUPPORTED protocol: %d", sock, prot);
sockprintf(sock,sess,"522 Network protocol not supported, use (1)");
continue;
}
}
else { /* LPRT */
if(sscanf(p,"%u,%u",&h1, &h2)!=2) {
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
FIND_CHAR(p,',');
if(*p)
p++;
FIND_CHAR(p,',');
if(*p)
p++;
switch(h1) {
case 4: /* IPv4 */
if(h2 != 4) {
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
sockprintf(sock,sess, "501 IPv4 Address is the wrong length");
continue;
}
for(h1 = 0; h1 < h2; h1++) {
((unsigned char *)(&data_addr.in.sin_addr))[h1]=atoi(p);
FIND_CHAR(p,',');
if(*p)
p++;
}
if(atoi(p)!=2) {
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
continue;
}
FIND_CHAR(p,',');
if(*p)
p++;
for(h1 = 0; h1 < 2; h1++) {
((unsigned char *)(&data_port))[1-h1]=atoi(p);
FIND_CHAR(p,',');
if(*p)
p++;
}
data_addr.in.sin_family=AF_INET;
break;
case 6: /* IPv6 */
if(h2 != 16) {
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
sockprintf(sock,sess, "501 IPv6 Address is the wrong length");
continue;
}
for(h1 = 0; h1 < h2; h1++) {
((unsigned char *)(&data_addr.in6.sin6_addr))[h1]=atoi(p);
FIND_CHAR(p,',');
if(*p)
p++;
}
if(atoi(p)!=2) {
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
continue;
}
FIND_CHAR(p,',');
if(*p)
p++;
for(h1 = 0; h1 < 2; h1++) {
((unsigned char *)(&data_port))[1-h1]=atoi(p);
FIND_CHAR(p,',');
if(*p)
p++;
}
data_addr.in6.sin6_family=AF_INET6;
break;
default:
lprintf(LOG_ERR, "Unable to parse LPRT %s", p);
inet_addrtop(&data_addr, data_ip, sizeof(data_ip));
if(data_port< IPPORT_RESERVED) {
lprintf(LOG_WARNING,"%04d !SUSPECTED BOUNCE ATTACK ATTEMPT by %s to %s port %u"
,sock,user.alias
ftp_hacklog("FTP BOUNCE", user.alias, cmd, host_name, &ftp.client_addr);
continue; /* As recommended by RFC2577 */
}
mode="active";
if(stricmp(cmd, "PASV")==0 || stricmp(cmd, "P@SW")==0 /* Kludge required for SMC Barricade V1.2 */
|| stricmp(cmd, "EPSV")==0 || strnicmp(cmd, "EPSV ", 5)==0 || stricmp(cmd, "LPSV")==0) {
if(pasv_sock!=INVALID_SOCKET)
ftp_close_socket(&pasv_sock,&pasv_sess,__LINE__);
if((pasv_sock=ftp_open_socket(pasv_addr.addr.sa_family, SOCK_STREAM))==INVALID_SOCKET) {
lprintf(LOG_WARNING,"%04d !PASV ERROR %d opening socket", sock,ERROR_VALUE);
sockprintf(sock,sess,"425 Error %d opening PASV data socket", ERROR_VALUE);
reuseaddr=FALSE;
if((result=setsockopt(pasv_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&reuseaddr,sizeof(reuseaddr)))!=0) {
lprintf(LOG_WARNING,"%04d !PASV ERROR %d disabling REUSEADDR socket option"
,sock,ERROR_VALUE);
sockprintf(sock,sess,"425 Error %d disabling REUSEADDR socket option", ERROR_VALUE);
continue;
}
if(startup->options&FTP_OPT_DEBUG_DATA)
lprintf(LOG_DEBUG,"%04d PASV DATA socket %d opened",sock,pasv_sock);
for(port=startup->pasv_port_low; port<=startup->pasv_port_high; port++) {
if(startup->options&FTP_OPT_DEBUG_DATA)
lprintf(LOG_DEBUG,"%04d PASV DATA trying to bind socket to port %u"
,sock,port);
if((result=bind(pasv_sock, &pasv_addr.addr,xp_sockaddr_len(&pasv_addr)))==0)
break;
if(port==startup->pasv_port_high)
break;
lprintf(LOG_ERR,"%04d !PASV ERROR %d (%d) binding socket to port %u"
,sock, result, ERROR_VALUE, port);
sockprintf(sock,sess,"425 Error %d binding data socket",ERROR_VALUE);
ftp_close_socket(&pasv_sock,&pasv_sess,__LINE__);
if(startup->options&FTP_OPT_DEBUG_DATA)
lprintf(LOG_DEBUG,"%04d PASV DATA socket %d bound to port %u",sock,pasv_sock,port);
lprintf(LOG_ERR,"%04d !PASV ERROR %d (%d) getting address/port"
,sock, result, ERROR_VALUE);
sockprintf(sock,sess,"425 Error %d getting address/port",ERROR_VALUE);
ftp_close_socket(&pasv_sock,&pasv_sess,__LINE__);
continue;
}
if((result=listen(pasv_sock, 1))!= 0) {
lprintf(LOG_ERR,"%04d !PASV ERROR %d (%d) listening on port %u"
,sock, result, ERROR_VALUE,port);
sockprintf(sock,sess,"425 Error %d listening on data socket",ERROR_VALUE);
ftp_close_socket(&pasv_sock,&pasv_sess,__LINE__);
if(strnicmp(cmd, "EPSV", 4)==0)
sockprintf(sock,sess,"229 Entering Extended Passive Mode (|||%hu|)", port);
else if (stricmp(cmd,"LPSV")==0) {
switch(addr.addr.sa_family) {
case AF_INET:
sockprintf(sock,sess, "228 Entering Long Passive Mode (4, 4, %d, %d, %d, %d, 2, %d, %d)"
,((unsigned char *)&(addr.in.sin_addr))[0]
,((unsigned char *)&(addr.in.sin_addr))[1]
,((unsigned char *)&(addr.in.sin_addr))[2]
,((unsigned char *)&(addr.in.sin_addr))[3]
,((unsigned char *)&(addr.in.sin_port))[0]
,((unsigned char *)&(addr.in.sin_port))[1]);
break;
case AF_INET6:
sockprintf(sock,sess, "228 Entering Long Passive Mode (6, 16, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, 2, %d, %d)"
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
,((unsigned char *)&(addr.in6.sin6_addr))[0]
,((unsigned char *)&(addr.in6.sin6_addr))[1]
,((unsigned char *)&(addr.in6.sin6_addr))[2]
,((unsigned char *)&(addr.in6.sin6_addr))[3]
,((unsigned char *)&(addr.in6.sin6_addr))[4]
,((unsigned char *)&(addr.in6.sin6_addr))[5]
,((unsigned char *)&(addr.in6.sin6_addr))[6]
,((unsigned char *)&(addr.in6.sin6_addr))[7]
,((unsigned char *)&(addr.in6.sin6_addr))[8]
,((unsigned char *)&(addr.in6.sin6_addr))[9]
,((unsigned char *)&(addr.in6.sin6_addr))[10]
,((unsigned char *)&(addr.in6.sin6_addr))[11]
,((unsigned char *)&(addr.in6.sin6_addr))[12]
,((unsigned char *)&(addr.in6.sin6_addr))[13]
,((unsigned char *)&(addr.in6.sin6_addr))[14]
,((unsigned char *)&(addr.in6.sin6_addr))[15]
,((unsigned char *)&(addr.in6.sin6_port))[0]
,((unsigned char *)&(addr.in6.sin6_port))[1]);
break;
}
}
else {
/* Choose IP address to use in passive response */
ip_addr=0;
/* TODO: IPv6 this here lookup */
if(startup->options&FTP_OPT_LOOKUP_PASV_IP
&& (host=gethostbyname(startup->host_name))!=NULL)
ip_addr=ntohl(*((ulong*)host->h_addr_list[0]));
if(ip_addr==0 && (ip_addr=startup->pasv_ip_addr.s_addr)==0)
ip_addr=ntohl(pasv_addr.in.sin_addr.s_addr);
if(startup->options&FTP_OPT_DEBUG_DATA)
lprintf(LOG_INFO,"%04d PASV DATA IP address in response: %u.%u.%u.%u (subject to NAT)"
,sock
,(ip_addr>>24)&0xff
,(ip_addr>>16)&0xff
,(ip_addr>>8)&0xff
,ip_addr&0xff
);
sockprintf(sock,sess,"227 Entering Passive Mode (%u,%u,%u,%u,%hu,%hu)"
,(ip_addr>>24)&0xff
,(ip_addr>>16)&0xff
,(ip_addr>>8)&0xff
,ip_addr&0xff
,(port>>8)&0xff
,port&0xff
);
mode="passive";
continue;
}
if(!strnicmp(cmd, "TYPE ",5)) {
continue;
}
if(!strnicmp(cmd, "ALLO",4)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(*p)
l=atol(p);
else
l=0;
if(local_fsys)
avail=getfreediskspace(local_dir,0);
avail=getfreediskspace(scfg.data_dir,0); /* Change to temp_dir? */
continue;
}
if(!strnicmp(cmd, "REST",4)) {
p=cmd+4;
SKIP_WHITESPACE(p);
if(*p)
filepos=atol(p);
else
filepos=0;
sockprintf(sock,sess,"350 Restarting at %lu. Send STORE or RETRIEVE to initiate transfer."
continue;
}
if(!strnicmp(cmd, "MODE ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
continue;
}
if(!strnicmp(cmd, "STRU ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
continue;
}
if(!stricmp(cmd, "SYST")) {
continue;
}
if(!stricmp(cmd, "ABOR")) {
if(!transfer_inprogress)
lprintf(LOG_WARNING,"%04d %s aborting transfer"
,sock,user.alias);
YIELD(); /* give send thread time to abort */
}
continue;
}
if(!strnicmp(cmd,"SMNT ",5) && sysop && !(startup->options&FTP_OPT_NO_LOCAL_FSYS)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(!stricmp(p,BBS_FSYS_DIR))
local_fsys=FALSE;
else {
if(!direxist(p)) {
lprintf(LOG_WARNING,"%04d !%s attempted to mount invalid directory: %s"
,sock, user.alias, p);
continue;
}
local_fsys=TRUE;
,local_fsys ? "Local" : "BBS");
lprintf(LOG_INFO,"%04d %s mounted %s file system"
,sock, user.alias, local_fsys ? "local" : "BBS");
continue;
}
/****************************/
/* Local File System Access */
/****************************/
if(sysop && local_fsys && !(startup->options&FTP_OPT_NO_LOCAL_FSYS)) {
if(local_dir[0]
&& local_dir[strlen(local_dir)-1]!='\\'
&& local_dir[strlen(local_dir)-1]!='/')
strcat(local_dir,"/");
if(!strnicmp(cmd, "LIST", 4) || !strnicmp(cmd, "NLST", 4)) {
if((fp=fopen(ftp_tmpfname(fname,"lst",sock),"w+b"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d opening %s",sock,errno,fname);
continue;
}
if(!strnicmp(cmd, "LIST", 4))
detail=TRUE;
else
detail=FALSE;
p=cmd+4;
SKIP_WHITESPACE(p);
if(*p=='-') { /* -Letc */
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
filespec=p;
if(*filespec==0)
filespec="*";
SAFEPRINTF2(path,"%s%s",local_dir, filespec);
lprintf(LOG_INFO,"%04d %s listing: %s in %s mode", sock, user.alias, path, mode);
sockprintf(sock,sess, "150 Directory of %s%s", local_dir, filespec);
now=time(NULL);
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));

rswindell
committed
glob(path,0,NULL,&g);
for(i=0;i<(int)g.gl_pathc;i++) {

rswindell
committed
f.size=flength(g.gl_pathv[i]);
t=fdate(g.gl_pathv[i]);
if(localtime_r(&t,&tm)==NULL)
fprintf(fp,"%crw-r--r-- 1 %-8s local %9"PRId32" %s %2d "

rswindell
committed
,isdir(g.gl_pathv[i]) ? 'd':'-'
,ftp_mon[tm.tm_mon],tm.tm_mday);
if(tm.tm_year==cur_tm.tm_year)
fprintf(fp,"%02d:%02d %s\r\n"
,tm.tm_hour,tm.tm_min

rswindell
committed
,getfname(g.gl_pathv[i]));
else
fprintf(fp,"%5d %s\r\n"
,1900+tm.tm_year

rswindell
committed
,getfname(g.gl_pathv[i]));

rswindell
committed
fprintf(fp,"%s\r\n",getfname(g.gl_pathv[i]));

rswindell
committed
globfree(&g);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,-1,FALSE,FALSE,FALSE,NULL,protection);
continue;
} /* Local LIST/NLST */
if(!strnicmp(cmd, "CWD ", 4) || !strnicmp(cmd,"XCWD ",5)) {
if(!strnicmp(cmd,"CWD ",4))
p=cmd+4;
else
p=cmd+5;
SKIP_WHITESPACE(p);
tp=p;
if(*tp=='/' || *tp=='\\') /* /local: and /bbs: are valid */
tp++;
if(!strnicmp(tp,BBS_FSYS_DIR,strlen(BBS_FSYS_DIR))) {
local_fsys=FALSE;
sockprintf(sock,sess,"250 CWD command successful (BBS file system mounted).");
lprintf(LOG_INFO,"%04d %s mounted BBS file system", sock, user.alias);
continue;
}
if(!strnicmp(tp,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR))) {
tp+=strlen(LOCAL_FSYS_DIR); /* already mounted */
p=tp;
}
if(p[1]==':' || !strncmp(p,"\\\\",2))
SAFEPRINTF2(path,"%s%s",root_dir(local_dir),p);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
}
if(!direxist(path)) {
sockprintf(sock,sess,"550 Directory does not exist (%s).",path);
lprintf(LOG_WARNING,"%04d !%s attempted to change to an invalid directory: %s"
,sock, user.alias, path);
} else {
sockprintf(sock,sess,"250 CWD command successful (%s).", local_dir);
}
continue;
} /* Local CWD */
if(!stricmp(cmd,"CDUP") || !stricmp(cmd,"XCUP")) {
SAFEPRINTF(path,"%s..",local_dir);
if(FULLPATH(local_dir,path,sizeof(local_dir))==NULL)
continue;
}
if(!stricmp(cmd, "PWD") || !stricmp(cmd,"XPWD")) {
if(strlen(local_dir)>3)
local_dir[strlen(local_dir)-1]=0; /* truncate '/' */
,local_dir);
continue;
} /* Local PWD */
if(!strnicmp(cmd, "MKD ", 4) || !strnicmp(cmd,"XMKD",4)) {
p=cmd+4;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_NOTICE,"%04d %s created directory: %s",sock,user.alias,fname);
sockprintf(sock,sess,"521 Error %d creating directory: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to create directory: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
if(!strnicmp(cmd, "RMD ", 4) || !strnicmp(cmd,"XRMD",4)) {
p=cmd+4;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_NOTICE,"%04d %s removed directory: %s",sock,user.alias,fname);
sockprintf(sock,sess,"450 Error %d removing directory: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to remove directory: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
if(!strnicmp(cmd, "RNFR ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
SAFEPRINTF2(ren_from,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(ren_from,"%s%s",local_dir,p);
lprintf(LOG_WARNING,"%04d !%s attempted to rename %s (not found)"
,sock,user.alias,ren_from);
} else
sockprintf(sock,sess,"350 File exists, ready for destination name");
continue;
}
if(!strnicmp(cmd, "RNTO ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
if((i=rename(ren_from, fname))==0) {
sockprintf(sock,sess,"250 \"%s\" renamed to \"%s\"",ren_from,fname);
lprintf(LOG_NOTICE,"%04d %s renamed %s to %s",sock,user.alias,ren_from,fname);
sockprintf(sock,sess,"450 Error %d renaming file: %s",i,ren_from);
lprintf(LOG_WARNING,"%04d !%s attempted to rename file: %s (Error %d)"
,sock,user.alias,ren_from,i);
}
continue;
}
if(!strnicmp(cmd, "RETR ", 5) || !strnicmp(cmd,"SIZE ",5)
|| !strnicmp(cmd, "MDTM ",5) || !strnicmp(cmd, "DELE ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(!strnicmp(p,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR)))
p+=strlen(LOCAL_FSYS_DIR); /* already mounted */
if(p[1]==':') /* drive specified */
else if(*p=='/') /* absolute, current drive */
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_WARNING,"%04d !%s file not found: %s",sock,user.alias,fname);
continue;
}
if(!strnicmp(cmd,"SIZE ",5)) {
continue;
}
if(!strnicmp(cmd,"MDTM ",5)) {
t=fdate(fname);
if(gmtime_r(&t,&tm)==NULL) /* specifically use GMT/UTC representation */
,1900+tm.tm_year,tm.tm_mon+1,tm.tm_mday
,tm.tm_hour,tm.tm_min,tm.tm_sec);
continue;
}
if(!strnicmp(cmd,"DELE ",5)) {
if((i=ftp_remove(sock, __LINE__, fname))==0) {
sockprintf(sock,sess,"250 \"%s\" removed successfully.",fname);
lprintf(LOG_NOTICE,"%04d %s deleted file: %s",sock,user.alias,fname);
sockprintf(sock,sess,"450 Error %d removing file: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to delete file: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
/* RETR */
lprintf(LOG_INFO,"%04d %s downloading: %s (%"PRIuOFF" bytes) in %s mode"
,sock,user.alias,fname,flength(fname)
,mode);
sockprintf(sock,sess,"150 Opening BINARY mode data connection for file transfer.");
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,filepos
,&transfer_inprogress,&transfer_aborted,FALSE,FALSE
,&lastactive,&user,&client,-1,FALSE,FALSE,FALSE,NULL,protection);
continue;
} /* Local RETR/SIZE/MDTM */
if(!strnicmp(cmd, "STOR ", 5) || !strnicmp(cmd, "APPE ", 5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(!strnicmp(p,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR)))
p+=strlen(LOCAL_FSYS_DIR); /* already mounted */
if(p[1]==':') /* drive specified */
else if(*p=='/') /* absolute, current drive */
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_INFO,"%04d %s uploading: %s in %s mode", sock,user.alias,fname
,mode);
sockprintf(sock,sess,"150 Opening BINARY mode data connection for file transfer.");
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,filepos
,&transfer_inprogress,&transfer_aborted,FALSE,FALSE
,&lastactive
,&user
,-1 /* dir */
,TRUE /* uploading */
,FALSE /* credits */
,!strnicmp(cmd,"APPE",4) ? TRUE : FALSE /* append */
,NULL /* desc */
);
filepos=0;
continue;
} /* Local STOR */
}
if(!strnicmp(cmd, "LIST", 4) || !strnicmp(cmd, "NLST", 4)) {
dir=curdir;
lib=curlib;
if(cmd[4]!=0)
lprintf(LOG_DEBUG,"%04d LIST/NLST: %s",sock,cmd);
/* path specified? */
p=cmd+4;
SKIP_WHITESPACE(p);
if(*p=='-') { /* -Letc */
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
filespec=p;
if(*filespec==0)
filespec="*";
if((fp=fopen(ftp_tmpfname(fname,"lst",sock),"w+b"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d opening %s",sock,errno,fname);
continue;
}
if(!strnicmp(cmd, "LIST", 4))
detail=TRUE;
else
detail=FALSE;
sockprintf(sock,sess,"150 Opening ASCII mode data connection for /bin/ls.");
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));
if(startup->options&FTP_OPT_INDEX_FILE && startup->index_file_name[0]
&& wildmatchi(startup->index_file_name, filespec, FALSE)) {
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,lib<0 ? scfg.sys_id : dir<0
? scfg.lib[lib]->sname : scfg.dir[dir]->code_suffix
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,startup->index_file_name);
else
fprintf(fp,"%s\r\n",startup->index_file_name);
}
/* HTML Index File */
if(startup->options&FTP_OPT_HTML_INDEX_FILE && startup->html_index_file[0]
&& wildmatchi(startup->html_index_file, filespec, FALSE)) {
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,lib<0 ? scfg.sys_id : dir<0
? scfg.lib[lib]->sname : scfg.dir[dir]->code_suffix
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,startup->html_index_file);
else
fprintf(fp,"%s\r\n",startup->html_index_file);
}
lprintf(LOG_INFO,"%04d %s listing: root in %s mode",sock,user.alias, mode);
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
if(startup->options&FTP_OPT_ALLOW_QWK) {
SAFEPRINTF(str,"%s.qwk",scfg.sys_id);
if(wildmatchi(str, filespec, FALSE)) {
if(detail) {
if(fexistcase(qwkfile)) {
t=fdate(qwkfile);
l=flength(qwkfile);
} else {
t=time(NULL);
l=10240;
};
if(localtime_r(&t,&tm)==NULL)
memset(&tm,0,sizeof(tm));
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,l
,ftp_mon[tm.tm_mon],tm.tm_mday,tm.tm_hour,tm.tm_min
,str);
} else
fprintf(fp,"%s\r\n",str);
}
}
/* File Aliases */

rswindell
committed
sprintf(aliasfile,"%sftpalias.cfg",scfg.ctrl_dir);
if((alias_fp=fopen(aliasfile,"r"))!=NULL) {
while(!feof(alias_fp)) {
if(!fgets(aliasline,sizeof(aliasline),alias_fp))
break;
alias_dir=FALSE;
p=aliasline; /* alias pointer */
SKIP_WHITESPACE(p);
if(*p==';') /* comment */
continue;
tp=p; /* terminator pointer */
FIND_WHITESPACE(tp);
if(*tp) *tp=0;
np=tp+1; /* filename pointer */
SKIP_WHITESPACE(np);
tp=np; /* terminator pointer */
FIND_WHITESPACE(tp);
dp=tp+1; /* description pointer */
SKIP_WHITESPACE(dp);
truncsp(dp);
if(stricmp(dp,BBS_HIDDEN_ALIAS)==0)
continue;
if(!wildmatchi(p, filespec, FALSE))
continue;
/* Virtual Path? */
if(!strnicmp(np,BBS_VIRTUAL_PATH,strlen(BBS_VIRTUAL_PATH))) {
if((dir=getdir(np+strlen(BBS_VIRTUAL_PATH),&user,&client))<0) {
lprintf(LOG_WARNING,"0000 !Invalid virtual path (%s) for %s",np,user.alias);
continue; /* No access or invalid virtual path */
tp=strrchr(np,'/');
if(tp==NULL)
continue;
tp++;
if(*tp) {
SAFEPRINTF2(aliasfile,"%s%s",scfg.dir[dir]->path,tp);
np=aliasfile;
}
else
alias_dir=TRUE;
}
if(!alias_dir && !fexist(np)) {
lprintf(LOG_WARNING,"0000 !Missing aliased file (%s) for %s",np,user.alias);
if(detail) {
if(alias_dir==TRUE) {
fprintf(fp,"drwxrwxrwx 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.lib[scfg.dir[dir]->lib]->sname
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,p);
}
else {
t=fdate(np);
if(localtime_r(&t,&tm)==NULL)
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9"PRIdOFF" %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,flength(np)
,ftp_mon[tm.tm_mon],tm.tm_mday,tm.tm_hour,tm.tm_min
,p);
}
} else
fprintf(fp,"%s\r\n",p);
}
fclose(alias_fp);
}
/* Library folders */
for(i=0;i<scfg.total_libs;i++) {
if(!wildmatchi(scfg.lib[i]->sname, filespec, FALSE))
continue;
fprintf(fp,"dr-xr-xr-x 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,scfg.lib[i]->sname);
else
fprintf(fp,"%s\r\n",scfg.lib[i]->sname);
}
} else if(dir<0) {
lprintf(LOG_INFO,"%04d %s listing: %s library in %s mode"
,sock,user.alias,scfg.lib[lib]->sname,mode);
for(i=0;i<scfg.total_dirs;i++) {
if(scfg.dir[i]->lib!=lib)
continue;
if(i!=(int)scfg.sysop_dir && i!=(int)scfg.upload_dir
if(!wildmatchi(scfg.dir[i]->code_suffix, filespec, FALSE))
continue;
fprintf(fp,"drwxrwxrwx 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.lib[lib]->sname