5280841 [rkeene@sledge /home/rkeene/tmp]$ cat -n wwwftp_cgi.c
  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <dirent.h>
  4 #include <unistd.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <signal.h>
  8 #include <fcntl.h>
  9 #include <stdio.h>
 10 #include <time.h>
 11 #include <pwd.h>
 12 #include <grp.h>
 13 #include "config.h"
 14 #include "md5.h"
 15 #if defined(DEBUG) && !defined(WWWFTP_NO_BT)
 16 #define ENABLE_BACKTRACE
 17 #endif
 18 #include "bt.h"
 19 
 20 extern char **environ;
 21 
 22 #ifndef WWWFTP_TOS_DECLINE
 23 #define WWWFTP_TOS_DECLINE url
 24 #endif
 25 
 26 #ifndef WWWFTP_WEBMASTER
 27 #define WWWFTP_WEBMASTER "webmaster@somewhere"
 28 #endif
 29 
 30 #define WWWFTP_NO_FOOTER 127
 31 
 32 #if DEBUG>=2
 33 extern char **environ;
 34 #endif
 35 
 36 #ifdef WWWFTP_STATIC_DL
 37 void *_dlopen(const char *pathname, int mode) { return(NULL); }
 38 void *_dlsym(void *handle, const char *name) { return(NULL); }
 39 int _dlclose(void *handle) { return(-1); }
 40 #endif
 41 
 42 
 43 char *wwwftp_strsep(char **stringp, const char *delim) {
 44     char *ret = *stringp;
 45 
 46     bt_reg;
 47 
 48     if (ret == NULL) bt_reg_return(NULL); /* grrr */
 49     if ((*stringp = strpbrk(*stringp, delim)) != NULL) {
 50         *((*stringp)++) = '\0';
 51     }                              
 52     bt_reg_return(ret);
 53 }
 54 
 55 
 56 void WWWFtp_HackAttempt(const char *arg, ...) {
 57 /* This should do something, I bet... */
 58     return;
 59 }
 60 
 61 int Header(const char *title) {
 62     static int HeaderSent=0;
 63 
 64     bt_reg;
 65 
 66     if (HeaderSent) bt_reg_return(1);
 67     HeaderSent=1;
 68 
 69     printf("Content-type: text/html\n\n");
 70     printf("<HTML><HEAD><TITLE>");
 71 #ifdef WWWFTP_PAGE_TITLE
 72     printf(WWWFTP_PAGE_TITLE);
 73 #endif
 74     if (title) {
 75         printf(" :: %s", title);
 76     }
 77     printf("</TITLE></HEAD><BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\">\n");
 78 #ifdef WWWFTP_PAGE_HEADER
 79     printf(WWWFTP_PAGE_HEADER);
 80 #endif
 81     printf("<HR WIDTH=\"85%%\">\n");
 82     bt_reg_return(0);
 83 }
 84 
 85 
 86 /* Return value indicates whether or not an error was actually printed */
 87 /* 0 = msg held/not printed, 1 = msg printed, -1 = msg ignored */
 88 #ifdef DEBUG
 89 #define ErrorMsg(x) ErrorMsg_real(x, __FILE__, __func__, __LINE__)
 90 int ErrorMsg_real(const char *msg, const char *file, const char *func, const int line) {
 91 #else
 92 int ErrorMsg(const char *msg) {
 93 #endif
 94     static char HoldBuf[1024]={0};
 95     static int holdit=0;
 96 
 97     bt_reg;
 98 
 99     if (msg==(void *) 1) {
100         holdit=1;
101         bt_reg_return(0);
102     }
103     if (msg==(void *) 2) {
104         holdit=0;
105         msg=NULL;
106         if (strlen(HoldBuf)==0) bt_reg_return(0);
107     }
108     if (!holdit) Header("*** ERROR ***");
109     if (!holdit && strlen(HoldBuf)!=0) {
110         printf("%s", HoldBuf);
111         HoldBuf[0]='\0';
112         bt_reg_return(1);
113     }
114 #ifdef DEBUG
115     if (file && func) {
116         if ((strlen(HoldBuf)+strlen(file)+strlen(func)+42)>=sizeof(HoldBuf)) bt_reg_return(-1);
117         sprintf(HoldBuf, "%s%s:%04i:%s(...): ", HoldBuf, file, line, func);
118     } else if (file) {
119         if ((strlen(HoldBuf)+strlen(file)+38)>=sizeof(HoldBuf)) bt_reg_return(-1);
120         sprintf(HoldBuf, "%s%s:%04i: ", HoldBuf, file, line);
121     }
122 #endif
123     sprintf(HoldBuf, "%s*** AN ERROR HAS OCURRED", HoldBuf);
124     if (msg) {
125         if ((strlen(HoldBuf)+strlen(msg)+6)>=sizeof(HoldBuf)) bt_reg_return(-1);
126         sprintf(HoldBuf, "%s: \"%s\"", HoldBuf, msg);
127     }
128     sprintf(HoldBuf, "%s ***<br>\n", HoldBuf);
129     if (!holdit) {
130         printf("%s", HoldBuf);
131         HoldBuf[0]='\0';
132         fflush(stdout);
133         bt_reg_return(1);
134     }
135     bt_reg_return(0);
136 }
137 
138 int Footer(void) {
139 #if DEBUG>=2
140     int i;
141 #endif
142     bt_reg;
143 
144     Header("Blank page");
145 
146 #if DEBUG>=2
147     printf("<HR WIDTH=\"85%%\">\n");
148     for (i=0;environ[i];i++) {
149         printf("%s<br>\n", environ[i]);
150     }
151     printf("<PRE>%s</PRE>", backtrace_show(1));
152 #endif
153 
154     printf("<HR WIDTH=\"85%%\">\n");
155     printf("Webmaster: <a href=\"mailto:%s\">%s</a><br>\n", WWWFTP_WEBMASTER, WWWFTP_WEBMASTER);
156 #ifdef WWWFTP_HOMEPAGE
157     printf("<A HREF=\"%s\">Home</A>", WWWFTP_HOMEPAGE);
158 #endif
159     printf("</BODY></HTML>\n");
160     bt_reg_return(0);
161 }
162 
163 void sighandler(int sig) {
164     bt_reg;
165 
166     if (sig==11) {
167         Header("URGENT ERROR");
168         printf("Backtrace:<br><PRE>%s</PRE>", backtrace_show(0));
169         Footer();
170         fflush(stdout);
171         exit(0);
172     }
173 }
174 
175 
176 #ifndef MD5bet
177 #define MD5bet "qwertyuiopabcdef"
178 #endif
179 #ifndef MD5UPDATE
180 #define MD5UPDATE(x) if ((buf=(x))!=NULL) MD5Update(&md5c, buf, strlen(buf));
181 #endif
182 char *CalcMagicCookie(char *extra) {
183     struct MD5Context md5c;
184     char *buf, md5text[33], *md5str;
185     md5byte md5sum[16];
186     int i;
187 
188     bt_reg;
189 
190     MD5Init(&md5c);
191     MD5UPDATE(getenv("REMOTE_ADDR"));
192     MD5UPDATE(getenv("REMOTE_HOST"));
193     MD5UPDATE(getenv("SERVER_PORT"));
194     MD5UPDATE(getenv("SERVER_NAME"));
195     MD5UPDATE(getenv("HTTP_USER_AGENT"));
196     MD5UPDATE(getenv("HTTP_ACCEPT"));
197     MD5UPDATE(getenv("HTTP_ACCEPT_CHARSET"));
198     MD5UPDATE(extra);
199     MD5Final(md5sum, &md5c);
200     for (i=0;i<16;i++) {
201         md5text[i*2]=MD5bet[(md5sum[i]&0xf0)>>4];
202         md5text[(i*2)+1]=MD5bet[(md5sum[i]&0xf)];
203     }
204     md5text[32]='\0';
205     md5str=strdup(md5text);
206     bt_reg_return(md5str);
207 }
208 
209 char *WWWFtp_FixStr(const char *str) {
210     char *ret, valstr[3];
211     int i, x, sl, val;
212 
213     sl=strlen(str)+1;
214     if ((ret=malloc(sl))==NULL) return(NULL);
215     for (x=i=0;i<sl;i++,x++) {
216         if (str[i]=='+') { ret[x]=' '; continue; }
217         if (str[i]=='%') {
218             strncpy(valstr, str+i+1, 2);
219             valstr[2]='\0';
220             val=strtol(valstr, NULL, 16);
221             ret[x]=val;
222             i+=2;
223             continue;
224         }
225         ret[x]=str[i];
226     }
227     return(ret);
228 }
229 
230 #ifdef WWWFTP_ASK_USERINFO
231 int WWWFtp_ParseClient(const char *cid, const char *filename, char *name, char *email) {
232     FILE *fp;
233     char lbuf[1024];
234     int found=0;
235 
236     fp=fopen(filename, "r");
237     if (fp) {
238         while (!feof(fp)) {
239             fgets(lbuf, sizeof(lbuf), fp);
240             if (strncmp(lbuf+3,cid,strlen(cid))==0) { found=1; break; }
241         }
242         fclose(fp);
243     }
244 
245     if (found) {
246         return(1);
247     }
248     return(0);
249 }
250 
251 void WWWFtp_SaveClient(const char *cid, const char *qstr, const char *filename) {
252     FILE *fp;
253     char *qbuf, *qbuf_s, *item;
254 
255     /* If we don't have a list, abort. */
256     if (strchr(qstr, '&')==NULL) return;
257 
258     /* Check to see if there's already an entry for this client. */
259     if (WWWFtp_ParseClient(cid,filename,NULL,NULL)!=0) return;
260 
261     /* Parse and add the client to the file. */
262     fp=fopen(filename, "a+");
263     if (!fp) return;
264 
265     qbuf_s=qbuf=strdup(qstr);
266 
267     fprintf(fp, "id=%s ", cid);
268 
269     while ((item=wwwftp_strsep(&qbuf, "&"))!=NULL) {
270         if (strstr(item, cid)==item) continue;
271         fprintf(fp, "\"%s\" ", WWWFtp_FixStr(item));
272     }
273     fprintf(fp, "\n");
274     fclose(fp);
275 
276     return;
277 }
278 #else
279 void WWWFtp_SaveClient(const char *cid, const char *qstr, const char *filename) { return; }
280 int WWWFtp_ParseClient(const char *cid, const char *filename, char *name, char *email) { return(0); }
281 #endif
282 
283 
284 int VerifyClient(const char *cid, const char *file) {
285     FILE *fp=NULL;
286     char *url=WWWFTP_DEFAULTURL;
287     char *purl, *purl_c, buf[1024];
288     int printed=0;
289 
290     bt_reg;
291 
292     Header("Verify Client");
293     if ((purl=getenv("REQUEST_URI"))!=NULL) {
294         if ((purl_c=strchr(purl, '?'))!=NULL) *purl_c='\0';
295         url=purl;
296     }
297     printf("<b>");
298     if (file) {
299         fp=fopen(file, "r");
300         if (fp) {
301             while (1) {
302                 fgets(buf, sizeof(buf), fp);
303                 if (feof(fp)) break;
304                 printf("%s<br>", buf);
305                 printed=1;
306             }
307             fclose(fp);
308         }
309     }
310     if (!printed) {
311         printf("Please read the following TERMS OF SERVICE:<br>");
312         /* What should we do when no disclaimer is specified?  LIE! */
313         printf("(empty)");
314     }
315     printf("</b><br>");
316 #ifdef WWWFTP_ASK_USERINFO
317     printf("<FORM ACTION=\"%s\" METHOD=get>", url);
318     if (WWWFtp_ParseClient(cid, WWWFTP_ASK_USERINFO, NULL, NULL)==0) {
319         printf("<strong>You may also <i>optionally</i> tell us information about yourself.</strong><br>");
320         printf("We will not obtain personally identifying information about you when you visit this site unless you
	choose to provide such information to us.  If you choose to send email to the site webmaster or submit contact
	information, that information will be used soley for contacting you and not stored.<br>");
321         printf("<TABLE>");
322         printf("<TR><TD>Your name:</TD><TD><INPUT TYPE=text NAME=name></TD></TR>");
323         printf("<TR><TD>Your email address:</TD><TD><INPUT TYPE=text NAME=email></TD></TR>");
324         printf("</TABLE>\n");
325     }
326     printf("Do you accept the TERMS OF SERVICE?<br>");
327     printf("<INPUT TYPE=submit NAME=\"%s\" VALUE=\"Yes\">\n", cid);
328     printf("<INPUT TYPE=submit NAME=decline VALUE=\"No\">\n");
329     printf("</FORM>");
330 #else
331     printf("Do you accept the TERMS OF SERVICE?<br>");
332     printf("<a href=\"%s?%s\">YES</a>   <a href=\"%s\">NO</a>", url, cid, WWWFTP_TOS_DECLINE);
333 #endif
334     bt_reg_return(0);
335 }
336 
337 char *GetMimeType(const char *filename) {
338 #if defined(WWWFTP_MIMEFILE) && !defined(WWWFTP_NO_TYPE)
339     static char buf[1024];
340     char *lbuf, *ibuf, *type;
341     char *ext;
342     FILE *fd;
343     int i;
344 
345     bt_reg;
346 
347     if ((ext=strrchr(filename, '.'))==NULL) bt_reg_return(WWWFTP_MIME_DEFAULT);
348     if (!(fd=fopen(WWWFTP_MIMEFILE, "r"))) bt_reg_return(WWWFTP_MIME_DEFAULT);
349     ext++;
350     while (!feof(fd)) {
351         fgets(buf, sizeof(buf)-1, fd);
352         for (i=strlen(buf)-1;i>=0;i--) {
353             if (buf[i]<32) { buf[i]=0; break; }
354         }
355         if (buf[0]=='#') continue;
356         lbuf=buf;
357         type=wwwftp_strsep(&lbuf, "\t ");
358         while ((ibuf=wwwftp_strsep(&lbuf," \t"))!=NULL) {
359             if (strcasecmp(ibuf, ext)==0) bt_reg_return(type);
360         }
361     }
362     fclose(fd);
363 #endif
364     bt_reg_return(WWWFTP_MIME_DEFAULT);
365 }
366 
367 int WWWFtp_Sendfile(const char *file) {
368     struct stat stbuf;
369 #ifndef WWWFTP_NO_TIMEINFO
370     struct tm *lastmodbuf;
371 #endif
372     struct tm *currtimebuf;
373     time_t currtime;
374     char buf[1024];
375     int fd, x;
376     int ftp_wronly=0;
377     char *pwd, *pwd_s;
378 
379     bt_reg;
380 
381     pwd=getcwd(NULL, 256);
382     if (strlen(pwd)<strlen(WWWFTP_ROOT)) {
383         pwd_s="[invalid path]";
384         free(pwd);
385         pwd=NULL;
386     } else {
387         pwd_s=pwd+strlen(WWWFTP_ROOT);
388         if (strcmp(pwd_s,"")==0) {
389             pwd_s="/";
390             free(pwd);
391             pwd=NULL;
392         }
393     }
394 
395 #ifdef WWWFTP_USER
396     if (stbuf.st_uid==WWWFTP_USER && (stbuf.st_mode&S_IWUSR)==S_IWUSR) ftp_wronly=1;
397 #endif
398     if (access(".", W_OK)==0) ftp_wronly=1;
399     if (strstr(pwd_s, "/incoming")) ftp_wronly=1;
400 
401     if (ftp_wronly) bt_reg_return(ErrorMsg("Could not open file"));
402 
403     currtime=time(NULL);
404     if (stat(file, &stbuf)<0) bt_reg_return(ErrorMsg("Could not open file"));
405     if ((fd=open(file, O_RDONLY))<0) bt_reg_return(ErrorMsg("Could not open file"));
406 
407     currtimebuf=localtime(&currtime);
408     strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", currtimebuf);
409     printf("Date: %s\n", buf);
410 
411 #ifndef WWWFTP_NO_TIMEINFO
412     lastmodbuf=localtime(&stbuf.st_mtime);
413     strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", lastmodbuf);
414     printf("Last-Modified: %s\n", buf);
415 #endif
416 
417     printf("Content-Length: %i\n", (int) stbuf.st_size);
418     printf("Content-Type: %s\n\n", GetMimeType(file));
419     while ((x=read(fd, buf, sizeof(buf)))>0) {
420         fwrite(buf, x, 1, stdout);
421     }
422     close(fd);
423     bt_reg_return(WWWFTP_NO_FOOTER);
424 }
425 
426 int strcmp_wwwftp(char **a, char **b) {
427     bt_reg;
428 
429     bt_reg_return(strcmp(*a, *b));
430 }
431 
432 
433 int WWWFtp_ProcessDir(const char *dir, const char *magic) {
434     DIR *dh;
435 #ifdef WWWFTP_SORTDIR
436     char **file_list;
437     int file_list_ents=0,files_len=WWWFTP_MAX_ENTRIES,i;
438 #endif
439     struct dirent *file;
440     struct stat stbuf;
441 #ifndef WWWFTP_NO_TIMEINFO
442     struct tm *tmbuf;
443 #endif
444 #ifndef WWWFTP_NO_USERINFO
445     struct passwd *pwbuf;
446     struct group *grbuf;
447     char *group_s, *username_s;
448 #endif
449     char *fname, *fadd, timestr[64], *username,  *group;
450     char *pwd, *pwd_s;
451     int ftp_wronly=0, writable=0;
452 
453     bt_reg;
454 
455     if (chdir(dir)<0) bt_reg_return(ErrorMsg("Invalid path name."));
456 
457     Header("Directory Viewer");
458 
459     pwd=getcwd(NULL, 256);
460     if (strlen(pwd)<strlen(WWWFTP_ROOT)) {
461         pwd_s="[invalid path]";
462         free(pwd);
463         pwd=NULL;
464     } else {
465         pwd_s=pwd+strlen(WWWFTP_ROOT);
466         if (strcmp(pwd_s,"")==0) {
467             pwd_s="/";
468             free(pwd);
469             pwd=NULL;
470         }
471     }
472 
473 #ifdef WWWFTP_NO_USERINFO
474     group=username="ftp";
475 #endif
476 #ifdef WWWFTP_NO_TIMEINFO
477     strcpy(timestr,"Jan 01 1970 00:00");
478 #endif
479 
480 #ifdef WWWFTP_USER
481     stat(dir, &stbuf);
482     if (stbuf.st_uid==WWWFTP_USER && (stbuf.st_mode&S_IWUSR)==S_IWUSR) ftp_wronly=1;
483 #endif
484     if (access(dir, W_OK)==0) ftp_wronly=1;
485     if (strstr(pwd_s, "/incoming")) ftp_wronly=1;
486 
487     dh=opendir(dir);
488     if (!dh) bt_reg_return(ErrorMsg("Could not open directory."));
489     printf("Directory of %s<br>\n", pwd_s);
490     printf("<PRE>");
491 #ifdef WWWFTP_SORTDIR
492     file_list=malloc(files_len*sizeof(char*));
493     while ((file=readdir(dh))!=NULL) {
494         if (file_list_ents>=files_len) {
495             files_len*=2;
496             if ((file_list=realloc(file_list, files_len*sizeof(char *)))==NULL) bt_reg_return(ErrorMsg("Unable to open
	directory"));
497         }
498         file_list[file_list_ents++]=strdup(file->d_name);
499     }
500     qsort(file_list, file_list_ents, sizeof(char *), (void *) strcmp_wwwftp);
501     for (i=0;i<file_list_ents;i++) {
502         fname=file_list[i];
503 #else
504     while ((file=readdir(dh))!=NULL) {
505         fname=file->d_name;
506 #endif
507         if (strcmp(".", fname)==0 || strcmp("wwwftp.cgi", fname)==0 || strcmp("DISCLAIMER.TXT", fname)==0 ||
	strcmp("WWWFTP_PARMS.TXT", fname)==0) continue;
508         if (stat(fname, &stbuf)<0) continue;
509         if (strcmp("..", fname)!=0 && ftp_wronly) continue;
510         if ((stbuf.st_mode&S_IFDIR)==S_IFDIR) { fadd="/"; } else { fadd=""; }
511 #ifndef WWWFTP_SHOWBAD
512         if (access(fname, R_OK)!=0 || (*fadd=='/' && access(fname, X_OK)!=0)) continue;
513 #endif
514 #ifndef WWWFTP_NO_TIMEINFO
515         tmbuf=localtime(&stbuf.st_mtime);
516         if (tmbuf) {
517             strftime(timestr, sizeof(timestr)-1, "%b %d %Y %H:%M", tmbuf);
518         } else {
519             strcpy(timestr,"[unknown]");
520         }
521 #endif
522 #ifndef WWWFTP_NO_USERINFO
523         pwbuf=getpwuid(stbuf.st_uid);
524         grbuf=getgrgid(stbuf.st_gid);
525         if (pwbuf && pwbuf->pw_name) {
526             username=pwbuf->pw_name;
527             username_s=NULL;
528         } else {
529             username_s=username=malloc(1024);
530             sprintf(username, "%i", (int) stbuf.st_uid);
531         }
532         if (grbuf && grbuf->gr_name) {
533             group=grbuf->gr_name;
534             group_s=NULL;
535         } else {
536             group_s=group=malloc(1024);
537             sprintf(group, "%i", (int) stbuf.st_gid);
538         }
539 #endif
540 
541 
542 #ifndef WWWFTP_NO_WRITE
543         writable=0;
544 #ifdef WWWFTP_USER
545         if (stbuf.st_uid==WWWFTP_USER && (stbuf.st_mode&S_IWUSR)==S_IWUSR) writable=2;
546 #endif
547         if (access(fname, W_OK)==0) writable=2;
548 #endif
549 
550         printf(" %c%s%s%s %-10s %-12s %11i %s <a href=\"%s%s?%s\">%s</a>%s\n",
551             "-d"[(*fadd)/'/'],
552 #ifdef WWWFTP_NO_USERINFO
553             "r--\0r-x\0rw-\0rwx"+((((*fadd)/'/')+writable)*4),
554             "r--\0r-x"+((*fadd/'/')*4),
555             "r--\0r-x"+((*fadd/'/')*4),
556 #else
557             "---\0--x\0-w-\0-wx\0r--\0r-x\0rw-\0rwx"+(((stbuf.st_mode>>6)&0x7)*4),
558             "---\0--x\0-w-\0-wx\0r--\0r-x\0rw-\0rwx"+(((stbuf.st_mode>>3)&0x7)*4),
559             "---\0--x\0-w-\0-wx\0r--\0r-x\0rw-\0rwx"+((stbuf.st_mode&0x7)*4),
560 #endif
561             username,
562             group,
563             (int) stbuf.st_size,
564             timestr,
565             fname, fadd, magic, fname, fadd);
566 #ifndef WWWFTP_NO_USERINFO
567         if (group_s) free(group_s);
568         if (username_s) free(username_s);
569 #endif
570     }
571     printf("</PRE>\n");
572     closedir(dh);
573 
574 #ifndef WWWFTP_NO_WRITE
575     if (ftp_wronly) {
576         printf("<FORM ACTION=\"?%s\" METHOD=\"POST\" ENCTYPE=\"multipart/form-data\">\n", magic);
577         printf("<INPUT TYPE=\"FILE\" NAME=upload>");
578         printf("</FORM>");
579     }
580 #endif
581     bt_reg_return(0);
582 }
583 
584 char *WWWFtp_Dequote(const char *str) {
585     char *ret, *deq;
586     int sl;
587 
588     if ((ret=strdup(str))==NULL) return(NULL);
589     sl=strlen(ret)+1;
590     while ((deq=strchr(ret, '\"'))!=NULL) {
591         memmove(deq, deq+1, sl-(deq-ret)-1);
592     }
593     return(ret);
594 }
595 
596 
597 int WWWFtp_ProcessUL(const char *dir, int length, const char *cid) {
598     char linebuf[1024];
599     char *bound, *cn_type, *file, *ele_name;
600     int inband=0, canwrite=0;
601     int x;
602 
603     bt_reg;
604 
605     if (access(dir, W_OK)==0) canwrite=1;
606 
607     if (!canwrite) bt_reg_return(ErrorMsg("Invalid path name."));
608 
609     if (chdir(dir)<0) bt_reg_return(ErrorMsg("Invalid path name."));
610     if ((cn_type=getenv("CONTENT_TYPE"))==NULL) bt_reg_return(ErrorMsg("Invalid HTTP headers."));
611 
612     bound=strstr(cn_type, "boundary=");
613     if (!bound) bt_reg_return(ErrorMsg("Invalid HTTP headers."));
614     bound+=9;
615     if (strchr(bound, ' ')) *strchr(bound, ' ')='\0';
616 
617 //  Header(NULL);
618 //  printf("len=%i, bound=\"%s\"<br>\n", length, bound);
619     while (1) {
620         fgets(linebuf, sizeof(linebuf), stdin);
621         if (feof(stdin)) break;
622         for (x=strlen(linebuf)-1;x>=0;x--) { if (linebuf[x]>=' ') break; linebuf[x]=0; }
623         if (strncmp(linebuf+2, bound, strlen(bound))==0) { inband=!inband; continue; }
624         if (!inband) continue;
625         if (strncasecmp(linebuf, "content-disposition: form-data;", 31)==0) {
626             if (!(file=strstr(linebuf, "filename="))) continue;
627             if (!(ele_name=strstr(linebuf, "name="))) continue;
628             ele_name+=5; file+=9;
629             if (strpbrk(file, "; ")) *strpbrk(file, "; ")='\0';
630             if (strpbrk(ele_name, "; ")) *strpbrk(ele_name, "; ")='\0';
631             if (strpbrk(file, "/")!=NULL) {
632                 WWWFtp_HackAttempt("Attempt to upload", file, NULL);
633                 bt_reg_return(ErrorMsg("Invalid file specificaiton.  Saving data for review."));
634             }
635             ele_name=WWWFtp_Dequote(ele_name);
636             if (strcmp(ele_name, "upload")!=0) { free(ele_name); continue; }
637             free(ele_name);
638             Header("Upload File");
639 
640             file=WWWFtp_Dequote(file);
641             printf("UPLOAD: file=%s<br>\n", file); 
642 /* XXX: Open, it's safe.. I swear ! */
643 
644 /* We no longer know the file name past the next line, do we need it? */
645             free(file);
646 
647 /* XXX: We need to make it read the data here. */
648 
649 
650             // close(...)
651         }
652     }
653 
654 
655     bt_reg_return(0);
656 }
657 
658 int WWWFtp_SetParms(const char *fname) {
659 /* XXX:  We should process the PARMS file.  We need to figure out what is going to go in there. */
660     return(0);
661 }
662 
663 
664 int WWWFtp(void) {
665     struct stat stbuf;
666     char *path_cp, *ele, *pwd, *path=NULL, *path_tmp=NULL, *disc_file=NULL, *file=NULL, *parms_file=NULL;
667     char *uri=NULL;
668     char *ClientID, *ClientCheck;
669     char *cn_length_str;
670     char *url;
671     int rv=0;
672     int cn_length;
673 
674     bt_reg;
675 
676     url=WWWFTP_DEFAULTURL;
677 
678     ErrorMsg((char *) 1); /* This makes it hold all the error messages */
679 
680 /* In this block (everything before the `error' label) we need to do three things for an error:
681  *   Call ErrorMsg()   To print (eventually) the error
682  *   path=NULL         To prevent the code from attempting to traverse the path
683  *   goto error        To abort further processing on the path
684  */
685 
686     if ((uri=getenv("REQUEST_URI"))!=NULL) {
687         path=strdup(uri);
688         path_tmp=strchr(path, '?');
689         if (path_tmp) *path_tmp='\0';
690     } else {
691         path=getenv("PATH_INFO");
692     }
693     if (path!=NULL) {
694         if (strstr(path, "..")!=NULL) { ErrorMsg("Invalid path name"); path=NULL; goto error; }
695         while (*path && *path=='/') path++;
696         if (chdir(WWWFTP_ROOT)!=0) { ErrorMsg("Invalid path name"); path=NULL; goto error; }
697         if (strcmp(path, "")!=0) {
698             if (stat(path, &stbuf)<0) { ErrorMsg("File does not exist"); path=NULL; goto error; }
699             if ((stbuf.st_mode&S_IFREG)==S_IFREG) {
700                 file=strrchr(path,'/');
701                 if (file) {
702                     *file='\0';
703                     file++;
704                 } else {
705                     file=path;
706                     path=NULL;
707                 }
708             }
709             if (path) {
710                 if (chdir(path)!=0) { ErrorMsg("Invalid path name"); path=NULL; goto error; }
711             }
712         }
713     } else {
714         if (chdir(WWWFTP_ROOT)!=0) { ErrorMsg("Invalid path name"); path=NULL; goto error; }
715     }
716     pwd=getcwd(NULL, 1024);
717     if (strncmp(pwd, WWWFTP_ROOT, strlen(WWWFTP_ROOT))!=0) { ErrorMsg("Invalid path name"); path=NULL; goto error; }
718     free(pwd); pwd=NULL;
719 
720 error:
721     if (path) {
722         chdir(WWWFTP_ROOT);
723         path_cp=strdup(path);
724         while ((ele=wwwftp_strsep(&path_cp,"/"))!=NULL) {
725             if (access("WWWFTP_PARMS.TXT", R_OK)==0) {
726                 if (parms_file) free(parms_file);
727                 pwd=getcwd(NULL, 1024);
728                 parms_file=malloc(strlen(pwd)+strlen("WWWFTP_PARMS.TXT")+5);
729                 sprintf(disc_file, "%s/WWWFTP_PARMS.TXT", pwd);
730                 free(pwd); pwd=NULL;
731             }
732             if (access("DISCLAIMER.TXT", R_OK)==0) {
733                 if (disc_file) free(disc_file);
734                 pwd=getcwd(NULL, 1024);
735                 disc_file=malloc(strlen(pwd)+strlen("DISCLAIMER.TXT")+5);
736                 sprintf(disc_file, "%s/DISCLAIMER.TXT", pwd);
737                 free(pwd); pwd=NULL;
738             }
739             if (chdir(ele)<0) break;
740         }
741     } else {
742         chdir(WWWFTP_ROOT);
743         if (access("WWWFTP_PARMS.TXT", R_OK)==0) {
744             if (parms_file) free(parms_file);
745             pwd=getcwd(NULL, 1024);
746             parms_file=malloc(strlen(pwd)+strlen("WWWFTP_PARMS.TXT")+5);
747             sprintf(disc_file, "%s/WWWFTP_PARMS.TXT", pwd);
748             free(pwd); pwd=NULL;
749         }
750         if (access("DISCLAIMER.TXT", R_OK)==0) {
751             if (disc_file) free(disc_file);
752             pwd=getcwd(NULL, 1024);
753             disc_file=malloc(strlen(pwd)+strlen("DISCLAIMER.TXT")+5);
754             sprintf(disc_file, "%s/DISCLAIMER.TXT", pwd);
755             free(pwd); pwd=NULL;
756         }
757     }
758 
759     /* If we have a config file, process it. */
760     if (parms_file) WWWFtp_SetParms(parms_file);
761 
762 /* One thing I want to do here is find a DISCLAIMER.TXT in the directory structure leading up to here
763  * and add it's path to the "ClientID", this file should also be a parameter for VerifyClient() so it
764  * can have something to read.  This will mean moving the following block down until after the client
765  * path has been followed, which could lead to a compromise of information that the files don't exist
766  * so we may have to remove all the ErrorMsg()'s ... or make a flag so that ErrorMsg() holds them for
767  * a while, until the flag is turned off, which is probably best since it will preserve our debugging
768  * info.
769  *          -- Roy Keene [0180420031349]
770  *  This should now be how it's working
771  *          -- Roy Keene [0220420031212]
772  */
773     ClientID=CalcMagicCookie(disc_file);
774     if ((ClientCheck=getenv("QUERY_STRING"))!=NULL) {
775 #ifdef WWWFTP_ASK_USERINFO
776         if (strstr(ClientCheck, "decline=")!=NULL) {
777             Header("Client denied.");
778             printf("Failed to agree to the terms of service.<br>");
779 #ifdef WWWFTP_TOS_DECLINE
780             printf("Please click <A HREF=\"%s\">here</A> to continue.<br>", WWWFTP_TOS_DECLINE);
781 #endif
782             bt_reg_return(0);
783         }
784 #endif
785         if (strcmp(ClientCheck, "")==0) bt_reg_return(VerifyClient(ClientID, disc_file));
786         if (strstr(ClientCheck, ClientID)==NULL) bt_reg_return(VerifyClient(ClientID, disc_file));
787 #ifdef WWWFTP_ASK_USERINFO
788         WWWFtp_SaveClient(ClientID, ClientCheck, WWWFTP_ASK_USERINFO);
789 #endif
790     } else {
791         bt_reg_return(VerifyClient(ClientID, disc_file));
792     }
793 
794 
795 /* If we got any error messages while we were holding them, print them, and abort further processing. */
796     if ((rv=ErrorMsg((char *) 2))!=0) {
797         bt_reg_return(rv);
798     }
799 
800     if (file) {
801         if (strchr(file, '/')!=NULL) bt_reg_return(ErrorMsg("Invalid file name"));
802         bt_reg_return(WWWFtp_Sendfile(file));
803     } else {
804         if ((cn_length_str=getenv("CONTENT_LENGTH"))!=NULL) {
805             cn_length=atoi(cn_length_str);
806             if (cn_length<=0) bt_reg_return(ErrorMsg("Invalid upload."));
807             bt_reg_return(WWWFtp_ProcessUL(".", cn_length, ClientID));
808         } else {
809             bt_reg_return(WWWFtp_ProcessDir(".", ClientID));
810         }
811     }
812     
813     bt_reg_return(0);
814 }
815 
816 int main(void) {
817     bt_reg;
818 #ifdef WWWFTP_USER
819     if (setuid(WWWFTP_USER)<0) {
820         if (getuid()!=WWWFTP_USER) {
821             ErrorMsg("Could not setup FTP.");
822             Footer();
823             bt_reg_return(0);
824         }
825     }
826 #endif
827     signal(SIGSEGV, sighandler);
828 
829     if (WWWFtp()!=WWWFTP_NO_FOOTER) Footer();
830     bt_reg_return(0);
831 }
5280842 [rkeene@sledge /home/rkeene/tmp]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2018-08-03 15:31:59