Bug#129104: bug 129104 (buffer overflow + template reading in cgiemail)
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 @@
RELEASE=@CGIEMAIL_RELEASE@
CC=@CC@
+prefix=@prefix@
+sysconfdir=@sysconfdir@
+TEMPLATECONF=$(sysconfdir)/cgiemail.conf
+CFLAGS := $(CFLAGS) -DTEMPLATECONF="\"$(TEMPLATECONF)\""
+
PROG=cgiemail cgiecho cgifile cgicso
DISTFILES=README ChangeLog *.[ch] configure *.in testce.txt
Cheers,
--
Colin Watson [cjwatson@flatline.org.uk]
Reply to: