On Sun, Jan 20, 2002 at 11:54:06PM -0500, Thomas Smith wrote: > On Thu, Jan 17, 2002 at 04:42:42PM +0000, Colin Watson wrote: > > Yes, with the current design there really isn't any way to do it well > > (including backwards compatibility), only patch it up. I suggest a > > simple 'templatedir="/foo/bar/baz"' in a trusted place like > > /etc/cgiemail.conf. That has the advantage that it can be parsed by the > > shell, so you can easily set it with debconf and not clobber the old > > setting on upgrades. > > Ok, that sounds as good as anything can be. Go ahead and write the code > (or does there need to be more planning?); I'll do the debconf stuff + > make up a sane default template telling people what to do when cgiemail > stops working. Templates should live in /usr/share/cgiemail, right? > 'Cause they're architecture-independent. > > Don't forget not to let people do something like "GET > /cgi-bin/cgiemail/../../../etc/passwd" :-)
OK, here's some code which I believe does the job. The parser is hardly elegant, but, as the configuration file is presumably in a trusted location, that isn't a security problem. Please try this out and see how it goes. Sorry for the delay in putting this together. --- cgiemail-1.6.orig/cgilib.c +++ cgiemail-1.6/cgilib.c @@ -461,6 +461,59 @@ } int +cgi_read_configuration(formp, templatedir, templatedirlen) + cgi_form *formp; + char *templatedir; + int templatedirlen; +{ + FILE *cfp; + char *linebuf; + int linebuflen; + char *directive = "templatedir=\""; + int directivelen = strlen(directive); + + cfp = fopen(TEMPLATECONF, "r"); + if (!cfp) + { + formp->errcond = 1; + strcpy(formp->errmsg, "500 Could not open configuration file"); + cgi_concat_errno(formp->errmsg); +#ifdef DISCLOSE_PATHS + strncpy(formp->errinfo, TEMPLATECONF, CGI_ERRMSG_MAX); +#else + strcpy(formp->errinfo, "Configuration file could not be accessed."); +#endif /* DISCLOSE_PATHS */ + return(1); + } + + linebuflen = templatedirlen + directivelen + 2; + linebuf = (char *) malloc(linebuflen + 1); + while (fgets(linebuf, linebuflen - 1, cfp)) + { + if (!strncmp(linebuf, directive, directivelen)) + { + char *inquotes = linebuf + directivelen; + char *endquotes = strchr(inquotes, '"'); + if (endquotes) + { + strncpy(templatedir, inquotes, endquotes - inquotes); + return(0); + } + } + } + + formp->errcond = 1; + strcpy(formp->errmsg, + "500 Could not find templatedir in configuration file"); +#ifdef DISCLOSE_PATHS + strncpy(formp->errinfo, TEMPLATECONF, CGI_ERRMSG_MAX); +#else + strcpy(formp->errinfo, "No templatedir=\"...\" line in configuration file."); +#endif /* DISCLOSE_PATHS */ + return(1); +} + +int cgi_template_fill(formp, templatefile) cgi_form *formp; char *templatefile; @@ -468,6 +521,7 @@ FILE *tfp; char varname[CGI_VARNAME_MAX]; char formatstr[CGI_VARNAME_MAX]; + char templatedir[CGI_VARNAME_MAX]; int varnamelen=0, formatlen=0, nfound=0, substitutions=0; int inchar, parse_state=0; @@ -475,6 +529,22 @@ char *envval; #endif /* ENABLE_CGIENV */ + + if (cgi_read_configuration(formp, templatedir, CGI_VARNAME_MAX - 1)) + return(1); + + if (strncmp(templatefile, templatedir, strlen(templatedir)) || + strstr(templatefile, "/../")) + { + formp->errcond=1; + strcpy(formp->errmsg, "403 Template not in valid directory"); +#ifdef DISCLOSE_PATHS + strncpy(formp->errinfo, templatefile, CGI_ERRMSG_MAX); +#else + strcpy(formp->errinfo, "Template file could not be accessed."); +#endif /* DISCLOSE_PATHS */ + return(1); + } /* open template file */ tfp = fopen(templatefile, "r"); --- cgiemail-1.6.orig/debian/rules +++ cgiemail-1.6/debian/rules @@ -38,7 +38,7 @@ configure-stamp: dh_testdir # Add here commands to configure the package. - ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info + ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --sysconfdir=/etc touch configure-stamp --- cgiemail-1.6.orig/Makefile.in +++ cgiemail-1.6/Makefile.in @@ -4,6 +4,11 @@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ +TEMPLATECONF=$(sysconfdir)/cgiemail.conf +CFLAGS := $(CFLAGS) -DTEMPLATECONF="\"$(TEMPLATECONF)\"" + PROG=cgiemail cgiecho cgifile cgicso DISTFILES=README ChangeLog *.[ch] configure *.in testce.txt Cheers, -- Colin Watson [EMAIL PROTECTED]