Verity/Search'97 Security Problems
Date: Thu, 16 Jul 1998 17:04:19 -0400
From: Jay Soffian <jay@CIMEDIA.COM>
To: BUGTRAQ@NETSPACE.ORG
Subject: Re: Verity/Search'97 Security Problems
--Multipart_Thu_Jul_16_17:04:19_1998-1
Content-Type: text/plain; charset=US-ASCII
Here is a wrapper I just wrote to clean up ResultTemplate. It's
working for us. YMMV.
j.
--
Jay Soffian <jay@cimedia.com> UNIX Systems Administrator
404.572.1941 Cox Interactive Media
/*
* Author: Jay Soffian <jay@cimedia.com>
*
* Idea: s97_cgi doesn't check ResultTemplate for a valid path, so it
* is possible to read arbitrary files using something like
* ResultTemplate=../../../../../../etc/passwd
* This script decodes the input (from either a GET or a POST),
* cleans up ResultTemplate, then execs s97_cgi
*
* usage: copy s97_cgi, s97r_cgi, etc to s97_cgi.orig
* compile this program and install it as s97_cgi, s97r_cgi, etc
* in the same directory as s97_cgi.orig
*
* 16 July 98
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#define verity_path_pre "/path/to/directory/with/s97_cgi"
#define verity_path_post ".orig"
int num_params = 0;
typedef struct
{
char *name;
char *val;
} param;
char method;
#define MAX_PARAMS 1000
#define GET 'G'
#define POST 'P'
param params[MAX_PARAMS];
void die(char *logmsg, char *usermsg) {
if (!usermsg) usermsg = "internal error";
printf("Content-type: text/html\n\n");
printf("<HTML><HEAD>\n"
"<TITLE>Error</TITLE>\n"
"</HEAD><BODY>\n"
"<H1>Error</H1>\n"
"Error: %s<P>\n"
"Please try your request again.<P>\n"
"</BODY></HTML>\n", usermsg);
fprintf(stderr,logmsg);
exit(0);
}
char * escape(char *s) {
register unsigned char *a, *b;
char *buffer;
b = s;
a = buffer = (char *)malloc((strlen(s)*3)+1);
if (!buffer) die ("Internal error", "Out of memory while processing request");
while (*b) {
if (*b <= '\x20' || *b >= '\x7f' || strchr("\"#%;<>?{}|\\^~`[]&", *b)) {
*a++ = '%';
sprintf(a,"%0X",*b);
a+=2;
b++;
} else {
*a++ = *b++;
}
}
*a = '\0';
return buffer;
}
void unescape(char *s)
{
register unsigned char *a, *b;
if (!*s) return;
for ((a = b = s);(*a = *b); ++a, ++b) {
switch (*b) {
case '%':
if (*(b+1) && *(b+2)) {
*b = toupper(*b);
b++; *a = *b >= 'A' ? (((*b & 0xdf) - 'A') +10) : *b - '0';
*a *= 16;
b++; *a += *b >= 'A' ? (((*b & 0xdf) - 'A') +10) : *b - '0';
}
break;
case '+':
*a = ' ';
break;
}
}
}
void cgiinit(void)
{
int
content_length = 0,
i = 0;
char
*query = NULL,
*cp = NULL,
*request_method = getenv("REQUEST_METHOD");
if (!request_method) die("No REQUEST_METHOD", NULL);
if (!strcmp(request_method,"POST")) {
method = POST;
if(getenv("CONTENT_TYPE") &&
strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded"))
die("CONTENT_TYPE not application/x-www-form-urlencoded",
"CONTENT_TYPE must be 'application/x-www-form-urlencoded'.");
if (getenv("CONTENT_LENGTH")) content_length = atoi(getenv("CONTENT_LENGTH"));
else die("No CONTENT_LENGTH", NULL);
query = (char *)malloc(sizeof(char) * content_length + 1);
if (query == NULL) die ("malloc() failed",NULL);
if (fread(query,sizeof(char),content_length,stdin) != content_length)
die("Ran out of input while processing request", NULL);
query[content_length] = '\0';
} else if (!strcmp(request_method,"GET")) {
method = GET;
if (getenv("QUERY_STRING")) query = strdup(getenv("QUERY_STRING"));
else die("No QUERY_STRING",NULL);
if (!query) die ("malloc() failed",NULL);
} else {
die ("Method not GET nor POST", "Method must be 'GET' or 'POST'.");
}
/* input is in query. let's parse it. */
if (strchr(query,'=')) {
params[i].name = strtok(query, "&");
while ((++i < MAX_PARAMS) && (params[i].name = strtok(NULL, "&"))); /* tokenize */
num_params = i;
for(i=0; i < num_params; i++) {
if ((cp = strchr(params[i].name, '='))) {
*cp = '\0';
params[i].val = cp+1;
} else {
params[i].val = "";
}
unescape(params[i].name);
unescape(params[i].val);
}
} else {
unescape(query);
params[0].name = "keywords";
params[0].val = query;
num_params = 1;
}
}
void fixpath (register char * a)
{
register char *b = a;
if (!*a) return;
if (*a == '/') b++;
while (*b)
if (*b == '.' && *(b+1) == '.' && *(b+2) == '/') b+=3;
else *a++ = *b++;
*a = '\0';
}
char * makequery(void)
{
char * buf, *cp, *name, *val;
int i, tot_len = 0, len, size = 1024;
cp = buf = (char *)malloc(size);
if (!buf) die ("malloc() failed", NULL);
for (i=0; i<num_params; i++) {
name = escape(params[i].name);
val = escape(params[i].val);
tot_len += len = strlen(name) + strlen(val) + 2;
if (tot_len > size) {
size *=2;
buf = realloc(buf, size);
if (!buf) die ("realloc() failed", NULL);
}
sprintf(cp,"%s=%s&",name,val);
cp+=len; tot_len +=len;
free(name); free(val);
}
*(cp-1) = '\0';
return buf;
}
int main (int argc, char **argv)
{
int size, i, fd[2], pid;
char *query, *path, ssize[128], *buf;
path = strrchr(argv[0],'/');
if (!path) path = argv[0];
else path++;
buf = malloc(sizeof(verity_path_pre) +
sizeof(verity_path_post) + strlen(path) + 1);
if (!buf) die("malloc() failed", NULL);
sprintf(buf,"%s%s%s",verity_path_pre, path, verity_path_post);
path = buf;
cgiinit();
for (i=0; i<num_params; i++)
if (!strcasecmp(params[i].name, "ResultTemplate"))
fixpath(params[i].val);
query = makequery();
size = strlen(query);
if (method == GET) {
buf = (char*) malloc(sizeof("QUERY_STRING=") + size + 1);
if (!buf) die("malloc() failed", NULL);
sprintf(buf,"QUERY_STRING=%s",query);
if (putenv(buf)) die ("putenv() failed", NULL);
execv(path, argv);
die("execv() failed", NULL);
} else if (method == POST) {
sprintf(ssize,"CONTENT_LENGTH=%d",size);
if (putenv(ssize)) die("putenv() failed", NULL);
if ( pipe(fd) ) die("pipe() failed", NULL);
if ((pid = fork()) < 0) die("fork() failed", NULL);
if (!pid) { /* child */
close(fd[1]);
dup2(fd[0],0);
close(fd[0]);
execv(path, argv);
die("execv() failed", NULL);
} else { /* parent */
close(fd[0]);
dup2(fd[1],1);
close(fd[1]);
fwrite(query,sizeof(char),size,stdout);
exit(0);
}
} else {
die ("Method not GET nor POST", "Method must be 'GET' or 'POST'.");
}
exit(0);
}
--Multipart_Thu_Jul_16_17:04:19_1998-1
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="veritywrap.c"
Content-Transfer-Encoding: base64
LyoKICogQXV0aG9yOiBKYXkgU29mZmlhbiA8amF5QGNpbWVkaWEuY29tPgogKgogKiBJZGVh
OiBzOTdfY2dpIGRvZXNuJ3QgY2hlY2sgUmVzdWx0VGVtcGxhdGUgZm9yIGEgdmFsaWQgcGF0
aCwgc28gaXQKICogaXMgcG9zc2libGUgdG8gcmVhZCBhcmJpdHJhcnkgZmlsZXMgdXNpbmcg
c29tZXRoaW5nIGxpa2UKICogUmVzdWx0VGVtcGxhdGU9Li4vLi4vLi4vLi4vLi4vLi4vZXRj
L3Bhc3N3ZAogKiBUaGlzIHNjcmlwdCBkZWNvZGVzIHRoZSBpbnB1dCAoZnJvbSBlaXRoZXIg
YSBHRVQgb3IgYSBQT1NUKSwKICogY2xlYW5zIHVwIFJlc3VsdFRlbXBsYXRlLCB0aGVuIGV4
ZWNzIHM5N19jZ2kKICoKICogdXNhZ2U6IGNvcHkgczk3X2NnaSwgczk3cl9jZ2ksIGV0YyB0
byBzOTdfY2dpLm9yaWcKICogY29tcGlsZSB0aGlzIHByb2dyYW0gYW5kIGluc3RhbGwgaXQg
YXMgczk3X2NnaSwgczk3cl9jZ2ksIGV0YwogKiBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMg
czk3X2NnaS5vcmlnCiAqCiAqIDE2IEp1bHkgOTgKICovCgojaW5jbHVkZSA8c3RkaW8uaD4K
I2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDx1bmlz
dGQuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CgojZGVmaW5lIHZlcml0eV9wYXRoX3ByZSAgIi9w
YXRoL3RvL2RpcmVjdG9yeS93aXRoL3M5N19jZ2kiCiNkZWZpbmUgdmVyaXR5X3BhdGhfcG9z
dCAiLm9yaWciCgppbnQgbnVtX3BhcmFtcyA9IDA7Cgp0eXBlZGVmIHN0cnVjdAp7CiAgY2hh
ciAqbmFtZTsKICBjaGFyICp2YWw7Cn0gcGFyYW07CgpjaGFyIG1ldGhvZDsKCiNkZWZpbmUg
TUFYX1BBUkFNUyAxMDAwCiNkZWZpbmUgR0VUICdHJwojZGVmaW5lIFBPU1QgJ1AnCgpwYXJh
bSBwYXJhbXNbTUFYX1BBUkFNU107Cgp2b2lkIGRpZShjaGFyICpsb2dtc2csIGNoYXIgKnVz
ZXJtc2cpIHsKICBpZiAoIXVzZXJtc2cpIHVzZXJtc2cgPSAiaW50ZXJuYWwgZXJyb3IiOwog
IHByaW50ZigiQ29udGVudC10eXBlOiB0ZXh0L2h0bWxcblxuIik7CiAgcHJpbnRmKCI8SFRN
TD48SEVBRD5cbiIKCSAiPFRJVExFPkVycm9yPC9USVRMRT5cbiIKCSAiPC9IRUFEPjxCT0RZ
PlxuIgoJICI8SDE+RXJyb3I8L0gxPlxuIgoJICJFcnJvcjogJXM8UD5cbiIKCSAiUGxlYXNl
IHRyeSB5b3VyIHJlcXVlc3QgYWdhaW4uPFA+XG4iCgkgIjwvQk9EWT48L0hUTUw+XG4iLCB1
c2VybXNnKTsKICBmcHJpbnRmKHN0ZGVycixsb2dtc2cpOwogIGV4aXQoMCk7Cn0KCmNoYXIg
KiBlc2NhcGUoY2hhciAqcykgewogIHJlZ2lzdGVyIHVuc2lnbmVkIGNoYXIgKmEsICpiOwog
IGNoYXIgKmJ1ZmZlcjsKICAKICBiID0gczsKICBhID0gYnVmZmVyID0gKGNoYXIgKiltYWxs
b2MoKHN0cmxlbihzKSozKSsxKTsKICBpZiAoIWJ1ZmZlcikgZGllICgiSW50ZXJuYWwgZXJy
b3IiLCAiT3V0IG9mIG1lbW9yeSB3aGlsZSBwcm9jZXNzaW5nIHJlcXVlc3QiKTsKICB3aGls
ZSAoKmIpIHsKICAgIGlmICgqYiA8PSAnXHgyMCcgfHwgKmIgPj0gJ1x4N2YnIHx8IHN0cmNo
cigiXCIjJTs8Pj97fXxcXF5+YFtdJiIsICpiKSkgewogICAgICAqYSsrID0gJyUnOwogICAg
ICBzcHJpbnRmKGEsIiUwWCIsKmIpOwogICAgICBhKz0yOwogICAgICBiKys7CiAgICB9IGVs
c2UgewogICAgICAqYSsrID0gKmIrKzsKICAgIH0KICB9CiAgKmEgPSAnXDAnOwogIHJldHVy
biBidWZmZXI7Cn0KCgp2b2lkIHVuZXNjYXBlKGNoYXIgKnMpCnsKICByZWdpc3RlciB1bnNp
Z25lZCBjaGFyICphLCAqYjsKICBpZiAoISpzKSByZXR1cm47CiAgZm9yICgoYSA9IGIgPSBz
KTsoKmEgPSAqYik7ICsrYSwgKytiKSB7CiAgICBzd2l0Y2ggKCpiKSB7CiAgICBjYXNlICcl
JzogCiAgICAgIGlmICgqKGIrMSkgJiYgKihiKzIpKSB7CgkqYiA9IHRvdXBwZXIoKmIpOwoJ
YisrOyAqYSA9ICAqYiA+PSAnQScgPyAoKCgqYiAmIDB4ZGYpIC0gJ0EnKSArMTApIDogKmIg
LSAnMCc7CgkqYSAqPSAxNjsgIAoJYisrOyAqYSArPSAqYiA+PSAnQScgPyAoKCgqYiAmIDB4
ZGYpIC0gJ0EnKSArMTApIDogKmIgLSAnMCc7CiAgICAgIH0KICAgICAgYnJlYWs7CiAgICBj
YXNlICcrJzoKICAgICAgKmEgPSAnICc7CiAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9p
ZCBjZ2lpbml0KHZvaWQpCnsKICBpbnQgCiAgICBjb250ZW50X2xlbmd0aCA9IDAsIAogICAg
aSA9IDA7CiAgY2hhciAKICAgICpxdWVyeSA9IE5VTEwsIAogICAgKmNwID0gTlVMTCwgCiAg
ICAqcmVxdWVzdF9tZXRob2QgPSBnZXRlbnYoIlJFUVVFU1RfTUVUSE9EIik7CiAgCiAgaWYg
KCFyZXF1ZXN0X21ldGhvZCkgZGllKCJObyBSRVFVRVNUX01FVEhPRCIsIE5VTEwpOwoKICBp
ZiAoIXN0cmNtcChyZXF1ZXN0X21ldGhvZCwiUE9TVCIpKSB7CiAgICBtZXRob2QgPSBQT1NU
OwogICAgaWYoZ2V0ZW52KCJDT05URU5UX1RZUEUiKSAmJiAKICAgICAgIHN0cmNtcChnZXRl
bnYoIkNPTlRFTlRfVFlQRSIpLCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQi
KSkgCiAgICAgIGRpZSgiQ09OVEVOVF9UWVBFIG5vdCBhcHBsaWNhdGlvbi94LXd3dy1mb3Jt
LXVybGVuY29kZWQiLAoJICAiQ09OVEVOVF9UWVBFIG11c3QgYmUgJ2FwcGxpY2F0aW9uL3gt
d3d3LWZvcm0tdXJsZW5jb2RlZCcuIik7CiAgICAKICAgIGlmIChnZXRlbnYoIkNPTlRFTlRf
TEVOR1RIIikpIGNvbnRlbnRfbGVuZ3RoID0gYXRvaShnZXRlbnYoIkNPTlRFTlRfTEVOR1RI
IikpOwogICAgZWxzZSBkaWUoIk5vIENPTlRFTlRfTEVOR1RIIiwgTlVMTCk7CgkKICAgIHF1
ZXJ5ID0gKGNoYXIgKiltYWxsb2Moc2l6ZW9mKGNoYXIpICogY29udGVudF9sZW5ndGggKyAx
KTsKICAgIGlmIChxdWVyeSA9PSBOVUxMKSBkaWUgKCJtYWxsb2MoKSBmYWlsZWQiLE5VTEwp
OwogICAgICAKICAgIGlmIChmcmVhZChxdWVyeSxzaXplb2YoY2hhciksY29udGVudF9sZW5n
dGgsc3RkaW4pICE9IGNvbnRlbnRfbGVuZ3RoKQogICAgICBkaWUoIlJhbiBvdXQgb2YgaW5w
dXQgd2hpbGUgcHJvY2Vzc2luZyByZXF1ZXN0IiwgTlVMTCk7CgkgIAogICAgcXVlcnlbY29u
dGVudF9sZW5ndGhdID0gJ1wwJzsKICB9IGVsc2UgaWYgKCFzdHJjbXAocmVxdWVzdF9tZXRo
b2QsIkdFVCIpKSB7CiAgICBtZXRob2QgPSBHRVQ7CiAgICBpZiAoZ2V0ZW52KCJRVUVSWV9T
VFJJTkciKSkgcXVlcnkgPSBzdHJkdXAoZ2V0ZW52KCJRVUVSWV9TVFJJTkciKSk7CiAgICBl
bHNlIGRpZSgiTm8gUVVFUllfU1RSSU5HIixOVUxMKTsKICAgIGlmICghcXVlcnkpIGRpZSAo
Im1hbGxvYygpIGZhaWxlZCIsTlVMTCk7CiAgfSBlbHNlIHsKICAgIGRpZSAoIk1ldGhvZCBu
b3QgR0VUIG5vciBQT1NUIiwgIk1ldGhvZCBtdXN0IGJlICdHRVQnIG9yICdQT1NUJy4iKTsK
ICB9CgogIC8qIGlucHV0IGlzIGluIHF1ZXJ5LiBsZXQncyBwYXJzZSBpdC4gKi8KICBpZiAo
c3RyY2hyKHF1ZXJ5LCc9JykpIHsKICAgIHBhcmFtc1tpXS5uYW1lID0gc3RydG9rKHF1ZXJ5
LCAiJiIpOwogICAgd2hpbGUgKCgrK2kgPCBNQVhfUEFSQU1TKSAmJiAocGFyYW1zW2ldLm5h
bWUgPSBzdHJ0b2soTlVMTCwgIiYiKSkpOyAvKiB0b2tlbml6ZSAqLwogICAgbnVtX3BhcmFt
cyA9IGk7CiAgICBmb3IoaT0wOyBpIDwgbnVtX3BhcmFtczsgaSsrKSB7CiAgICAgIGlmICgo
Y3AgPSBzdHJjaHIocGFyYW1zW2ldLm5hbWUsICc9JykpKSB7CgkqY3AgPSAnXDAnOwoJcGFy
YW1zW2ldLnZhbCA9IGNwKzE7CiAgICAgIH0gZWxzZSB7CglwYXJhbXNbaV0udmFsID0gIiI7
CiAgICAgIH0KICAgICAgdW5lc2NhcGUocGFyYW1zW2ldLm5hbWUpOwogICAgICB1bmVzY2Fw
ZShwYXJhbXNbaV0udmFsKTsKICAgIH0KICB9IGVsc2UgewogICAgdW5lc2NhcGUocXVlcnkp
OwogICAgcGFyYW1zWzBdLm5hbWUgPSAia2V5d29yZHMiOwogICAgcGFyYW1zWzBdLnZhbCA9
IHF1ZXJ5OwogICAgbnVtX3BhcmFtcyA9IDE7CiAgfQp9Cgp2b2lkIGZpeHBhdGggKHJlZ2lz
dGVyIGNoYXIgKiBhKSAKewogIHJlZ2lzdGVyIGNoYXIgKmIgPSBhOwoKICBpZiAoISphKSBy
ZXR1cm47CiAgaWYgKCphID09ICcvJykgYisrOwogIHdoaWxlICgqYikgCiAgICBpZiAoKmIg
PT0gJy4nICYmICooYisxKSA9PSAnLicgJiYgKihiKzIpID09ICcvJykgYis9MzsKICAgIGVs
c2UgKmErKyA9ICpiKys7CiAgKmEgPSAnXDAnOwp9CgpjaGFyICogbWFrZXF1ZXJ5KHZvaWQp
IAp7CiAgY2hhciAqIGJ1ZiwgKmNwLCAqbmFtZSwgKnZhbDsKICBpbnQgaSwgdG90X2xlbiA9
IDAsIGxlbiwgc2l6ZSA9IDEwMjQ7CiAgY3AgPSBidWYgPSAoY2hhciAqKW1hbGxvYyhzaXpl
KTsKICBpZiAoIWJ1ZikgZGllICgibWFsbG9jKCkgZmFpbGVkIiwgTlVMTCk7CiAgZm9yIChp
PTA7IGk8bnVtX3BhcmFtczsgaSsrKSB7CiAgICBuYW1lID0gZXNjYXBlKHBhcmFtc1tpXS5u
YW1lKTsKICAgIHZhbCAgPSBlc2NhcGUocGFyYW1zW2ldLnZhbCk7IAogICAgdG90X2xlbiAr
PSBsZW4gPSBzdHJsZW4obmFtZSkgKyBzdHJsZW4odmFsKSArIDI7CiAgICBpZiAodG90X2xl
biA+IHNpemUpIHsKICAgICAgc2l6ZSAqPTI7CiAgICAgIGJ1ZiA9IHJlYWxsb2MoYnVmLCBz
aXplKTsKICAgICAgaWYgKCFidWYpIGRpZSAoInJlYWxsb2MoKSBmYWlsZWQiLCBOVUxMKTsK
ICAgIH0KICAgIHNwcmludGYoY3AsIiVzPSVzJiIsbmFtZSx2YWwpOwogICAgY3ArPWxlbjsg
dG90X2xlbiArPWxlbjsKICAgIGZyZWUobmFtZSk7IGZyZWUodmFsKTsKICB9CiAgKihjcC0x
KSA9ICdcMCc7CiAgcmV0dXJuIGJ1ZjsKfQoKaW50IG1haW4gKGludCBhcmdjLCBjaGFyICoq
YXJndikKewogIGludCBzaXplLCBpLCBmZFsyXSwgcGlkOwogIGNoYXIgKnF1ZXJ5LCAqcGF0
aCwgc3NpemVbMTI4XSwgKmJ1ZjsKCiAgcGF0aCA9IHN0cnJjaHIoYXJndlswXSwnLycpOwog
IGlmICghcGF0aCkgcGF0aCA9IGFyZ3ZbMF07CiAgZWxzZSBwYXRoKys7CiAgYnVmID0gbWFs
bG9jKHNpemVvZih2ZXJpdHlfcGF0aF9wcmUpICArIAoJICAgICAgIHNpemVvZih2ZXJpdHlf
cGF0aF9wb3N0KSArIHN0cmxlbihwYXRoKSArIDEpOwogIGlmICghYnVmKSBkaWUoIm1hbGxv
YygpIGZhaWxlZCIsIE5VTEwpOwogIHNwcmludGYoYnVmLCIlcyVzJXMiLHZlcml0eV9wYXRo
X3ByZSwgcGF0aCwgdmVyaXR5X3BhdGhfcG9zdCk7CiAgcGF0aCA9IGJ1ZjsKCiAgY2dpaW5p
dCgpOwogIGZvciAoaT0wOyBpPG51bV9wYXJhbXM7IGkrKykgCiAgICBpZiAoIXN0cmNhc2Vj
bXAocGFyYW1zW2ldLm5hbWUsICJSZXN1bHRUZW1wbGF0ZSIpKSAKICAgICAgZml4cGF0aChw
YXJhbXNbaV0udmFsKTsKICBxdWVyeSA9IG1ha2VxdWVyeSgpOwogIHNpemUgPSBzdHJsZW4o
cXVlcnkpOwogIGlmIChtZXRob2QgPT0gR0VUKSB7CiAgICBidWYgPSAoY2hhciopIG1hbGxv
YyhzaXplb2YoIlFVRVJZX1NUUklORz0iKSArIHNpemUgKyAxKTsKICAgIGlmICghYnVmKSBk
aWUoIm1hbGxvYygpIGZhaWxlZCIsIE5VTEwpOwogICAgc3ByaW50ZihidWYsIlFVRVJZX1NU
UklORz0lcyIscXVlcnkpOwogICAgaWYgKHB1dGVudihidWYpKSBkaWUgKCJwdXRlbnYoKSBm
YWlsZWQiLCBOVUxMKTsKICAgIGV4ZWN2KHBhdGgsIGFyZ3YpOwogICAgZGllKCJleGVjdigp
IGZhaWxlZCIsIE5VTEwpOwogIH0gZWxzZSBpZiAobWV0aG9kID09IFBPU1QpIHsKICAgIHNw
cmludGYoc3NpemUsIkNPTlRFTlRfTEVOR1RIPSVkIixzaXplKTsKICAgIGlmIChwdXRlbnYo
c3NpemUpKSBkaWUoInB1dGVudigpIGZhaWxlZCIsIE5VTEwpOwogICAgaWYgKCBwaXBlKGZk
KSApIGRpZSgicGlwZSgpIGZhaWxlZCIsIE5VTEwpOwogICAgaWYgKChwaWQgPSBmb3JrKCkp
IDwgMCkgZGllKCJmb3JrKCkgZmFpbGVkIiwgTlVMTCk7CiAgICBpZiAoIXBpZCkgeyAvKiBj
aGlsZCAqLwogICAgICBjbG9zZShmZFsxXSk7CiAgICAgIGR1cDIoZmRbMF0sMCk7CiAgICAg
IGNsb3NlKGZkWzBdKTsKICAgICAgZXhlY3YocGF0aCwgYXJndik7CiAgICAgIGRpZSgiZXhl
Y3YoKSBmYWlsZWQiLCBOVUxMKTsKICAgIH0gZWxzZSB7IC8qIHBhcmVudCAqLwogICAgICBj
bG9zZShmZFswXSk7CiAgICAgIGR1cDIoZmRbMV0sMSk7CiAgICAgIGNsb3NlKGZkWzFdKTsK
ICAgICAgZndyaXRlKHF1ZXJ5LHNpemVvZihjaGFyKSxzaXplLHN0ZG91dCk7CiAgICAgIGV4
aXQoMCk7CiAgICB9CiAgfSBlbHNlIHsKICAgIGRpZSAoIk1ldGhvZCBub3QgR0VUIG5vciBQ
T1NUIiwgIk1ldGhvZCBtdXN0IGJlICdHRVQnIG9yICdQT1NUJy4iKTsKICB9CiAgZXhpdCgw
KTsKfQo=
--Multipart_Thu_Jul_16_17:04:19_1998-1--