Verity/Search'97 Security Problems

From: Jay Soffian (jayat_private)
Date: Thu Jul 16 1998 - 22:03:47 PDT

  • Next message: matt: "Re: EMERGENCY: new remote root exploit in UW imapd"

    --Multipart_Fri_Jul_17_01:03:47_1998-1
    Content-Type: text/plain; charset=US-ASCII
    
    
    Sorry about the extra traffic. I probably fired off the veritywrap.c
    sooner than I should have. There was a bug or two in it that I've
    squashed. This is the last version I'll send. We spoke with Verity
    today and they are supposed to have patched binaries out RSN.
    
    j.
    --
    Jay Soffian <jayat_private>                       UNIX Systems Administrator
    404.572.1941                                             Cox Interactive Media
    
    /*
     * Author: Jay Soffian <jayat_private>
     *
     * 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
     *
     * History: o fixed bug with cp not being correct after realloc in
     *            makequery()
     *          o fixed handling of isindex queries
     *
     * 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
     * DON"T FORGET TO RESTRICT ACCESS TO THE *.orig BINARIES, OR THIS
     * WRAPPER DOESN"T DO MUCH GOOD. Use <Files> (apache) or equiv.
     *
     * 16 July 98
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <ctype.h>
    
    #define verity_path_pre  "/path/to/dir/with/verity/s97_cgi/" /* notice trailing slash */
    #define verity_path_post ".orig"
    
    int num_params = 0;
    
    typedef struct
    {
      char *name;
      char *val;
    } param;
    char * keywords = NULL;
    
    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 ("malloc() failed", NULL);
      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,'=')) { /* name = value pairs */
        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 { /* isindex */
        unescape(query);
        keywords = query;
      }
    }
    
    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, offset,  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) {
          while (tot_len > size) size *=2;
          offset = cp - buf;
          buf = realloc(buf, size);
          if (!buf) die ("realloc() failed", NULL);
          cp = buf + offset;
        }
        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);
      if (num_params) query = makequery();
      else query = escape(keywords);
      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_Fri_Jul_17_01:03:47_1998-1
    Content-Type: application/octet-stream
    Content-Disposition: attachment; filename="veritywrap.c"
    Content-Transfer-Encoding: base64
    
    LyoKICogQXV0aG9yOiBKYXkgU29mZmlhbiA8amF5QGNpbWVkaWEuY29tPgogKgogKiBJZGVh
    OiBzOTdfY2dpIGRvZXNuJ3QgY2hlY2sgUmVzdWx0VGVtcGxhdGUgZm9yIGEgdmFsaWQgcGF0
    aCwgc28gaXQKICogaXMgcG9zc2libGUgdG8gcmVhZCBhcmJpdHJhcnkgZmlsZXMgdXNpbmcg
    c29tZXRoaW5nIGxpa2UKICogUmVzdWx0VGVtcGxhdGU9Li4vLi4vLi4vLi4vLi4vLi4vZXRj
    L3Bhc3N3ZAogKiBUaGlzIHNjcmlwdCBkZWNvZGVzIHRoZSBpbnB1dCAoZnJvbSBlaXRoZXIg
    YSBHRVQgb3IgYSBQT1NUKSwKICogY2xlYW5zIHVwIFJlc3VsdFRlbXBsYXRlLCB0aGVuIGV4
    ZWNzIHM5N19jZ2kKICoKICogSGlzdG9yeTogbyBmaXhlZCBidWcgd2l0aCBjcCBub3QgYmVp
    bmcgY29ycmVjdCBhZnRlciByZWFsbG9jIGluCiAqICAgICAgICAgICAgbWFrZXF1ZXJ5KCkK
    ICogICAgICAgICAgbyBmaXhlZCBoYW5kbGluZyBvZiBpc2luZGV4IHF1ZXJpZXMKICoKICog
    dXNhZ2U6IGNvcHkgczk3X2NnaSwgczk3cl9jZ2ksIGV0YyB0byBzOTdfY2dpLm9yaWcKICog
    Y29tcGlsZSB0aGlzIHByb2dyYW0gYW5kIGluc3RhbGwgaXQgYXMgczk3X2NnaSwgczk3cl9j
    Z2ksIGV0YwogKiBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgczk3X2NnaS5vcmlnCiAqIERP
    TiJUIEZPUkdFVCBUTyBSRVNUUklDVCBBQ0NFU1MgVE8gVEhFICoub3JpZyBCSU5BUklFUywg
    T1IgVEhJUwogKiBXUkFQUEVSIERPRVNOIlQgRE8gTVVDSCBHT09ELiBVc2UgPEZpbGVzPiAo
    YXBhY2hlKSBvciBlcXVpdi4KICoKICogMTYgSnVseSA5OAogKi8KCiNpbmNsdWRlIDxzdGRp
    by5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUg
    PHVuaXN0ZC5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KCiNkZWZpbmUgdmVyaXR5X3BhdGhfcHJl
    ICAiL3BhdGgvdG8vZGlyL3dpdGgvdmVyaXR5L3M5N19jZ2kvIiAvKiBub3RpY2UgdHJhaWxp
    bmcgc2xhc2ggKi8KI2RlZmluZSB2ZXJpdHlfcGF0aF9wb3N0ICIub3JpZyIKCmludCBudW1f
    cGFyYW1zID0gMDsKCnR5cGVkZWYgc3RydWN0CnsKICBjaGFyICpuYW1lOwogIGNoYXIgKnZh
    bDsKfSBwYXJhbTsKY2hhciAqIGtleXdvcmRzID0gTlVMTDsKCmNoYXIgbWV0aG9kOwoKI2Rl
    ZmluZSBNQVhfUEFSQU1TIDEwMDAKI2RlZmluZSBHRVQgJ0cnCiNkZWZpbmUgUE9TVCAnUCcK
    CnBhcmFtIHBhcmFtc1tNQVhfUEFSQU1TXTsKCnZvaWQgZGllKGNoYXIgKmxvZ21zZywgY2hh
    ciAqdXNlcm1zZykgewogIGlmICghdXNlcm1zZykgdXNlcm1zZyA9ICJpbnRlcm5hbCBlcnJv
    ciI7CiAgcHJpbnRmKCJDb250ZW50LXR5cGU6IHRleHQvaHRtbFxuXG4iKTsKICBwcmludGYo
    IjxIVE1MPjxIRUFEPlxuIgoJICI8VElUTEU+RXJyb3I8L1RJVExFPlxuIgoJICI8L0hFQUQ+
    PEJPRFk+XG4iCgkgIjxIMT5FcnJvcjwvSDE+XG4iCgkgIkVycm9yOiAlczxQPlxuIgoJICJQ
    bGVhc2UgdHJ5IHlvdXIgcmVxdWVzdCBhZ2Fpbi48UD5cbiIKCSAiPC9CT0RZPjwvSFRNTD5c
    biIsIHVzZXJtc2cpOwogIGZwcmludGYoc3RkZXJyLGxvZ21zZyk7CiAgZXhpdCgwKTsKfQoK
    Y2hhciAqIGVzY2FwZShjaGFyICpzKSB7CiAgcmVnaXN0ZXIgdW5zaWduZWQgY2hhciAqYSwg
    KmI7CiAgY2hhciAqYnVmZmVyOwogIAogIGIgPSBzOwogIGEgPSBidWZmZXIgPSAoY2hhciAq
    KW1hbGxvYygoc3RybGVuKHMpKjMpKzEpOwogIGlmICghYnVmZmVyKSBkaWUgKCJtYWxsb2Mo
    KSBmYWlsZWQiLCBOVUxMKTsKICB3aGlsZSAoKmIpIHsKICAgIGlmICgqYiA8PSAnXHgyMCcg
    fHwgKmIgPj0gJ1x4N2YnIHx8IHN0cmNocigiXCIjJTs8Pj97fXxcXF5+YFtdJiIsICpiKSkg
    ewogICAgICAqYSsrID0gJyUnOwogICAgICBzcHJpbnRmKGEsIiUwWCIsKmIpOwogICAgICBh
    Kz0yOwogICAgICBiKys7CiAgICB9IGVsc2UgewogICAgICAqYSsrID0gKmIrKzsKICAgIH0K
    ICB9CiAgKmEgPSAnXDAnOwogIHJldHVybiBidWZmZXI7Cn0KCgp2b2lkIHVuZXNjYXBlKGNo
    YXIgKnMpCnsKICByZWdpc3RlciB1bnNpZ25lZCBjaGFyICphLCAqYjsKICBpZiAoISpzKSBy
    ZXR1cm47CiAgZm9yICgoYSA9IGIgPSBzKTsoKmEgPSAqYik7ICsrYSwgKytiKSB7CiAgICBz
    d2l0Y2ggKCpiKSB7CiAgICBjYXNlICclJzogCiAgICAgIGlmICgqKGIrMSkgJiYgKihiKzIp
    KSB7CgkqYiA9IHRvdXBwZXIoKmIpOwoJYisrOyAqYSA9ICAqYiA+PSAnQScgPyAoKCgqYiAm
    IDB4ZGYpIC0gJ0EnKSArMTApIDogKmIgLSAnMCc7CgkqYSAqPSAxNjsgIAoJYisrOyAqYSAr
    PSAqYiA+PSAnQScgPyAoKCgqYiAmIDB4ZGYpIC0gJ0EnKSArMTApIDogKmIgLSAnMCc7CiAg
    ICAgIH0KICAgICAgYnJlYWs7CiAgICBjYXNlICcrJzoKICAgICAgKmEgPSAnICc7CiAgICAg
    IGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBjZ2lpbml0KHZvaWQpCnsKICBpbnQgCiAgICBj
    b250ZW50X2xlbmd0aCA9IDAsIAogICAgaSA9IDA7CiAgY2hhciAKICAgICpxdWVyeSA9IE5V
    TEwsIAogICAgKmNwID0gTlVMTCwgCiAgICAqcmVxdWVzdF9tZXRob2QgPSBnZXRlbnYoIlJF
    UVVFU1RfTUVUSE9EIik7CiAgCiAgaWYgKCFyZXF1ZXN0X21ldGhvZCkgZGllKCJObyBSRVFV
    RVNUX01FVEhPRCIsIE5VTEwpOwoKICBpZiAoIXN0cmNtcChyZXF1ZXN0X21ldGhvZCwiUE9T
    VCIpKSB7CiAgICBtZXRob2QgPSBQT1NUOwogICAgaWYoZ2V0ZW52KCJDT05URU5UX1RZUEUi
    KSAmJiAKICAgICAgIHN0cmNtcChnZXRlbnYoIkNPTlRFTlRfVFlQRSIpLCJhcHBsaWNhdGlv
    bi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSkgCiAgICAgIGRpZSgiQ09OVEVOVF9UWVBFIG5v
    dCBhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiLAoJICAiQ09OVEVOVF9UWVBF
    IG11c3QgYmUgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcuIik7CiAgICAK
    ICAgIGlmIChnZXRlbnYoIkNPTlRFTlRfTEVOR1RIIikpIGNvbnRlbnRfbGVuZ3RoID0gYXRv
    aShnZXRlbnYoIkNPTlRFTlRfTEVOR1RIIikpOwogICAgZWxzZSBkaWUoIk5vIENPTlRFTlRf
    TEVOR1RIIiwgTlVMTCk7CgkKICAgIHF1ZXJ5ID0gKGNoYXIgKiltYWxsb2Moc2l6ZW9mKGNo
    YXIpICogY29udGVudF9sZW5ndGggKyAxKTsKICAgIGlmIChxdWVyeSA9PSBOVUxMKSBkaWUg
    KCJtYWxsb2MoKSBmYWlsZWQiLE5VTEwpOwogICAgICAKICAgIGlmIChmcmVhZChxdWVyeSxz
    aXplb2YoY2hhciksY29udGVudF9sZW5ndGgsc3RkaW4pICE9IGNvbnRlbnRfbGVuZ3RoKQog
    ICAgICBkaWUoIlJhbiBvdXQgb2YgaW5wdXQgd2hpbGUgcHJvY2Vzc2luZyByZXF1ZXN0Iiwg
    TlVMTCk7CgkgIAogICAgcXVlcnlbY29udGVudF9sZW5ndGhdID0gJ1wwJzsKICB9IGVsc2Ug
    aWYgKCFzdHJjbXAocmVxdWVzdF9tZXRob2QsIkdFVCIpKSB7CiAgICBtZXRob2QgPSBHRVQ7
    CiAgICBpZiAoZ2V0ZW52KCJRVUVSWV9TVFJJTkciKSkgcXVlcnkgPSBzdHJkdXAoZ2V0ZW52
    KCJRVUVSWV9TVFJJTkciKSk7CiAgICBlbHNlIGRpZSgiTm8gUVVFUllfU1RSSU5HIixOVUxM
    KTsKICAgIGlmICghcXVlcnkpIGRpZSAoIm1hbGxvYygpIGZhaWxlZCIsTlVMTCk7CiAgfSBl
    bHNlIHsKICAgIGRpZSAoIk1ldGhvZCBub3QgR0VUIG5vciBQT1NUIiwgIk1ldGhvZCBtdXN0
    IGJlICdHRVQnIG9yICdQT1NUJy4iKTsKICB9CgogIC8qIGlucHV0IGlzIGluIHF1ZXJ5LiBs
    ZXQncyBwYXJzZSBpdC4gKi8KICBpZiAoc3RyY2hyKHF1ZXJ5LCc9JykpIHsgLyogbmFtZSA9
    IHZhbHVlIHBhaXJzICovCiAgICBwYXJhbXNbaV0ubmFtZSA9IHN0cnRvayhxdWVyeSwgIiYi
    KTsKICAgIHdoaWxlICgoKytpIDwgTUFYX1BBUkFNUykgJiYgKHBhcmFtc1tpXS5uYW1lID0g
    c3RydG9rKE5VTEwsICImIikpKTsgLyogdG9rZW5pemUgKi8KICAgIG51bV9wYXJhbXMgPSBp
    OwogICAgZm9yKGk9MDsgaSA8IG51bV9wYXJhbXM7IGkrKykgewogICAgICBpZiAoKGNwID0g
    c3RyY2hyKHBhcmFtc1tpXS5uYW1lLCAnPScpKSkgewoJKmNwID0gJ1wwJzsKCXBhcmFtc1tp
    XS52YWwgPSBjcCsxOwogICAgICB9IGVsc2UgewoJcGFyYW1zW2ldLnZhbCA9ICIiOwogICAg
    ICB9CiAgICAgIHVuZXNjYXBlKHBhcmFtc1tpXS5uYW1lKTsKICAgICAgdW5lc2NhcGUocGFy
    YW1zW2ldLnZhbCk7CiAgICB9CiAgfSBlbHNlIHsgLyogaXNpbmRleCAqLwogICAgdW5lc2Nh
    cGUocXVlcnkpOwogICAga2V5d29yZHMgPSBxdWVyeTsKICB9Cn0KCnZvaWQgZml4cGF0aCAo
    cmVnaXN0ZXIgY2hhciAqIGEpIAp7CiAgcmVnaXN0ZXIgY2hhciAqYiA9IGE7CgogIGlmICgh
    KmEpIHJldHVybjsKICBpZiAoKmEgPT0gJy8nKSBiKys7CiAgd2hpbGUgKCpiKSAKICAgIGlm
    ICgqYiA9PSAnLicgJiYgKihiKzEpID09ICcuJyAmJiAqKGIrMikgPT0gJy8nKSBiKz0zOwog
    ICAgZWxzZSAqYSsrID0gKmIrKzsKICAqYSA9ICdcMCc7Cn0KCmNoYXIgKiBtYWtlcXVlcnko
    dm9pZCkgCnsKICBjaGFyICogYnVmLCAqY3AsICpuYW1lLCAqdmFsOwogIGludCBpLCBvZmZz
    ZXQsICB0b3RfbGVuID0gMCwgbGVuLCBzaXplID0gMTAyNDsKICBjcCA9IGJ1ZiA9IChjaGFy
    ICopbWFsbG9jKHNpemUpOwogIGlmICghYnVmKSBkaWUgKCJtYWxsb2MoKSBmYWlsZWQiLCBO
    VUxMKTsKICBmb3IgKGk9MDsgaTxudW1fcGFyYW1zOyBpKyspIHsKICAgIG5hbWUgPSBlc2Nh
    cGUocGFyYW1zW2ldLm5hbWUpOwogICAgdmFsICA9IGVzY2FwZShwYXJhbXNbaV0udmFsKTsg
    CiAgICB0b3RfbGVuICs9IGxlbiA9IHN0cmxlbihuYW1lKSArIHN0cmxlbih2YWwpICsgMjsK
    ICAgIGlmICh0b3RfbGVuID4gc2l6ZSkgewogICAgICB3aGlsZSAodG90X2xlbiA+IHNpemUp
    IHNpemUgKj0yOwogICAgICBvZmZzZXQgPSBjcCAtIGJ1ZjsKICAgICAgYnVmID0gcmVhbGxv
    YyhidWYsIHNpemUpOwogICAgICBpZiAoIWJ1ZikgZGllICgicmVhbGxvYygpIGZhaWxlZCIs
    IE5VTEwpOwogICAgICBjcCA9IGJ1ZiArIG9mZnNldDsKICAgIH0KICAgIHNwcmludGYoY3As
    IiVzPSVzJiIsbmFtZSx2YWwpOwogICAgY3ArPWxlbjsgdG90X2xlbiArPWxlbjsKICAgIGZy
    ZWUobmFtZSk7IGZyZWUodmFsKTsKICB9CiAgKihjcC0xKSA9ICdcMCc7CiAgcmV0dXJuIGJ1
    ZjsKfQoKaW50IG1haW4gKGludCBhcmdjLCBjaGFyICoqYXJndikKewogIGludCBzaXplLCBp
    LCBmZFsyXSwgcGlkOwogIGNoYXIgKnF1ZXJ5LCAqcGF0aCwgc3NpemVbMTI4XSwgKmJ1ZjsK
    CiAgcGF0aCA9IHN0cnJjaHIoYXJndlswXSwnLycpOwogIGlmICghcGF0aCkgcGF0aCA9IGFy
    Z3ZbMF07CiAgZWxzZSBwYXRoKys7CiAgYnVmID0gbWFsbG9jKHNpemVvZih2ZXJpdHlfcGF0
    aF9wcmUpICArIAoJICAgICAgIHNpemVvZih2ZXJpdHlfcGF0aF9wb3N0KSArIHN0cmxlbihw
    YXRoKSArIDEpOwogIGlmICghYnVmKSBkaWUoIm1hbGxvYygpIGZhaWxlZCIsIE5VTEwpOwog
    IHNwcmludGYoYnVmLCIlcyVzJXMiLHZlcml0eV9wYXRoX3ByZSwgcGF0aCwgdmVyaXR5X3Bh
    dGhfcG9zdCk7CiAgcGF0aCA9IGJ1ZjsKCiAgY2dpaW5pdCgpOwogIGZvciAoaT0wOyBpPG51
    bV9wYXJhbXM7IGkrKykgCiAgICBpZiAoIXN0cmNhc2VjbXAocGFyYW1zW2ldLm5hbWUsICJS
    ZXN1bHRUZW1wbGF0ZSIpKSAKICAgICAgZml4cGF0aChwYXJhbXNbaV0udmFsKTsKICBpZiAo
    bnVtX3BhcmFtcykgcXVlcnkgPSBtYWtlcXVlcnkoKTsKICBlbHNlIHF1ZXJ5ID0gZXNjYXBl
    KGtleXdvcmRzKTsKICBzaXplID0gc3RybGVuKHF1ZXJ5KTsKICBpZiAobWV0aG9kID09IEdF
    VCkgewogICAgYnVmID0gKGNoYXIqKSBtYWxsb2Moc2l6ZW9mKCJRVUVSWV9TVFJJTkc9Iikg
    KyBzaXplICsgMSk7CiAgICBpZiAoIWJ1ZikgZGllKCJtYWxsb2MoKSBmYWlsZWQiLCBOVUxM
    KTsKICAgIHNwcmludGYoYnVmLCJRVUVSWV9TVFJJTkc9JXMiLHF1ZXJ5KTsKICAgIGlmIChw
    dXRlbnYoYnVmKSkgZGllICgicHV0ZW52KCkgZmFpbGVkIiwgTlVMTCk7CiAgICBleGVjdihw
    YXRoLCBhcmd2KTsKICAgIGRpZSgiZXhlY3YoKSBmYWlsZWQiLCBOVUxMKTsKICB9IGVsc2Ug
    aWYgKG1ldGhvZCA9PSBQT1NUKSB7CiAgICBzcHJpbnRmKHNzaXplLCJDT05URU5UX0xFTkdU
    SD0lZCIsc2l6ZSk7CiAgICBpZiAocHV0ZW52KHNzaXplKSkgZGllKCJwdXRlbnYoKSBmYWls
    ZWQiLCBOVUxMKTsKICAgIGlmICggcGlwZShmZCkgKSBkaWUoInBpcGUoKSBmYWlsZWQiLCBO
    VUxMKTsKICAgIGlmICgocGlkID0gZm9yaygpKSA8IDApIGRpZSgiZm9yaygpIGZhaWxlZCIs
    IE5VTEwpOwogICAgaWYgKCFwaWQpIHsgLyogY2hpbGQgKi8KICAgICAgY2xvc2UoZmRbMV0p
    OwogICAgICBkdXAyKGZkWzBdLDApOwogICAgICBjbG9zZShmZFswXSk7CiAgICAgIGV4ZWN2
    KHBhdGgsIGFyZ3YpOwogICAgICBkaWUoImV4ZWN2KCkgZmFpbGVkIiwgTlVMTCk7CiAgICB9
    IGVsc2UgeyAvKiBwYXJlbnQgKi8KICAgICAgY2xvc2UoZmRbMF0pOwogICAgICBkdXAyKGZk
    WzFdLDEpOwogICAgICBjbG9zZShmZFsxXSk7CiAgICAgIGZ3cml0ZShxdWVyeSxzaXplb2Yo
    Y2hhciksc2l6ZSxzdGRvdXQpOwogICAgICBleGl0KDApOwogICAgfQogIH0gZWxzZSB7CiAg
    ICBkaWUgKCJNZXRob2Qgbm90IEdFVCBub3IgUE9TVCIsICJNZXRob2QgbXVzdCBiZSAnR0VU
    JyBvciAnUE9TVCcuIik7CiAgfQogIGV4aXQoMCk7Cn0K
    
    --Multipart_Fri_Jul_17_01:03:47_1998-1--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:05:47 PDT