A PHP Error was encountered

Severity: 8192

Message: Function create_function() is deprecated

Filename: geshi/geshi.php

Line Number: 4698

Backtrace:

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/geshi/geshi.php
Line: 4698
Function: _error_handler

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/geshi/geshi.php
Line: 4621
Function: _optimize_regexp_list_tokens_to_string

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/geshi/geshi.php
Line: 1655
Function: optimize_regexp_list

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/geshi/geshi.php
Line: 2029
Function: optimize_keyword_group

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/geshi/geshi.php
Line: 2168
Function: build_parse_cache

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/libraries/Process.php
Line: 45
Function: parse_code

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/models/Pastes.php
Line: 517
Function: syntax

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/application/controllers/Main.php
Line: 693
Function: getPaste

File: /home/httpd/vhosts/scratchbook.ch/geopaste.scratchbook.ch/index.php
Line: 315
Function: require_once

tinyldap.c - Stikked
From leitner, 11 Years ago, written in C.
Embed
  1. #define _FILE_OFFSET_BITS 64
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "str.h"
  6. #include "case.h"
  7. #include "byte.h"
  8. #include "buffer.h"
  9. #include "ldap.h"
  10. #include "mduptab.h"
  11. #include "ldif.h"
  12. #include "open.h"
  13. #include "mmap.h"
  14. #include "uint32.h"
  15. #include "auth.h"
  16. #include "bstr.h"
  17. #ifdef STANDALONE
  18. #include "socket.h"
  19. #include "ip6.h"
  20. #ifdef __FreeBSD__
  21. #include <sys/types.h>
  22. #include <sys/wait.h>
  23. #else
  24. #include <wait.h>
  25. #endif
  26. #endif
  27. #include "case.h"
  28. #include <signal.h>
  29. #include "uint16.h"
  30. #include "acl.h"
  31. #include <ctype.h>
  32. #include <assert.h>
  33. #include <fcntl.h>
  34. #include "errmsg.h"
  35. #include "textcode.h"
  36. #include "fmt.h"
  37. #include <sys/socket.h>
  38. #include <netinet/in.h>
  39. #include <netinet/tcp.h>
  40.  
  41. #ifdef DEBUG
  42. #include <sys/poll.h>
  43. #define verbose 1
  44. #define debug 1
  45. #else
  46. #define verbose 0
  47. #define debug 0
  48. #endif
  49.  
  50. #define HUGE_SIZE_FOR_SANITY_CHECKS 1024*1024
  51.  
  52. /* basic operation: the whole data file is mmapped read-only at the beginning and stays there. */
  53. char* map;      /* where the file is mapped */
  54. size_t filelen; /* how many bytes are mapped (the whole file) */
  55. uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
  56.                 /* these are the first values from the file, see the file "FORMAT"
  57.                  * basic counts and offsets needed to calculate the positions of
  58.                  * the data structures in the file. */
  59.  
  60.  
  61. /* We do queries with indexes by evaluating all the filters (subexpressions) that can be
  62.  * answered with an index, and then getting a bit vector, one bit for each record. */
  63.  
  64. /* how many longs are needed to have one bit for each record? */
  65. uint32 record_set_length;
  66.  
  67. /* some pre-looked-up attribute offsets to speed up ldap_match_mapped */
  68. uint32 dn_ofs,objectClass_ofs,userPassword_ofs,any_ofs;
  69.  
  70.  
  71.  
  72.  
  73. /* journal hash structures */
  74. struct attribute2 {
  75.   unsigned char* a,* v;
  76. };
  77.  
  78. /* we have chained hashing (that's what next is for), but we also have a linear list of
  79.  * all the entries in the journal (that's what linear is for), so we can traverse the
  80.  * entries in the same order they were put in the journal */
  81. struct hashnode {
  82.   struct hashnode* next,* linear;
  83.   unsigned long hashval;
  84.   unsigned char* dn;
  85.   size_t n;
  86.   int overwrite;
  87.   struct attribute2 a[1];
  88. };
  89.  
  90.  
  91.  
  92.  
  93. /* to avoid string compares, we don't work with char* but with uint32 (offsets within
  94.  * the mmapped file) whenever it's about values that will be mentioned in the file, such
  95.  * as attribute names.  So, for each filter we get sent, we look up the attributes in the
  96.  * file, so we have the offsets to save the strcmp later.
  97.  * In the same step, we also get the attribute flags.  tinyldap does not have LDAP
  98.  * schemas, so it does not know which attributes are case sensitive and which aren't.  So,
  99.  * this is saved in a flag, which is currently set by addindex when a case insensitive
  100.  * index is created. */
  101.  
  102. /* This routine is called when we got a Filter and now want to look up the offsets for
  103.  * each attribute mentioned in it */
  104.  
  105. /* recursively fill in attrofs and attrflag */
  106. static void fixup(struct Filter* f) {
  107.   if (!f) return;
  108.   switch (f->type) {
  109.   case EQUAL:
  110.   case SUBSTRING:
  111.   case GREATEQUAL:
  112.   case LESSEQUAL:
  113.   case PRESENT:
  114.   case APPROX:
  115.     {
  116.       char* x=map+5*4+size_of_string_table;
  117.       size_t i;
  118.       f->attrofs=f->attrflag=0;
  119.       for (i=0; i<attribute_count; ++i) {
  120.         uint32 j=uint32_read(x);
  121.         if (!matchcasestring(&f->ava.desc,map+j)) {
  122.           f->attrofs=j;
  123.           uint32_unpack(x+attribute_count*4,&f->attrflag);
  124.           break;
  125.         }
  126.         x+=4;
  127.       }
  128.       if (!f->attrofs) {
  129.         buffer_puts(buffer_2,"cannot find attribute \"");
  130.         buffer_put(buffer_2,f->ava.desc.s,f->ava.desc.l);
  131.         buffer_putsflush(buffer_2,"\"!\n");
  132.       }
  133.     }
  134.   case AND:
  135.   case OR:
  136.   case NOT:
  137.     if (f->x) fixup(f->x);
  138.   default:
  139.     break;
  140.   }
  141.   if (f->next) fixup(f->next);
  142. }
  143.  
  144. static void fixupadl(struct AttributeDescriptionList* a) {
  145.   while (a) {
  146.     char* x=map+5*4+size_of_string_table;
  147.     size_t i;
  148.     a->attrofs=0;
  149.     for (i=0; i<attribute_count; ++i) {
  150.       uint32 j=uint32_read(x);
  151.       if (!matchcasestring(&a->a,map+j)) {
  152.         a->attrofs=j;
  153.         break;
  154.       }
  155.       x+=4;
  156.     }
  157.     if (!a->attrofs) {
  158.       buffer_puts(buffer_2,"cannot find attribute \"");
  159.       buffer_put(buffer_2,a->a.s,a->a.l);
  160.       buffer_putsflush(buffer_2,"\"!\n");
  161.     }
  162.     a=a->next;
  163.   }
  164. }
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173. /*
  174.             _                                    _
  175.   __ _  ___| |  ___ _   _ _ __  _ __   ___  _ __| |_
  176.  / _` |/ __| | / __| | | | '_ \| '_ \ / _ \| '__| __|
  177. | (_| | (__| | \__ \ |_| | |_) | |_) | (_) | |  | |_
  178.  \__,_|\___|_| |___/\__,_| .__/| .__/ \___/|_|   \__|
  179.                          |_|   |_|
  180. */
  181.  
  182. uint32 filters,acls;            /* number of filters and acls in the ACL section of the data file */
  183. uint32 filtertab,acltab;        /* offsets of the filter and acl table in the data file */
  184. char* acl_ec_subjects;          /* if the n'th byte here is nonzero, then the current subject
  185.                                    (the dn the user is logged in as) matches the n'th filter, i.e.
  186.                                    the ACLs with this subject need to be applied. */
  187. struct Filter** Filters;
  188. char Self[]="self";
  189. char Any[]="*";
  190. uint32 authenticated_as;
  191. char* authenticated_as_str;
  192.  
  193. struct acl {
  194.   uint32 subject,object;        /* index of filter for subject,object */
  195.   uint16 may,maynot;
  196.   uint32 attrs;
  197.   uint32 Attrs[1];
  198. };
  199.  
  200. struct acl** Acls;
  201.  
  202. static void load_acls() {
  203.   struct acl** oldAcls=Acls;
  204.   size_t oldacls=acls;
  205.   uint32 ofs;
  206.   uint32 acl_ofs;
  207.   acl_ofs=0;
  208.   for (ofs=indices_offset+record_count*4; ofs<filelen;) {
  209.     uint32 index_type,next;
  210.     uint32_unpack(map+ofs,&index_type);
  211.     uint32_unpack(map+ofs+4,&next);
  212.     if (index_type==2) { acl_ofs=ofs; break; }
  213.     if (next<ofs || next>filelen) {
  214. kaputt:
  215.       buffer_putsflush(buffer_1,"broken data file!\n");
  216.       exit(1);
  217.     }
  218.     ofs=next;
  219.   }
  220.   filters=acls=0; acl_ec_subjects=0;
  221.   if (acl_ofs) {
  222.     uint32 i;
  223.     ofs=acl_ofs+8;
  224.     filters=uint32_read(map+ofs);
  225.     acl_ec_subjects=malloc(2*filters);
  226.     filtertab=ofs+4;
  227.     ofs=filtertab+filters*4;
  228.     if (ofs<filtertab) goto kaputt;
  229.     Filters=malloc(sizeof(Filters[0])*filters);
  230.     if (!Filters) goto kaputt;
  231.     for (i=0; i<filters; ++i) {
  232.       struct Filter* f;
  233.       ofs=uint32_read(map+filtertab+i*4);
  234.       if (ofs<filtertab || ofs>filelen) goto kaputt;
  235.       if (byte_equal(map+ofs,4,"self"))
  236.         f=(struct Filter*)Self;
  237.       else if (byte_equal(map+ofs,2,"*"))
  238.         f=(struct Filter*)Any;
  239.       else if (scan_ldapsearchfilter(map+ofs,map+filelen,&f)!=0) {
  240.         fixup(f);
  241.         if (debug) {
  242.           size_t l=fmt_ldapsearchfilterstring(0,f);
  243.           char* buf=malloc(l+23);
  244.           if (!buf) goto kaputt;
  245.           buf[fmt_ldapsearchfilterstring(buf,f)]=0;
  246.           free(buf);
  247.         }
  248.       } else goto kaputt;
  249.       Filters[i]=f;
  250.     }
  251.     ofs=uint32_read(map+filtertab+filters*4);
  252.     if (ofs<filtertab || ofs>filelen-4) goto kaputt;
  253.     acls=uint32_read(map+ofs);
  254.     acltab=ofs+4;
  255.     Acls=malloc(sizeof(Acls[0])*acls);
  256.     if (!Acls) goto kaputt;
  257.     for (i=0; i<acls; ++i) {
  258.       uint32 j;
  259.       uint32 tmp,cnt;
  260.       ofs=uint32_read(map+acltab+i*4);
  261.       if (ofs>filelen-16) goto kaputt;
  262.       cnt=0;
  263.       for (tmp=ofs+12; tmp<filelen; tmp+=4) {
  264.         uint32 j=uint32_read(map+tmp);
  265.         if (j>tmp) goto kaputt;
  266.         if (!j) break;
  267.         ++cnt;
  268.       }
  269.       Acls[i]=malloc(sizeof(struct acl)+cnt*sizeof(uint32));
  270.       if (!Acls[i]) goto kaputt;
  271.       Acls[i]->subject=uint32_read(map+ofs);
  272.       Acls[i]->object=uint32_read(map+ofs+4);
  273.       Acls[i]->may=uint16_read(map+ofs+8);
  274.       Acls[i]->maynot=uint16_read(map+ofs+10);
  275.       Acls[i]->attrs=cnt;
  276.  
  277.       tmp=ofs+12;
  278.       for (j=0; j<cnt; ++j) {
  279.         uint32 x;
  280.         Acls[i]->Attrs[j]=x=uint32_read(map+tmp+4*j);
  281.         if (any_ofs==0 && map[x]=='*' && map[x+1]==0) any_ofs=x;
  282.       }
  283.     }
  284.   }
  285.   if (acls) {
  286.     uint32 i;
  287.     for (i=0; i<filters; ++i)
  288.       acl_ec_subjects[i]=(Filters[i]==(struct Filter*)Any);
  289.   }
  290.   if (oldAcls) {
  291.     size_t i;
  292.     for (i=0; i<oldacls; ++i)
  293.       free(oldAcls[i]);
  294.     free(oldAcls);
  295.   }
  296. }
  297.  
  298. /* End of ACL code */
  299.  
  300. static const char* datafilename;
  301. static struct stat ss_data;
  302. static struct stat ss_journal;
  303.  
  304. void map_datafile(const char* filename) {
  305.   map=mmap_read(datafilename=filename,&filelen);
  306.   stat(datafilename,&ss_data);
  307.   if (!map) {
  308.     buffer_putsflush(buffer_2,"could not open data!\n");
  309.     exit(1);
  310.   }
  311.   uint32_unpack(map,&magic);
  312.   uint32_unpack(map+4,&attribute_count);
  313.   uint32_unpack(map+2*4,&record_count);
  314.   uint32_unpack(map+3*4,&indices_offset);
  315.   uint32_unpack(map+4*4,&size_of_string_table);
  316.   record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
  317.  
  318.   /* look up "dn" and "objectClass" */
  319.   {
  320.     char* x=map+5*4+size_of_string_table;
  321.     size_t i;
  322.     dn_ofs=objectClass_ofs=userPassword_ofs=any_ofs=0;
  323.     for (i=0; i<attribute_count; ++i) {
  324.       uint32 j;
  325.       j=uint32_read(x);
  326.       if (case_equals("dn",map+j))
  327.         dn_ofs=j;
  328.       else if (case_equals("objectClass",map+j))
  329.         objectClass_ofs=j;
  330.       else if (case_equals("userPassword",map+j))
  331.         userPassword_ofs=j;
  332.       x+=4;
  333.     }
  334.     if (!dn_ofs || !objectClass_ofs) {
  335.       buffer_putsflush(buffer_2,"can't happen error: dn or objectClass not there?!\n");
  336.       exit(0);
  337.     }
  338.   }
  339.   load_acls();
  340. }
  341.  
  342. /*
  343.      _      _                                 _
  344.   __| | ___| |__  _   _  __ _    ___ ___   __| | ___
  345.  / _` |/ _ \ '_ \| | | |/ _` |  / __/ _ \ / _` |/ _ \
  346. | (_| |  __/ |_) | |_| | (_| | | (_| (_) | (_| |  __/
  347.  \__,_|\___|_.__/ \__,_|\__, |  \___\___/ \__,_|\___|
  348.                         |___/
  349. */
  350.  
  351. #define BUFSIZE 8192
  352.  
  353. #if (debug != 0)
  354. /* debugging support functions, adapted from t2.c */
  355. static void printava(struct AttributeValueAssertion* a,const char* rel) {
  356.   buffer_puts(buffer_2,"[");
  357.   buffer_put(buffer_2,a->desc.s,a->desc.l);
  358.   buffer_puts(buffer_2," ");
  359.   buffer_puts(buffer_2,rel);
  360.   buffer_puts(buffer_2," ");
  361.   buffer_put(buffer_2,a->value.s,a->value.l);
  362.   buffer_puts(buffer_2,"]");
  363. }
  364.  
  365. static void printal(struct AttributeDescriptionList* a) {
  366.   while (a) {
  367.     buffer_put(buffer_2,a->a.s,a->a.l);
  368.     a=a->next;
  369.     if (a) buffer_puts(buffer_2,",");
  370.   }
  371.   if (a) buffer_puts(buffer_2,"\n");
  372. }
  373.  
  374. static void printfilter(struct Filter* f) {
  375.   switch (f->type) {
  376.   case AND:
  377.     buffer_puts(buffer_2,"&(");
  378. mergesub:
  379.     printfilter(f->x);
  380.     buffer_puts(buffer_2,")\n");
  381.     break;
  382.   case OR:
  383.     buffer_puts(buffer_2,"|(");
  384.     goto mergesub;
  385.     break;
  386.   case NOT:
  387.     buffer_puts(buffer_2,"!(");
  388.     goto mergesub;
  389.   case EQUAL:
  390.     printava(&f->ava,"==");
  391.     break;
  392.   case SUBSTRING:
  393.     {
  394.       struct Substring* s=f->substrings;
  395.       int first=1;
  396.       buffer_put(buffer_2,f->ava.desc.s,f->ava.desc.l);
  397.       buffer_puts(buffer_2," has ");
  398.       while (s) {
  399.         if (!first) buffer_puts(buffer_2," and "); first=0;
  400.         switch(s->substrtype) {
  401.         case prefix: buffer_puts(buffer_2,"prefix \""); break;
  402.         case any: buffer_puts(buffer_2,"substr \""); break;
  403.         case suffix: buffer_puts(buffer_2,"suffix \""); break;
  404.         }
  405.         buffer_put(buffer_2,s->s.s,s->s.l);
  406.         buffer_puts(buffer_2,"\"");
  407.         s=s->next;
  408.       }
  409.     }
  410.     break;
  411.   case GREATEQUAL:
  412.     printava(&f->ava,">=");
  413.     break;
  414.   case LESSEQUAL:
  415.     printava(&f->ava,"<=");
  416.     break;
  417.   case PRESENT:
  418.     printava(&f->ava,"\\exist");
  419.     break;
  420.   case APPROX:
  421.     printava(&f->ava,"\\approx");
  422.     break;
  423.   case EXTENSIBLE:
  424.     buffer_puts(buffer_2,"[extensible]");
  425.     break;
  426.   }
  427.   if (f->next) {
  428.     buffer_puts(buffer_2,",");
  429.     printfilter(f->next);
  430.   }
  431.   buffer_flush(buffer_2);
  432. }
  433. #endif
  434.  
  435.  
  436.  
  437.  
  438. /*
  439.  _           _                           _
  440. (_)_ __   __| | _____  __   ___ ___   __| | ___
  441. | | '_ \ / _` |/ _ \ \/ /  / __/ _ \ / _` |/ _ \
  442. | | | | | (_| |  __/>  <  | (_| (_) | (_| |  __/
  443. |_|_| |_|\__,_|\___/_/\_\  \___\___/ \__,_|\___|
  444. */
  445.  
  446. /* find out whether this filter can be accelerated with the indices */
  447. static int indexable(struct Filter* f) {
  448.   struct Filter* y=f->x;
  449.   if (!f) return 0;
  450.   switch (f->type) {
  451.   case AND:
  452.     while (y) {
  453.       if (indexable(y)) return 1;
  454.       y=y->next;
  455.     }
  456.     return 0;
  457.   case OR:
  458.     while (y) {
  459.       if (!indexable(y)) return 0;
  460.       y=y->next;
  461.     }
  462.     /* fall through */
  463.   case PRESENT:
  464.     return 1;
  465. #if 0
  466.   /* doesn't make much sense to try to speed up negated queries */
  467.   case NOT:
  468.     return indexable(y);
  469. #endif
  470.   case SUBSTRING:
  471.     if (f->substrings->substrtype!=prefix) return 0;
  472.     /* fall through */
  473.   case EQUAL:
  474.   case LESSEQUAL:
  475.   case GREATEQUAL:
  476.     {
  477.       uint32 ofs;
  478.       for (ofs=indices_offset+record_count*4; ofs<filelen;) {
  479.         uint32 index_type,next,indexed_attribute;
  480.         index_type=uint32_read(map+ofs);
  481.         next=uint32_read(map+ofs+4);
  482.         indexed_attribute=uint32_read(map+ofs+8);
  483.         if (index_type<=1 || (index_type==3 && f->type==EQUAL))
  484.           if (!matchstring(&f->ava.desc,map+indexed_attribute))
  485.             return 1;
  486.         ofs=next;
  487.       }
  488.     }
  489.     /* fall through */
  490.   default:
  491.     return 0;
  492.   }
  493. }
  494.  
  495. /* each record can have more than one attribute with the same name, i.e.  two email
  496.  * addresses.  Thus, the index can't just be a sorted list of pointers the records
  497.  * (because a record with two email addresses needs to be in the index twice, once for
  498.  * each email address).  So our index is a sorted list of pointers to the attributes.
  499.  * Thus, a look-up in the index does not yield the record but the attribute.  We need to
  500.  * be able to find the record for a given attribute.  To do that, we exploit the fact that
  501.  * the strings in the string table are in the same order as the records, so we can do a
  502.  * binary search over the record table to find the record with the attribute.  This does
  503.  * not work for objectClass, because the classes are stored in a different string table to
  504.  * remove duplicates. */
  505.  
  506. /* Yes, this is an evil kludge to keep index size small.  However, it turned out that it
  507.  * also dominated lookup time for a relatively minor index size reduction.  So index type
  508.  * 1 was added (flag f to addindex), which does not need this.  The benefit is so big that
  509.  * tinyldap will drop support for type 0 indices sooner or later.  Type 1 indexes are
  510.  * twice as large, and save the record number besides each index entry. */
  511.  
  512. /* find record given a data pointer */
  513. static long findrec(uint32 dat) {
  514.   uint32* records=(uint32*)(map+indices_offset);
  515.   uint32 bottom=0;
  516.   uint32 top=record_count-1;
  517.  
  518.   while ((top>=bottom)) {
  519.     uint32 mid=(top+bottom)/2;
  520.     uint32 l;
  521.  
  522.     l=uint32_read(map+uint32_read((char*)(&records[mid]))+8);
  523.     if (l<=dat) {
  524.       if (mid>=record_count-1)
  525.         l=uint32_read(map+uint32_read((char*)(&records[0]))+12);
  526.       else
  527.         l=uint32_read(map+uint32_read((char*)(&records[mid+1]))+8);
  528.       if (l>dat) {
  529.         return mid;     /* found! */
  530.       }
  531.       bottom=mid+1;
  532.     } else
  533.       if (mid)
  534.         top=mid-1;
  535.       else
  536.         break;
  537.   }
  538.   buffer_putsflush(buffer_2,"findrec failed!\n");
  539.   return -1;
  540. }
  541.  
  542. #define RANGECHECK 1
  543.  
  544. struct bitfield {
  545.   unsigned long* bits;
  546. #ifdef RANGECHECK
  547.   size_t n;
  548. #endif
  549.   size_t first,last;
  550. };
  551.  
  552. /* basic bit-set support: set all bits to 0 */
  553. static inline void emptyset(struct bitfield* b) {
  554.   size_t i;
  555. #ifdef RANGECHECK
  556.   b->n=
  557. #endif
  558.     b->first=record_count;
  559.   b->last=0;
  560.   for (i=0; i<record_set_length; ++i) b->bits[i]=0;
  561. }
  562.  
  563. /* basic bit-set support: set all bits to 1 */
  564. static inline void fillset(struct bitfield* b) {
  565.   size_t i;
  566.   b->first=0;
  567. #ifdef RANGECHECK
  568.   b->n=
  569. #endif
  570.   b->last=record_count;
  571.   for (i=0; i<record_set_length; ++i) b->bits[i]=(unsigned long)-1;
  572. }
  573.  
  574. /* basic bit-set support: set one bit to 1 */
  575. static inline void setbit(struct bitfield* b,size_t bit) {
  576. #ifdef RANGECHECK
  577.   if (bit<=b->n) {
  578. #endif
  579.     if (bit<b->first) b->first=bit;
  580.     if (bit>b->last) b->last=bit;
  581.     b->bits[bit/(8*sizeof(long))] |= (1<<(bit&(8*sizeof(long)-1)));
  582. #ifdef RANGECHECK
  583.   }
  584. #endif
  585. }
  586.  
  587. /* basic bit-set support: see if given bit is set */
  588. static inline int isset(struct bitfield* b,size_t bit) {
  589. #ifdef RANGECHECK
  590.   if (bit>b->n) return 0;
  591. #endif
  592.   return b->bits[bit/(8*sizeof(long))] & (1<<(bit&(8*sizeof(long)-1)));
  593. }
  594.  
  595. /* use index (sorted table of offsets to records) to do a binary search
  596.  * for all records that match the value in s.  Set the corresponding
  597.  * bits to 1 in bitfield. */
  598. static void tagmatches(uint32* index,size_t elements,struct string* s,
  599.                        struct bitfield* b,int (*match)(struct string* s,const char* c),
  600.                        uint32 index_type,enum FilterType ft) {
  601.   uint32 bottom=0;
  602.   uint32 top=elements;
  603.   uint32 mid,k,m;
  604.   long rec;
  605.   rec=0;
  606.   emptyset(b);
  607.  
  608.   while ((top>=bottom)) {
  609.     int l;
  610.  
  611.     mid=(top+bottom)/2;
  612.     k=uint32_read((char*)(&index[mid]));
  613. #ifdef DEBUG
  614.     buffer_puts(buffer_2,"match[");
  615.     buffer_putulong(buffer_2,bottom);
  616.     buffer_puts(buffer_2,"..");
  617.     buffer_putulong(buffer_2,top);
  618.     buffer_puts(buffer_2,"]: ");
  619.     buffer_put(buffer_2,s->s,s->l);
  620.     buffer_puts(buffer_2," <-> ");
  621.     buffer_puts(buffer_2,map+k);
  622.     buffer_putsflush(buffer_2,": ");
  623. #endif
  624.     if ((l=match(s,map+k))==0) {
  625.       /* match! */
  626. #ifdef DEBUG
  627.       buffer_putsflush(buffer_2,"MATCH!\n");
  628. #endif
  629.       if (index_type==0)
  630.         rec=findrec(k);
  631.       else if (index_type==1)
  632.         rec=uint32_read((char*)(&index[mid+elements]));
  633.       else {
  634.         buffer_puts(buffer_2,"unsupported index type ");
  635.         buffer_putulong(buffer_2,index_type);
  636.         buffer_puts(buffer_2," in tagmatches!\n");
  637.         return;
  638.       }
  639.       if (rec>=0)
  640.         setbit(b,rec);
  641.       /* there may be multiple matches.
  642.         * Look before and after mid, too */
  643.       if (mid)  /* thx Andreas Stührk */
  644.         for (k=mid-1; k>0; --k) {
  645.           m=uint32_read((char*)(&index[k]));
  646.           if ((ft==LESSEQUAL) || (l=match(s,map+m))==0) {
  647.             if (index_type==0)
  648.               rec=findrec(m);
  649.             else if (index_type==1)
  650.               rec=uint32_read((char*)(&index[k+elements]));
  651.             if (rec>=0)
  652.               setbit(b,rec);
  653.           } else break;
  654.         }
  655.       for (k=mid+1; k<elements; ++k) {
  656.         m=uint32_read((char*)(&index[k]));
  657.         if ((ft==GREATEQUAL) || (l=match(s,map+m))==0) {
  658.           if (index_type==0)
  659.             rec=findrec(m);
  660.           else if (index_type==1)
  661.             rec=uint32_read((char*)(&index[k+elements]));
  662.           if (rec>=0)
  663.             setbit(b,rec);
  664.         } else break;
  665.       }
  666.       return;
  667.     }
  668.  
  669.     if (l<0) {
  670. #ifdef DEBUG
  671.       buffer_putsflush(buffer_2,"smaller!\n");
  672. #endif
  673.       if (mid)
  674.         top=mid-1;
  675.       else
  676.         break;  /* since our offsets are unsigned, we need to avoid the -1 case */
  677.     } else
  678. #ifdef DEBUG
  679.       buffer_putsflush(buffer_2,"larger!\n"),
  680. #endif
  681.       bottom=mid+1;
  682.   }
  683.   /* not found; we can still have matches if type==LESSEQUAL or
  684.    * type==GREATEQUAL */
  685.   if (ft==GREATEQUAL) {
  686.     for (k=mid; k<elements; ++k) {
  687.       m=uint32_read((char*)(&index[k]));
  688.       if (index_type==0)
  689.         rec=findrec(m);
  690.       else if (index_type==1)
  691.         rec=uint32_read((char*)(&index[k+elements]));
  692.       if (rec>=0)
  693.         setbit(b,rec);
  694.     }
  695.   } else if (ft==LESSEQUAL) {
  696.     for (k=0; k<=mid; ++k) {
  697.       m=uint32_read((char*)(&index[k]));
  698.       if (index_type==0)
  699.         rec=findrec(m);
  700.       else if (index_type==1)
  701.         rec=uint32_read((char*)(&index[k+elements]));
  702.       if (rec>=0)
  703.         setbit(b,rec);
  704.     }
  705.   }
  706. }
  707.  
  708. static uint32 hash(const unsigned char* c,size_t keylen) {
  709.   size_t h=0,i;
  710.   for (i=0; i<keylen; ++i) {
  711.     /* from djb's cdb */
  712.     h += (h<<5);
  713.     h ^= c[i];
  714.   }
  715.   return (uint32)h;
  716. }
  717.  
  718. static uint32 hash_tolower(const unsigned char* c,size_t keylen) {
  719.   size_t h=0,i;
  720.   for (i=0; i<keylen; ++i) {
  721.     /* from djb's cdb */
  722.     h += (h<<5);
  723.     h ^= tolower(c[i]);
  724.   }
  725.   return (uint32)h;
  726. }
  727.  
  728. /* Use the indices to answer a query with the given filter.
  729.  * For all matching records, set the corresponding bit to 1 in bitfield.
  730.  * Note that this match can be approximate.  Before answering, the
  731.  * matches are verified with ldap_match_mapped, so the index can also
  732.  * be used if it only helps eliminate some of the possible matches (for
  733.  * example an AND query where only one of the involved attributes has an
  734.  * index). */
  735. static int useindex(struct Filter* f,struct bitfield* b) {
  736.   struct Filter* y=f->x;
  737.   if (!f) return 1;
  738.  
  739.   if (f->type==EQUAL) {         /* prefer a hash index if there is one */
  740.     uint32 ofs;
  741.     for (ofs=indices_offset+record_count*4; ofs<filelen;) {
  742.       uint32 index_type,next,indexed_attribute;
  743.       index_type=uint32_read(map+ofs);
  744.       next=uint32_read(map+ofs+4);
  745.       indexed_attribute=uint32_read(map+ofs+8);
  746.       if (index_type==3)
  747.         if (!matchstring(&f->ava.desc,map+indexed_attribute)) {
  748.           uint32 hashtabsize=uint32_read(map+ofs+12);
  749.           uint32 hashtab=ofs+16;
  750.           uint32 hashval=f->attrflag&1?hash_tolower((unsigned char*)f->ava.value.s,f->ava.value.l):hash((unsigned char*)f->ava.value.s,f->ava.value.l);
  751.           uint32 hashofs=uint32_read(map+hashtab+(hashval%hashtabsize)*4);
  752.           if (hashofs==0) return 1;
  753.           if (hashofs<ofs)
  754.             /* direct hit */
  755.             setbit(b,hashofs);
  756.           else {
  757.             uint32 n=uint32_read(map+hashofs);
  758.             hashofs+=4;
  759.             while (n) {
  760.               setbit(b,uint32_read(map+hashofs));
  761.               hashofs+=4;
  762.               --n;
  763.             }
  764.           }
  765.           return 1;
  766.         }
  767.       ofs=next;
  768.     }
  769.   }
  770.  
  771.   switch (f->type) {
  772.   case AND:
  773.     {
  774.       struct bitfield tmp;
  775.       int ok=0;
  776.       tmp.bits=alloca(record_set_length*sizeof(unsigned long));
  777.       if (y) {
  778.         useindex(y,b);
  779.         y=y->next;
  780.       } else
  781.         fillset(b);
  782.       while (y) {
  783.         if (useindex(y,&tmp)) {
  784.           size_t i;
  785.           for (i=0; i<record_set_length; ++i)
  786.             b->bits[i] &= tmp.bits[i];
  787.           if (tmp.first>b->first) b->first=tmp.first;
  788.           if (tmp.last<b->last) b->last=tmp.last;
  789.           ok=1;
  790.         }
  791.         y=y->next;
  792.       }
  793.       return ok;
  794.     }
  795.   case OR:
  796.     {
  797.       struct bitfield tmp;
  798.       int ok=1;
  799.       tmp.bits=alloca(record_set_length*sizeof(unsigned long));
  800.       if (y) {
  801.         useindex(y,b);
  802.         y=y->next;
  803.       } else
  804.         emptyset(b);
  805.       while (y) {
  806.         if (useindex(y,&tmp)) {
  807.           size_t i;
  808.           for (i=0; i<record_set_length; ++i)
  809.             b->bits[i] |= tmp.bits[i];
  810.           if (tmp.first<b->first) b->first=tmp.first;
  811.           if (tmp.last>b->last) b->last=tmp.last;
  812.         } else
  813.           ok=0;
  814.         y=y->next;
  815.       }
  816.       return ok;
  817.     }
  818. #if 0
  819.   /* doesn't make much sense to try to speed up negated queries */
  820.   case NOT:
  821.     return indexable(y);
  822. #endif
  823.   case SUBSTRING:
  824.     if (f->substrings->substrtype!=prefix) return 0;
  825.     {
  826.       uint32 ofs;
  827.       for (ofs=indices_offset+record_count*4; ofs<filelen;) {
  828.         uint32 index_type,next,indexed_attribute;
  829.         index_type=uint32_read(map+ofs);
  830.         next=uint32_read(map+ofs+4);
  831.         indexed_attribute=uint32_read(map+ofs+8);
  832.         if (index_type<=1)
  833.           if (!matchstring(&f->ava.desc,map+indexed_attribute)) {
  834.             tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<<index_type),&f->substrings->s,b,
  835.                        f->attrflag&1?matchcaseprefix:matchprefix,index_type,f->type);
  836.             return 1;
  837.           }
  838.         ofs=next;
  839.       }
  840.     }
  841.     return 0;
  842.   case PRESENT:
  843.     {
  844.       /* now this is not exactly using an index, but a linear search
  845.        * through the record table, but since each check is very cheap,
  846.        * we pretend it's indexed */
  847.       char* x=map+5*4+size_of_string_table+attribute_count*8;
  848.       size_t i;
  849.       emptyset(b);
  850.       for (i=0; i<record_count; ++i) {
  851.         if (ldap_match_present(x-map,f->attrofs))
  852.           setbit(b,i);
  853.         x+=uint32_read(x)*8;
  854.       }
  855.       return 1;
  856.     }
  857.   case LESSEQUAL:
  858.   case GREATEQUAL:
  859.   case EQUAL:
  860.     {
  861.       uint32 ofs;
  862.       for (ofs=indices_offset+record_count*4; ofs<filelen;) {
  863.         uint32 index_type,next,indexed_attribute;
  864.         index_type=uint32_read(map+ofs);
  865.         next=uint32_read(map+ofs+4);
  866.         indexed_attribute=uint32_read(map+ofs+8);
  867.         if (index_type<=1)
  868.           if (!matchstring(&f->ava.desc,map+indexed_attribute)) {
  869.             tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/(4<<index_type),&f->ava.value,b,
  870.                        f->attrflag&1?matchcasestring:matchstring,index_type,f->type);
  871.             return 1;
  872.           }
  873.         ofs=next;
  874.       }
  875.     }
  876.     /* fall through */
  877.   default:
  878.     return 0;
  879.   }
  880. }
  881.  
  882.  
  883.  
  884. /*
  885.                                                                  _
  886.   __ _ _   _  ___ _ __ _   _    __ _ _ __  _____      _____ _ __(_)_ __   __ _
  887.  / _` | | | |/ _ \ '__| | | |  / _` | '_ \/ __\ \ /\ / / _ \ '__| | '_ \ / _` |
  888. | (_| | |_| |  __/ |  | |_| | | (_| | | | \__ \\ V  V /  __/ |  | | | | | (_| |
  889.  \__, |\__,_|\___|_|   \__, |  \__,_|_| |_|___/ \_/\_/ \___|_|  |_|_| |_|\__, |
  890.     |_|                |___/                                             |___/
  891. */
  892.  
  893. static int checkacl(uint32 recofs,uint32 attrofs,unsigned long operation,struct SearchResultEntry* sre) {
  894.   uint32 j;
  895.   for (j=0; j<acls; ++j) {
  896.     /* does the ACL subject apply? */
  897.     if (!acl_ec_subjects[Acls[j]->subject]) continue;
  898.     /* does the ACL even apply to the wanted operation? */
  899.     if ((Acls[j]->may | Acls[j]->maynot) & operation) {
  900.       uint32 k;
  901.       if (acl_ec_subjects[filters+Acls[j]->object]==-1) continue;
  902.       if (acl_ec_subjects[filters+Acls[j]->object]==0) {
  903.         int match=0;
  904.         if (Filters[Acls[j]->object]==(struct Filter*)Any)
  905.           match=1;
  906.         else if (Filters[Acls[j]->object]==(struct Filter*)Self) {
  907.           if (authenticated_as==0 && authenticated_as_str)
  908.             match=!strcmp(map+uint32_read(map+recofs+8),authenticated_as_str);
  909.           else
  910.             match=(recofs==authenticated_as);
  911.         } else if (recofs)
  912.           match=ldap_matchfilter_mapped(recofs,Filters[Acls[j]->object]);
  913.         else if (sre)
  914.           match=ldap_matchfilter_sre(sre,Filters[Acls[j]->object]);
  915.         else
  916.           match=-1;
  917.         if (match)
  918.           acl_ec_subjects[filters+Acls[j]->object]=1;
  919.         else {
  920.           acl_ec_subjects[filters+Acls[j]->object]=-1;
  921.           continue;
  922.         }
  923.       }
  924.       for (k=0; k<Acls[j]->attrs; ++k) {
  925.         if (Acls[j]->Attrs[k]==any_ofs || attrofs==Acls[j]->Attrs[k]) {
  926.           if (Acls[j]->may&operation)
  927.             return 1;
  928.           else
  929.             return -1;
  930.           break;
  931.         }
  932.       }
  933.     }
  934.   }
  935.   return 0;
  936. }
  937.  
  938. static int ldap_matchfilter_hn(struct hashnode* hn,struct Filter* f);
  939.  
  940. static int checkacl_hn(struct hashnode* hn,const unsigned char* attr,unsigned long operation) {
  941.   uint32 j;
  942.   for (j=0; j<acls; ++j) {
  943.     /* does the ACL subject apply? */
  944.     if (!acl_ec_subjects[Acls[j]->subject]) continue;
  945.     /* does the ACL even apply to the wanted operation? */
  946.     if ((Acls[j]->may | Acls[j]->maynot) & operation) {
  947.       uint32 k;
  948.       if (acl_ec_subjects[filters+Acls[j]->object]==-1) continue;
  949.       if (acl_ec_subjects[filters+Acls[j]->object]==0) {
  950.         int match=0;
  951.         if (Filters[Acls[j]->object]==(struct Filter*)Any)
  952.           match=1;
  953.         else if (Filters[Acls[j]->object]==(struct Filter*)Self)
  954.           match=dn && !strcmp((char*)hn->dn,authenticated_as_str);
  955.         else if (dn)
  956.           match=ldap_matchfilter_hn(hn,Filters[Acls[j]->object]);
  957.         else
  958.           match=-1;
  959.         if (match)
  960.           acl_ec_subjects[filters+Acls[j]->object]=1;
  961.         else {
  962.           acl_ec_subjects[filters+Acls[j]->object]=-1;
  963.           continue;
  964.         }
  965.       }
  966.       for (k=0; k<Acls[j]->attrs; ++k) {
  967. /*          if (Acls[j]->Attrs[k]==any_ofs || !matchstring(&adl->a,map+Acls[j]->Attrs[k])) { */
  968.         if (Acls[j]->Attrs[k]==any_ofs || bstr_equal((char*)attr,map+Acls[j]->Attrs[k])) {
  969.           if (Acls[j]->may&operation)
  970.             return 1;
  971.           else
  972.             return -1;
  973.           break;
  974.         }
  975.       }
  976.     }
  977.   }
  978.   return 0;
  979. }
  980.  
  981.  
  982. static struct hashnode** dn_in_journal(unsigned char* dn);
  983.  
  984. static void answerwith_hn(struct hashnode* hn,struct SearchRequest* sr,long messageid,int out);
  985.  
  986. /* this routine is called for each record matched the query.  It basically puts together
  987.  * an answer LDAP message from the record and the list of attributes the other side said
  988.  * it wanted to have. */
  989. static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int out) {
  990.   struct SearchResultEntry sre;
  991.   struct PartialAttributeList** pal=&sre.attributes;
  992.   struct hashnode** hn;
  993.  
  994.   if ((hn=dn_in_journal((unsigned char*)map+uint32_read(map+ofs+8))) && *hn) {
  995.     (*hn)->overwrite=1;
  996.     answerwith_hn(*hn,sr,messageid,out);
  997.     return;
  998.   }
  999.  
  1000. #if (debug != 0)
  1001.   if (debug) {
  1002.     char* x=map+ofs;
  1003.     uint32 j;
  1004.     buffer_putulong(buffer_2,j=uint32_read(x));
  1005.     buffer_puts(buffer_2," attributes:\n");
  1006.     x+=8;
  1007.     buffer_puts(buffer_2,"  dn: ");
  1008.     buffer_puts(buffer_2,map+uint32_read(x));
  1009.     buffer_puts(buffer_2,"\n  objectClass: ");
  1010.     x+=4;
  1011.     buffer_puts(buffer_2,map+uint32_read(x));
  1012.     buffer_puts(buffer_2,"\n");
  1013.     x+=4;
  1014.     for (; j>2; --j) {
  1015.       buffer_puts(buffer_2,"  ");
  1016.       buffer_puts(buffer_2,map+uint32_read(x));
  1017.       buffer_puts(buffer_2,": ");
  1018.       buffer_puts(buffer_2,map+uint32_read(x+4));
  1019.       buffer_puts(buffer_2,"\n");
  1020.       x+=8;
  1021.     }
  1022.     buffer_flush(buffer_2);
  1023.   }
  1024. #endif
  1025.  
  1026.   if (acls)
  1027.     byte_zero(acl_ec_subjects+filters,filters);
  1028.  
  1029.   if (acls && checkacl(ofs,dn_ofs,acl_read,0)!=1) return;
  1030.  
  1031.   sre.objectName.l=bstrlen(sre.objectName.s=map+uint32_read(map+ofs+8));
  1032.   sre.attributes=0;
  1033.  
  1034.   /* now go through list of requested attributes */
  1035.   {
  1036.     struct AttributeDescriptionList* adl=sr->attributes;
  1037.     if (!adl && attribute_count>2) {
  1038.       /* did not ask for any attributes.  send 'em all. */
  1039.       /* to do that, construct a list of all attributes */
  1040.  
  1041.       uint32 i;
  1042.       char* x=map+5*4+size_of_string_table+4;
  1043.       if (attribute_count>HUGE_SIZE_FOR_SANITY_CHECKS/sizeof(struct AttributeDescriptionList))
  1044.         return;
  1045.       adl=alloca((attribute_count)*sizeof(struct AttributeDescriptionList));
  1046.       for (i=0; i<attribute_count-1; ++i) {
  1047.         uint32 j;
  1048.         uint32_unpack(x,&j);
  1049.         x+=4;
  1050.         adl[i].a.s=map+j;
  1051.         adl[i].a.l=str_len(map+j);
  1052.         adl[i].attrofs=j;
  1053.         adl[i].next=adl+i+1;
  1054.       }
  1055.       adl[attribute_count-2].next=0;
  1056.     }
  1057.     while (adl) {
  1058.       const char* val=0;
  1059.       uint32 i=2,j;
  1060.  
  1061.       if (!acls || checkacl(ofs,adl->attrofs,acl_read,0)==1) {
  1062.         uint32_unpack(map+ofs,&j);
  1063. #if 0
  1064.         buffer_puts(buffer_2,"looking for attribute \"");
  1065.         buffer_put(buffer_2,adl->a.s,adl->a.l);
  1066.         buffer_putsflush(buffer_2,"\"\n");
  1067. #endif
  1068.         if (!matchstring(&adl->a,"dn")) val=sre.objectName.s; else
  1069.         if (!matchstring(&adl->a,"objectClass"))
  1070.           val=map+uint32_read(map+ofs+12);
  1071.         else {
  1072.           for (; i<j; ++i)
  1073. /*          if (!matchstring(&adl->a,map+uint32_read(map+ofs+i*8))) { */
  1074.             if (adl->attrofs == uint32_read(map+ofs+i*8)) {
  1075.               val=map+uint32_read(map+ofs+i*8+4);
  1076.               ++i;
  1077.               break;
  1078.             }
  1079.         }
  1080.         if (val) {
  1081.           *pal=malloc(sizeof(struct PartialAttributeList));
  1082.           if (!*pal) {
  1083. nomem:
  1084.             buffer_putsflush(buffer_2,"out of virtual memory!\n");
  1085.             exit(1);
  1086.           }
  1087.           (*pal)->type=adl->a;
  1088.           {
  1089.             struct AttributeDescriptionList** a;
  1090.             a=&(*pal)->values;
  1091. add_attribute:
  1092.             *a=malloc(sizeof(struct AttributeDescriptionList));
  1093.             if (!*a) goto nomem;
  1094.             (*a)->a.s=bstrfirst(val);
  1095.             (*a)->a.l=bstrlen(val);
  1096.             for (;i<j; ++i)
  1097. /*            if (!matchstring(&adl->a,map+uint32_read(map+ofs+i*8))) { */
  1098.               if (adl->attrofs == uint32_read(map+ofs+i*8)) {
  1099.                 val=map+uint32_read(map+ofs+i*8+4);
  1100.                 ++i;
  1101.                 a=&(*a)->next;
  1102.                 goto add_attribute;
  1103.               }
  1104.             (*a)->next=0;
  1105.           }
  1106.           (*pal)->next=0;
  1107.           pal=&(*pal)->next;
  1108.         }
  1109.       }
  1110.       adl=adl->next;
  1111.     }
  1112.   }
  1113.   {
  1114.     long l=fmt_ldapsearchresultentry(0,&sre);
  1115.     char *buf;
  1116.     long tmp;
  1117.     if (l<=HUGE_SIZE_FOR_SANITY_CHECKS) {
  1118.       buf=alloca(l+300); /* you never know ;) */
  1119.       if (verbose) {
  1120.         buffer_puts(buffer_2,"sre len ");
  1121.         buffer_putulong(buffer_2,l);
  1122.         buffer_putsflush(buffer_2,".\n");
  1123.       }
  1124.       tmp=fmt_ldapmessage(buf,messageid,SearchResultEntry,l);
  1125.       fmt_ldapsearchresultentry(buf+tmp,&sre);
  1126.       write(out,buf,l+tmp);
  1127.     }
  1128.   }
  1129.   free_ldappal(sre.attributes);
  1130. }
  1131.  
  1132.  
  1133. /*
  1134.  _     _       _       _                _   _     _
  1135. | |__ (_) __ _| |__   | | _____   _____| | | | __| | __ _ _ __
  1136. | '_ \| |/ _` | '_ \  | |/ _ \ \ / / _ \ | | |/ _` |/ _` | '_ \
  1137. | | | | | (_| | | | | | |  __/\ V /  __/ | | | (_| | (_| | |_) |
  1138. |_| |_|_|\__, |_| |_| |_|\___| \_/ \___|_| |_|\__,_|\__,_| .__/
  1139.          |___/                                           |_|
  1140. */
  1141.  
  1142. static int copystring(struct string* dest,struct string* src) {
  1143.   dest->s=malloc(src->l+1);
  1144.   if (!dest->s) return -1;
  1145.   byte_copy((char*)dest->s,src->l,src->s);
  1146.   dest->l=src->l;
  1147.   return 0;
  1148. }
  1149.  
  1150. /* deep copy an attribute description list */
  1151. static int copyadl(struct AttributeDescriptionList** dest,struct AttributeDescriptionList* src) {
  1152.   *dest=0;
  1153.   while (src) {
  1154.     if (!(*dest=malloc(sizeof(*src)))) return -1;
  1155.     byte_zero(*dest,sizeof(*src));
  1156.     if (copystring(&(*dest)->a,&src->a)) return -1;
  1157.     (*dest)->attrofs=src->attrofs;
  1158.     dest=&(*dest)->next;
  1159.     src=src->next;
  1160.   }
  1161.   return 0;
  1162. }
  1163.  
  1164. /* semi-deep copy an attribute description list */
  1165. static int copyadl2(struct AttributeDescriptionList** dest,struct AttributeDescriptionList* src) {
  1166.   *dest=0;
  1167.   while (src) {
  1168.     if (!(*dest=malloc(sizeof(*src)))) return -1;
  1169.     byte_zero(*dest,sizeof(*src));
  1170.     (*dest)->a=src->a;
  1171.     (*dest)->attrofs=src->attrofs;
  1172.     dest=&(*dest)->next;
  1173.     src=src->next;
  1174.   }
  1175.   return 0;
  1176. }
  1177.  
  1178.  
  1179.  
  1180.  
  1181. #if 0
  1182. /* deep copy a partial attribute list */
  1183. static int copypal(struct PartialAttributeList** dest,struct PartialAttributeList* src) {
  1184.   *dest=0;
  1185.   while (src) {
  1186.     if (!(*dest=malloc(sizeof(**dest)))) return -1;
  1187.     byte_zero(*dest,sizeof(**dest));
  1188.     if (copystring(&(*dest)->type,&src->type) ||
  1189.         copyadl(&(*dest)->values,src->values)) return -1;
  1190.     dest=&(*dest)->next;
  1191.     src=src->next;
  1192.   }
  1193.   return 0;
  1194. }
  1195. #endif
  1196.  
  1197. /* small helper for addreq2sre */
  1198. static int ar2sreh1(struct PartialAttributeList** dest,struct Addition* src) {
  1199.   *dest=0;
  1200.   while (src) {
  1201.     if (!(*dest=malloc(sizeof(**dest)))) return -1;
  1202.     byte_zero(*dest,sizeof(**dest));
  1203.     if (copystring(&(*dest)->type,&src->AttributeDescription) ||
  1204.         copyadl(&(*dest)->values,&src->vals)) return -1;
  1205.     dest=&(*dest)->next;
  1206.     src=src->next;
  1207.   }
  1208.   return 0;
  1209. }
  1210.  
  1211. /* convert an AddRequest to a SearchResultEntry */
  1212. static int addreq2sre(struct SearchResultEntry* sre,struct AddRequest* ar) {
  1213.   byte_zero(sre,sizeof(*sre));
  1214.   if (copystring(&sre->objectName,&ar->entry) ||
  1215.       !(sre->attributes=malloc(sizeof(*sre->attributes))) ||
  1216.       ar2sreh1(&sre->attributes,&ar->a)) {
  1217.     free_ldapsearchresultentry(sre);
  1218.     return -1;
  1219.   }
  1220.   return 0;
  1221. }
  1222.  
  1223. /* small helper for modreq2sre */
  1224. static int mr2sreh1(struct PartialAttributeList** dest,struct Modification* src) {
  1225.   *dest=0;
  1226.   while (src) {
  1227.     if (!(*dest=malloc(sizeof(**dest)))) return -1;
  1228.     byte_zero(*dest,sizeof(**dest));
  1229.     (*dest)->type=src->AttributeDescription;
  1230.     if (copyadl2(&(*dest)->values,src->vals)) return -1;
  1231.     dest=&(*dest)->next;
  1232.     src=src->next;
  1233.   }
  1234.   return 0;
  1235. }
  1236.  
  1237. /* We need two versions for the modify request.  The first one just creates a stupid
  1238.  * SearchResultEntry out of just the changed attributes, which is then only used for ACL
  1239.  * matching.  The second version merges in the existing record to form the modified
  1240.  * record.  This is the first version for ACL checking. */
  1241. static int modreq2sre(struct SearchResultEntry* sre,struct ModifyRequest* mr) {
  1242.   byte_zero(sre,sizeof(*sre));
  1243.   sre->objectName=mr->object;
  1244.   if (!(sre->attributes=malloc(sizeof(*sre->attributes))) ||
  1245.       mr2sreh1(&sre->attributes,&mr->m)) {
  1246.     free_ldapsearchresultentry(sre);
  1247.     return -1;
  1248.   }
  1249.   return 0;
  1250. }
  1251.  
  1252. static int applymodreq(struct hashnode* hn,struct ModifyRequest* mr,struct SearchResultEntry* sre) {
  1253.   struct PartialAttributeList** l;
  1254.   struct Modification* m;
  1255.   size_t i;
  1256.   sre->objectName.l=strlen((char*)hn->dn);
  1257.   sre->objectName.s=(char*)hn->dn;
  1258.   sre->attributes=0;
  1259.   l=&(sre->attributes);
  1260.   /* go through all the attributes in the hash node and apply the modifications */
  1261.   for (i=0; i<hn->n; ++i) {
  1262.     enum { Keep, Drop } todo=Keep;
  1263.     for (m=&mr->m; m; m=m->next) {
  1264.       if (!matchstring(&m->AttributeDescription,(char*)hn->a[i].a)) {
  1265.         /* same attribute */
  1266.         if (m->operation==Add)
  1267.           continue;
  1268.         else if (m->operation==Delete) {
  1269.           /* if it's delete, we need to check the value list */
  1270.           struct AttributeDescriptionList* adl=m->vals;
  1271.           if (!adl)
  1272.             todo=Drop;  /* if the list is empty, drop all */
  1273.           else
  1274.             for (adl=m->vals; adl; adl=adl->next) {
  1275.               if (!matchstring(&adl->a,(char*)hn->a[i].v)) {
  1276.                 todo=Drop;
  1277.                 break;
  1278.               }
  1279.             }
  1280.         } else
  1281.           todo=Drop;
  1282.       }
  1283.       if (todo==Drop) break;
  1284.     }
  1285.     if (todo==Keep) {
  1286.       *l=malloc(sizeof(**l));
  1287.       if (!*l) return -1;
  1288.       (*l)->next=0;
  1289.       (*l)->type.s=bstrfirst((char*)hn->a[i].a);
  1290.       (*l)->type.l=bstrlen((char*)hn->a[i].a);
  1291.       if (!((*l)->values=malloc(sizeof(*(*l)->values)))) return -1;
  1292.       (*l)->values->a.s=bstrfirst((char*)hn->a[i].v);
  1293.       (*l)->values->a.l=bstrlen((char*)hn->a[i].v);
  1294.       (*l)->values->attrofs=0;
  1295.       (*l)->values->next=0;
  1296.       l=&(*l)->next;
  1297.     }
  1298.   }
  1299.   /* then add all the "replace" or "add" attributes */
  1300.   for (m=&mr->m; m; m=m->next) {
  1301.     if ((m->operation==Add || m->operation==Replace) && m->vals) {
  1302.       *l=malloc(sizeof(**l));
  1303.       if (!*l) return -1;
  1304.       (*l)->next=0;
  1305.       (*l)->type.s=m->AttributeDescription.s;
  1306.       (*l)->type.l=m->AttributeDescription.l;
  1307.       if (copyadl2(&(*l)->values,m->vals)==-1) return -1;
  1308.       l=&(*l)->next;
  1309.     }
  1310.   }
  1311.   return 0;
  1312. }
  1313.  
  1314. /* write a search result entry to a file */
  1315. static int writesretofd(int fd,struct SearchResultEntry* sre) {
  1316.   /* we have no locking, but we open using O_APPEND, so the OS synchronizes for us as long
  1317.    * as we write atomically.  Therefore we have to buffer here. */
  1318.   size_t i,l,nl;
  1319.   char* c;
  1320.   struct PartialAttributeList* pal=sre->attributes;
  1321.   l=5+fmt_ldapescape(0,sre->objectName.s,sre->objectName.l);    /* "\ndn: ...\n" */
  1322.   if (l<=5) return -1;
  1323.   while (pal) {
  1324.     struct AttributeDescriptionList* adl=pal->values;
  1325.     while (adl) {
  1326.       nl=fmt_ldapescape(0,pal->type.s,pal->type.l);
  1327.       if (nl>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
  1328.       l+=nl;
  1329.       nl=fmt_ldapescape(0,adl->a.s,adl->a.l);
  1330.       if (nl>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
  1331.       l+=nl;
  1332.       if (l+3>HUGE_SIZE_FOR_SANITY_CHECKS) return -1;
  1333.       l+=3;
  1334.       adl=adl->next;
  1335.     }
  1336.     pal=pal->next;
  1337.   }
  1338.   c=alloca(l+1);
  1339.   if (!c) return -1;
  1340.   i=fmt_str(c,"dn: ");
  1341.   i+=fmt_ldapescape(c+i,sre->objectName.s,sre->objectName.l);
  1342.   i+=fmt_str(c+i,"\n");
  1343.   pal=sre->attributes;
  1344.   while (pal) {
  1345.     struct AttributeDescriptionList* adl=pal->values;
  1346.     while (adl) {
  1347.       i+=fmt_ldapescape(c+i,pal->type.s,pal->type.l);
  1348.       i+=fmt_str(c+i,": ");
  1349.       i+=fmt_ldapescape(c+i,adl->a.s,adl->a.l);
  1350.       i+=fmt_str(c+i,"\n");
  1351.       adl=adl->next;
  1352.     }
  1353.     pal=pal->next;
  1354.   }
  1355.   i+=fmt_str(c+i,"\n");
  1356.  
  1357.   return (write(fd,c,i)==(ssize_t)i)?0:-1;
  1358. }
  1359.  
  1360. /* This is the high level LDAP handling code.  It reads queries from the socket at in, and
  1361.  * then writes the answers to out.  Normally in == out, but they are separate here so this
  1362.  * can also be called with in=stdin and out=stdout. */
  1363.  
  1364. static void answerwithjournal(struct SearchRequest* sr,long messageid,int out);
  1365. static struct hashnode** dn_in_journal2(const char* dn,size_t dnlen);
  1366.  
  1367. static int lookupdn(struct string* dn,size_t* index, struct hashnode** hn) {
  1368.   struct Filter f;
  1369.   struct hashnode** tmphn;
  1370.   if (dn->l<1 || !dn->s) {
  1371.     buffer_putsflush(buffer_2,"lookupdn called for NULL dn!\n");
  1372.     return -1;
  1373.   }
  1374.   if ((tmphn=dn_in_journal2(dn->s,dn->l)) && *tmphn) {
  1375.     *hn=*tmphn;
  1376.     *index=-1;
  1377.     return (*hn)->n > 0;
  1378.   }
  1379.   *hn=0;
  1380.   f.type=EQUAL;
  1381.   f.ava.desc.l=2; f.ava.desc.s="dn";
  1382.   f.ava.value=*dn;
  1383.   f.next=f.x=0;
  1384.   fixup(&f);
  1385.   if (!indexable(&f)) {
  1386.     buffer_putsflush(buffer_2,"no index for dn, lookup failed!\n");
  1387.     return -1;
  1388.   } else {
  1389.     struct bitfield result;
  1390.     size_t i;
  1391.     result.bits=alloca(record_set_length*sizeof(unsigned long));
  1392.     useindex(&f,&result);
  1393.     if (result.first>result.last)
  1394.       return 0;
  1395. //    assert(result.last<=record_count);
  1396.     for (i=result.first; i<=result.last; ) {
  1397.       if (!result.bits[i/(8*sizeof(long))]) {
  1398.         i+=8*sizeof(long);
  1399.         continue;
  1400.       }
  1401.       for (; i<=result.last; ++i) {
  1402.         if (isset(&result,i)) {
  1403.           *index=i;
  1404.           return 1;
  1405.         }
  1406.       }
  1407.     }
  1408.   }
  1409.   return 0;
  1410. }
  1411.  
  1412. static void normalize_string_dn(struct string* s) {
  1413.   /* OK this is a kludge.  s->s is supposed to be read-only because it points into the
  1414.    * buffer where we read it into from the network.
  1415.    * Since normalize_dn ends up using less or equal space, and we are not interested in
  1416.    * the non-normalized dn, we do the read-write cast and normalize in-place.
  1417.    * Kids, don't do this at home. */
  1418.   s->l=normalize_dn((char*)s->s,s->s,s->l);
  1419. }
  1420.  
  1421. static void update();
  1422.  
  1423. void reply_with_index(struct SearchRequest* sr,unsigned long* messageid,int out) {
  1424.   size_t returned=0;
  1425.   struct bitfield result;
  1426.   size_t i;
  1427. #if (debug != 0)
  1428.   if (debug) buffer_putsflush(buffer_2,"query can be answered with index!\n");
  1429. #endif
  1430.   result.bits=alloca(record_set_length*sizeof(unsigned long));
  1431.   /* Use the index to find matching data.  Put the offsets
  1432.     * of the matches in a table.  Use findrec to locate
  1433.     * the records that point to the data. */
  1434.   useindex(sr->filter,&result);
  1435. //            assert(result.last<=record_count);
  1436.   for (i=result.first; i<=result.last; ) {
  1437.     size_t ni=i+8*sizeof(long);
  1438.     if (!result.bits[i/(8*sizeof(long))]) {
  1439.       i=ni;
  1440.       continue;
  1441.     }
  1442.     if (ni>record_count) ni=record_count;
  1443.     for (; i<ni; ++i) {
  1444.       if (isset(&result,i)) {
  1445.         uint32 j;
  1446.         uint32_unpack(map+indices_offset+4*i,&j);
  1447.         if (ldap_match_mapped(j,sr)) {
  1448.           if (sr->sizeLimit && sr->sizeLimit<++returned)
  1449.             break;
  1450.           answerwith(j,sr,*messageid,out);
  1451.         }
  1452.       }
  1453.     }
  1454.   }
  1455. }
  1456.  
  1457. /* a standard LDAP session looks like this:
  1458.  *   1. connect to server
  1459.  *   2. send a BindRequest
  1460.  *      get back a BindResponse
  1461.  *   3. send a SearchRequest
  1462.  *      get back n SearchResultEntries
  1463.  *      get back a SearchResultDone
  1464.  *   4. send an UnbindRequest
  1465.  *   5. close
  1466.  * tinyldap does not complain if you don't unbind before hanging up.
  1467.  */
  1468. static int handle(int in,int out) {
  1469.   size_t len;
  1470.   char buf[BUFSIZE];
  1471.   for (len=0;;) {
  1472.     int tmp=read(in,buf+len,BUFSIZE-len);
  1473.     int res;
  1474.     unsigned long messageid,op;
  1475.     size_t Len;
  1476.     if (tmp==0) {
  1477.       close(in);
  1478.       if (in!=out) close(out);
  1479.       return 0;
  1480. //      if (BUFSIZE-len) { return 0; }
  1481.     }
  1482.     if (tmp<0) { write(2,"error!\n",7); return 1; }
  1483.     len+=tmp;
  1484.     res=scan_ldapmessage(buf,buf+len,&messageid,&op,&Len);
  1485.     if (res>0) {
  1486.       if (verbose) {
  1487.         buffer_puts(buffer_2,"got message of length ");
  1488.         buffer_putulong(buffer_2,Len);
  1489.         buffer_puts(buffer_2," with id ");
  1490.         buffer_putulong(buffer_2,messageid);
  1491.         buffer_puts(buffer_2,": op ");
  1492.         buffer_putulong(buffer_2,op);
  1493.         buffer_putsflush(buffer_2,".\n");
  1494.       }
  1495.       update();
  1496.       switch (op) {
  1497.       case BindRequest:
  1498.         {
  1499.           unsigned long version,method;
  1500.           struct string name;
  1501.           size_t tmp;
  1502.           tmp=scan_ldapbindrequest(buf+res,buf+len,&version,&name,&method);
  1503.           if (tmp>0) {
  1504.             if (verbose) {
  1505.               buffer_puts(buffer_2,"bind request: version ");
  1506.               buffer_putulong(buffer_2,version);
  1507.               buffer_puts(buffer_2," for name \"");
  1508.               buffer_put(buffer_2,name.s,name.l);
  1509.               buffer_puts(buffer_2,"\" with method ");
  1510.               buffer_putulong(buffer_2,method);
  1511.               buffer_putsflush(buffer_2,".\n");
  1512.             }
  1513.             if (name.l) {
  1514.               struct string password;
  1515.               size_t idx;
  1516.               struct hashnode* hn;
  1517.               int err=success;
  1518.  
  1519.               scan_ldapstring(buf+res+tmp,buf+len,&password);
  1520.  
  1521.               normalize_string_dn(&name);
  1522.               switch (lookupdn(&name,&idx,&hn)) {
  1523.               case -1: err=operationsError; break;
  1524.               case 1: break;
  1525.               case 0: err=noSuchObject; break;
  1526.               default: err=operationsError;
  1527.               }
  1528.               if (err!=success)
  1529.                 goto authfailure;
  1530.               else {
  1531.                 char* c=0;
  1532.                 uint32 authdn=0;
  1533.                 char* authdn_str=0;
  1534.                 if (idx==(size_t)-1) {  // found in journal
  1535.                   size_t i;
  1536.                   for (i=0; i<hn->n; ++i)
  1537.                     if (!strcmp((char*)hn->a[i].a,"userPassword")) {
  1538.                       c=(char*)hn->a[i].v;
  1539.                       authdn=0;
  1540.                       authdn_str=(char*)hn->dn;
  1541.                       break;
  1542.                     }
  1543.                 } else {        // found in db
  1544.                   uint32 j;
  1545.                   uint32_unpack(map+indices_offset+4*idx,&j);
  1546.                   uint32_unpack(map+j+8,&authdn);
  1547.                   authdn_str=map+authdn;
  1548.                   authdn=j;
  1549.                   if (!(j=ldap_find_attr_value(j,userPassword_ofs))) {
  1550.                     buffer_putsflush(buffer_2,"no userPassword attribute found, bind failed!\n");
  1551.                     goto authfailure;
  1552.                   }
  1553.                   c=map+j;
  1554.                 }
  1555.  
  1556.                 if (check_password(c,&password)) {
  1557.                   authenticated_as=authdn;
  1558.                   authenticated_as_str=authdn_str;
  1559.                   if (acls) {
  1560.                     size_t i;
  1561.                     for (i=0; i<filters; ++i)
  1562.                       acl_ec_subjects[i]=(Filters[i]==(struct Filter*)Any);
  1563.                     for (i=0; i<acls; ++i) {
  1564.                       size_t j=Acls[i]->subject;
  1565.                       if (!acl_ec_subjects[j]) {
  1566.                         if (authdn==0)  // authenticated against hashnode
  1567.                           acl_ec_subjects[j]=ldap_matchfilter_hn(hn,Filters[j]);
  1568.                         else    // authenticated against mapped db
  1569.                           acl_ec_subjects[j]=ldap_matchfilter_mapped(authdn,Filters[j]);
  1570.                       }
  1571.                     }
  1572.                   }
  1573.                 } else
  1574. authfailure:
  1575.                 {
  1576.                   char outbuf[1024];
  1577.                   size_t s=100;
  1578.                   size_t len=fmt_ldapbindresponse(outbuf+s,inappropriateAuthentication,"","authentication failure","");
  1579.                   size_t hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
  1580.                   fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
  1581.                   write(out,outbuf+s-hlen,len+hlen);
  1582.                   continue;
  1583.                 }
  1584.               }
  1585.             }
  1586.             {
  1587.               char outbuf[1024];
  1588.               size_t s=100;
  1589.               size_t len=fmt_ldapbindresponse(outbuf+s,0,"","go ahead","");
  1590.               size_t hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
  1591.               fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
  1592.               write(out,outbuf+s-hlen,len+hlen);
  1593.             }
  1594.           }
  1595.         }
  1596.         break;
  1597.       case SearchRequest:
  1598.         {
  1599.           struct SearchRequest sr;
  1600.           size_t tmp;
  1601. #if 0
  1602.           {
  1603.             int fd=open_write("request");
  1604.             write(fd,buf,res+len);
  1605.             close(fd);
  1606.           }
  1607. #endif
  1608.           if ((tmp=scan_ldapsearchrequest(buf+res,buf+len,&sr))) {
  1609.             size_t returned=0;
  1610.  
  1611. #if (debug != 0)
  1612.             if (debug) {
  1613.               const char* scopes[]={"baseObject","singleLevel","wholeSubtree"};
  1614.               const char* alias[]={"neverDerefAliases","derefInSearching","derefFindingBaseObj","derefAlways"};
  1615.               buffer_puts(buffer_2,"search request: baseObject \"");
  1616.               buffer_put(buffer_2,sr.baseObject.s,sr.baseObject.l);
  1617.               buffer_puts(buffer_2,"\", scope ");
  1618.               buffer_puts(buffer_2,scopes[sr.scope]);
  1619.               buffer_puts(buffer_2,", ");
  1620.               buffer_puts(buffer_2,alias[sr.derefAliases]);
  1621.               buffer_puts(buffer_2,"\nsize limit ");
  1622.               buffer_putulong(buffer_2,sr.sizeLimit);
  1623.               buffer_puts(buffer_2,", time limit ");
  1624.               buffer_putulong(buffer_2,sr.timeLimit);
  1625.               buffer_puts(buffer_2,"\n");
  1626.               printfilter(sr.filter);
  1627.               buffer_puts(buffer_2,"attributes: ");
  1628.               printal(sr.attributes);
  1629.               buffer_putsflush(buffer_2,"\n\n");
  1630.             }
  1631. #endif
  1632.             fixup(sr.filter);
  1633.             fixupadl(sr.attributes);
  1634.             if (indexable(sr.filter)) {
  1635.               reply_with_index(&sr,&messageid,out);
  1636.             } else {
  1637.               char* x=map+5*4+size_of_string_table+attribute_count*8;
  1638.               size_t i;
  1639. #if (debug != 0)
  1640.               if (debug) buffer_putsflush(buffer_2,"query can NOT be answered with index!\n");
  1641. #endif
  1642.               for (i=0; i<record_count; ++i) {
  1643.                 uint32 j;
  1644.                 uint32_unpack(x,&j);
  1645.                 if (ldap_match_mapped(x-map,&sr)) {
  1646.                   if (sr.sizeLimit && sr.sizeLimit<++returned)
  1647.                     break;
  1648.                   answerwith(x-map,&sr,messageid,out);
  1649.                 }
  1650.                 x+=j*8;
  1651.               }
  1652.             }
  1653.  
  1654.             /* now answer with the results from the journal */
  1655.             answerwithjournal(&sr,messageid,out);
  1656.             free_ldapsearchrequest(&sr);
  1657.           } else {
  1658.             buffer_putsflush(buffer_2,"couldn't parse search request!\n");
  1659.             exit(1);
  1660.           }
  1661.           {
  1662.             char buf[1000];
  1663.             size_t l=fmt_ldapsearchresultdone(buf+100,0,"","","");
  1664.             size_t hlen=fmt_ldapmessage(0,messageid,SearchResultDone,l);
  1665.             fmt_ldapmessage(buf+100-hlen,messageid,SearchResultDone,l);
  1666.             write(out,buf+100-hlen,l+hlen);
  1667.           }
  1668.         }
  1669.         break;
  1670.       case UnbindRequest:
  1671.         close(out); if (in!=out) close(in);
  1672.         return 0;
  1673.       case ModifyRequest:
  1674.         {
  1675.           struct ModifyRequest mr;
  1676.           size_t tmp,err=success;
  1677.           buffer_putsflush(buffer_2,"modifyrequest!\n");
  1678.           if ((tmp=scan_ldapmodifyrequest(buf+res,buf+len,&mr))) {
  1679.             struct SearchResultEntry sre;
  1680.             if (verbose) {
  1681.               buffer_puts(buffer_1,"modify request: dn \"");
  1682.               buffer_put(buffer_1,mr.object.s,mr.object.l);
  1683.               buffer_putsflush(buffer_1,"\"\n");
  1684.               switch (mr.m.operation) {
  1685.               case 0: buffer_puts(buffer_1,"Add\n"); break;
  1686.               case 1: buffer_puts(buffer_1,"Delete\n"); break;
  1687.               case 2: buffer_puts(buffer_1,"Replace\n"); break;
  1688.               }
  1689.               buffer_put(buffer_1,mr.m.AttributeDescription.s,mr.m.AttributeDescription.l);
  1690.               buffer_puts(buffer_1,"\n");
  1691.               {
  1692.                 struct AttributeDescriptionList* x=mr.m.vals;
  1693.                 do {
  1694.                   buffer_puts(buffer_1," -> \"");
  1695.                   buffer_put(buffer_1,x->a.s,x->a.l);
  1696.                   buffer_putsflush(buffer_1,"\"\n");
  1697.                   x=x->next;
  1698.                 } while (x);
  1699.               }
  1700.             }
  1701.  
  1702.             normalize_string_dn(&mr.object);
  1703.  
  1704.             if (acls) {
  1705.               /* convert modifyrequest to searchresultentry */
  1706.               modreq2sre(&sre,&mr);
  1707.               /* 1. check ACLs */
  1708.               if (checkacl(0,0,acl_write,&sre)!=1)
  1709.                 err=insufficientAccessRights;
  1710.               free_ldapsearchresultentry(&sre);
  1711.             } else
  1712.               err=insufficientAccessRights;
  1713.             if (err==success) {
  1714.               /* 2. check if there already is a record with this dn */
  1715.               struct hashnode* hn;
  1716.               size_t idx;
  1717.               switch (lookupdn(&mr.object,&idx,&hn)) {
  1718.               case -1: err=operationsError; break;
  1719.               case 1: break;
  1720.               case 0: err=noSuchObject; break;
  1721.               default: err=operationsError;
  1722.               }
  1723.               if (err==success) {
  1724. #if 1
  1725.                 /* 3. apply modifications to record to get new record */
  1726.                 if (!applymodreq(hn,&mr,&sre)) {
  1727.                   /* 4. write record to journal */
  1728.                   int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
  1729.                   if (fd==-1)
  1730.                     err=operationsError;
  1731.                   else {
  1732.                     if (writesretofd(fd,&sre)==-1)
  1733.                       err=operationsError;
  1734.                     close(fd);
  1735.                   }
  1736.                 } else
  1737.                   err=operationsError;
  1738.                 free_ldapsearchresultentry(&sre);
  1739. #else
  1740.                 err=operationsError;
  1741. #endif
  1742.               }
  1743.             }
  1744.           } else {
  1745.             buffer_putsflush(buffer_2,"could not parse modifyRequest!\n");
  1746.             err=protocolError;
  1747.           }
  1748.  
  1749.           {
  1750.             char outbuf[1024];
  1751.             int s=100;
  1752.             int len=fmt_ldapresult(outbuf+s,err,"","","");
  1753.             int hlen=fmt_ldapmessage(0,messageid,AddResponse,len);
  1754.             fmt_ldapmessage(outbuf+s-hlen,messageid,AddResponse,len);
  1755.             write(out,outbuf+s-hlen,len+hlen);
  1756.           }
  1757.  
  1758.           free_ldapmodifyrequest(&mr);
  1759.         }
  1760.         break;
  1761.       case AbandonRequest:
  1762.         if (verbose) buffer_putsflush(buffer_2,"AbandonRequest!\n");
  1763.         /* do nothing */
  1764.         break;
  1765.       case AddRequest:
  1766.         {
  1767.           int err=success;
  1768.           struct AddRequest ar;
  1769. //          buffer_putsflush(buffer_2,"AddRequest!\n");
  1770.           if ((tmp=scan_ldapaddrequest(buf+res,buf+len,&ar))) {
  1771.             struct SearchResultEntry sre;
  1772.             normalize_string_dn(&ar.entry);
  1773.             /* convert addrequest to searchresultentry */
  1774.             addreq2sre(&sre,&ar);
  1775.  
  1776.             /* 1. check ACLs */
  1777.             if (checkacl(0,0,acl_add,&sre)==1) {
  1778.               /* 2. check if there already is a record with this dn */
  1779.               struct hashnode* hn;
  1780.               size_t idx;
  1781.               switch (lookupdn(&sre.objectName,&idx,&hn)) {
  1782.               case -1: err=operationsError; break;
  1783.               case 1: err=entryAlreadyExists; break;
  1784.               case 0: break;
  1785.               default: err=operationsError;
  1786.               }
  1787.               if (err==success) {
  1788.                 /* 3. write record to journal */
  1789.                 int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
  1790.                 if (fd==-1)
  1791.                   err=operationsError;
  1792.                 else {
  1793.                   if (writesretofd(fd,&sre)==-1)
  1794.                     err=operationsError;
  1795.                   close(fd);
  1796.                 }
  1797.               }
  1798.             } else
  1799.               err=insufficientAccessRights;
  1800.           } else
  1801.             err=protocolError;
  1802.  
  1803.           buffer_put(buffer_1,ar.entry.s,ar.entry.l);
  1804.           buffer_putsflush(buffer_1,"\n");
  1805.           if (verbose) { /* iterate all attributes */
  1806.             struct Addition * x;
  1807.             struct AttributeDescriptionList * y;
  1808.             for (x = &ar.a;x;x=x->next) {
  1809.               for (y = &x->vals;y;y=y->next) {
  1810.                 buffer_put(buffer_1,x->AttributeDescription.s,x->AttributeDescription.l);
  1811.                 buffer_puts(buffer_1,": ");
  1812.                 buffer_put(buffer_1,y->a.s,y->a.l);
  1813.                 buffer_putsflush(buffer_1,"\n");
  1814.               }
  1815.             }
  1816.           }
  1817.  
  1818.           free_ldapaddrequest(&ar);
  1819.  
  1820.           {
  1821.             char outbuf[1024];
  1822.             size_t s=100;
  1823.             size_t len=fmt_ldapresult(outbuf+s,err,"","","");
  1824.             size_t hlen=fmt_ldapmessage(0,messageid,AddResponse,len);
  1825.             fmt_ldapmessage(outbuf+s-hlen,messageid,AddResponse,len);
  1826.             write(out,outbuf+s-hlen,len+hlen);
  1827.           }
  1828.         }
  1829.         break;
  1830.       case DelRequest:
  1831.         {
  1832.           struct string s;
  1833.           size_t l=scan_ldapdeleterequest(buf+res,buf+len,&s);
  1834.           if (l>0) {
  1835.             struct SearchResultEntry sre;
  1836.             int err=success;
  1837.             if (verbose) {
  1838.               buffer_puts(buffer_2,"Delete Request for DN \"");
  1839.               buffer_put(buffer_2,s.s,s.l);
  1840.               buffer_putsflush(buffer_2,"\".\n");
  1841.             }
  1842.             normalize_string_dn(&s);
  1843.             /* convert modifyrequest to searchresultentry */
  1844.             sre.objectName=s;
  1845.             sre.attributes=0;
  1846.             /* 1. check ACLs */
  1847.             if (checkacl(0,0,acl_delete,&sre)!=1)
  1848.               err=insufficientAccessRights;
  1849.             if (err==success) {
  1850.               /* 2. check if there already is a record with this dn */
  1851.               struct hashnode* hn;
  1852.               size_t idx;
  1853.               switch (lookupdn(&s,&idx,&hn)) {
  1854.               case -1: err=operationsError; break;
  1855.               case 1: break;
  1856.               case 0: err=noSuchObject; break;
  1857.               default: err=operationsError;
  1858.               }
  1859.               if (err==success) {
  1860.                 /* 3. write record to journal */
  1861.                 int fd=open("journal",O_WRONLY|O_APPEND|O_CREAT,0600);
  1862.                 if (fd==-1)
  1863.                   err=operationsError;
  1864.                 else {
  1865.                   if (writesretofd(fd,&sre)==-1)
  1866.                     err=operationsError;
  1867.                   close(fd);
  1868.                 }
  1869.               }
  1870.             }
  1871.             {
  1872.               char outbuf[1024];
  1873.               size_t s=100;
  1874.               size_t len=fmt_ldapresult(outbuf+s,err,"","","");
  1875.               size_t hlen=fmt_ldapmessage(0,messageid,DelResponse,len);
  1876.               fmt_ldapmessage(outbuf+s-hlen,messageid,DelResponse,len);
  1877.               write(out,outbuf+s-hlen,len+hlen);
  1878.             }
  1879.           }
  1880.         }
  1881.         break;
  1882.       case ModifyDNRequest:
  1883.         /* TODO */
  1884.       default:
  1885.         buffer_puts(buffer_2,"unknown request type ");
  1886.         buffer_putulong(buffer_2,op);
  1887.         buffer_putsflush(buffer_2,"\n");
  1888.         return 0;
  1889. //      exit(1);
  1890.       }
  1891.       Len+=res;
  1892. #if 0
  1893.       buffer_puts(buffer_2,"byte_copy(buf,");
  1894.       buffer_putulong(buffer_2,len-Len);
  1895.       buffer_puts(buffer_2,",buf+");
  1896.       buffer_putulong(buffer_2,Len);
  1897.       buffer_putsflush(buffer_2,");\n");
  1898. #endif
  1899.       if (Len<len) {
  1900.         byte_copy(buf,len-Len,buf+Len);
  1901.         len-=Len;
  1902.       } else len=0;
  1903.     } else
  1904.       exit(2);
  1905.   }
  1906. }
  1907.  
  1908.  
  1909.  
  1910. /* journal reading code */
  1911.  
  1912. extern int (*ldif_parse_callback)(struct ldaprec* l);
  1913.  
  1914. extern mstorage_t stringtable;
  1915. extern mduptab_t attributes,classes;
  1916.  
  1917. static unsigned long hash2(const unsigned char* c) {
  1918.   unsigned long h=0;
  1919.   if (*c==0) {
  1920.     uint32 len=uint32_read((char*)c+1);
  1921.     return hash(c+5,len);
  1922.   }
  1923.   while (*c) {
  1924.     /* from djb's cdb */
  1925.     h += (h<<5);
  1926.     h ^= *c;
  1927.     ++c;
  1928.   }
  1929.   return (uint32)h;
  1930. }
  1931.  
  1932. #define HASHTABSIZE 8191
  1933.  
  1934. static unsigned char* bstrdup(unsigned char* c) {
  1935.   size_t len;
  1936.   unsigned char* x;
  1937.   if (*c)
  1938.     len=str_len((char*)c)+1;
  1939.   else {
  1940.     len=5+uint32_read((char*)c+1);
  1941.     if (len<5) return 0;
  1942.   }
  1943.   x=malloc(len);
  1944.   if (x) byte_copy(x,len,c);
  1945.   return x;
  1946. }
  1947.  
  1948. static unsigned char* bstrdup_attrib(unsigned char* c) {
  1949.   char* x=map+5*4+size_of_string_table;
  1950.   size_t i,l;
  1951.   if (*c)
  1952.     l=str_len((char*)c)+1;
  1953.   else {
  1954.     l=uint32_read((char*)c+1);
  1955.     c+=5;
  1956.   }
  1957.   for (i=0; i<attribute_count; ++i) {
  1958.     uint32 j=uint32_read(x);
  1959.     if (case_equalb(c,l,map+j))
  1960.       return (unsigned char*)map+j;
  1961.     x+=4;
  1962.   }
  1963.   return bstrdup(c);
  1964. }
  1965.  
  1966. struct hashnode* hashtab[HASHTABSIZE];
  1967.  
  1968. static struct hashnode** dn_in_journal(unsigned char* dn) {
  1969.   unsigned long hashval;
  1970.   struct hashnode** hn;
  1971.   hashval=hash2(dn);
  1972.   hn=hashtab+(hashval%HASHTABSIZE);
  1973.   while (*hn) {
  1974.     if ((*hn)->hashval==hashval) {
  1975.       if (!bstr_diff((char*)(*hn)->dn,(char*)dn))
  1976.         break;
  1977.     }
  1978.     hn=&((*hn)->next);
  1979.   }
  1980.   return hn;
  1981. }
  1982.  
  1983. static struct hashnode** dn_in_journal2(const char* dn,size_t dnlen) {
  1984.   unsigned long hashval;
  1985.   struct hashnode** hn;
  1986.   hashval=hash((const unsigned char*)dn,dnlen);
  1987. //  printf("lookup: \"%.*s\" -> %lu\n",dnlen,dn,hashval);
  1988.   hn=hashtab+(hashval%HASHTABSIZE);
  1989.   while (*hn) {
  1990.     if ((*hn)->hashval==hashval) {
  1991.       if (!bstr_diff2((char*)(*hn)->dn,dn,dnlen))
  1992.         break;
  1993.     }
  1994.     hn=&((*hn)->next);
  1995.   }
  1996.   return hn;
  1997. }
  1998.  
  1999. struct hashnode* root;
  2000.  
  2001. static int parse_callback(struct ldaprec* l) {
  2002.   static struct hashnode** nextinlinearlist=&root;
  2003.   size_t i;
  2004.   unsigned long hashval;
  2005.   struct hashnode** hn;
  2006.   if (l->dn==(uint32)-1)
  2007.     return -1;
  2008.   hashval=hash2((unsigned char*)stringtable.root+l->dn);
  2009. //  printf("journal: \"%s\" -> %lu\n",stringtable.root+l->dn,hashval);
  2010.   hn=hashtab+(hashval%HASHTABSIZE);
  2011.   while (*hn) {
  2012.     if ((*hn)->hashval==hashval) {
  2013.       if (!bstr_diff((char*)(*hn)->dn,stringtable.root+l->dn))
  2014.         break;
  2015.     }
  2016.     hn=&((*hn)->next);
  2017.   }
  2018.   if (*hn) {
  2019.     /* a record with this dn exists */
  2020.     /* adjust it to the new reality */
  2021.     for (i=0; i<(*hn)->n; ++i) {
  2022.       free((*hn)->a[i].a);
  2023.       free((*hn)->a[i].v);
  2024.     }
  2025.     *hn = realloc(*hn,sizeof(**hn)-sizeof(struct attribute2)+l->n*sizeof(struct attribute2));
  2026.     if (!*hn) nomem: die(1,"out of memory!");
  2027.   } else {
  2028.     *hn = malloc(sizeof(**hn)-sizeof(struct attribute2)+l->n*sizeof(struct attribute2));
  2029.     if (!*hn) goto nomem;
  2030.     if (!((*hn)->dn=bstrdup((unsigned char*)stringtable.root+l->dn))) goto nomem;
  2031.     (*hn)->hashval=hashval;
  2032.     (*hn)->next=0;
  2033.  
  2034.     (*hn)->overwrite=0;
  2035.     /* put new entry in the linear list */
  2036.     *nextinlinearlist=*hn;
  2037.     (*hn)->linear=0;
  2038.     nextinlinearlist=&(*hn)->linear;
  2039.   }
  2040.   (*hn)->n=l->n;
  2041.   for (i=0; i<l->n; ++i) {
  2042.     if (!((*hn)->a[i].a=bstrdup_attrib((unsigned char*)attributes.strings.root+l->a[i].name)) ||
  2043.         !((*hn)->a[i].v=bstrdup((unsigned char*)((*hn)->a[i].a==(unsigned char*)map+objectClass_ofs?classes.strings.root:stringtable.root)+l->a[i].value))) goto nomem;
  2044.   }
  2045.   stringtable.used=0;
  2046.   return 0;
  2047. }
  2048.  
  2049. static void readjournal() {
  2050.   ldif_parse_callback=parse_callback;
  2051.   mduptab_init(&attributes);
  2052.   mduptab_init(&classes);
  2053.   if (ldif_parse("journal",0,&ss_journal)) {
  2054.     buffer_putsflush(buffer_2,"Failed to parse journal!\n");
  2055.     exit(1);
  2056.   }
  2057. }
  2058.  
  2059. static void update() {
  2060.   struct stat new_data,new_journal;
  2061.   if (stat(datafilename,&new_data)==-1) {
  2062.     /* no data file?!  There is no way to salvage the situation. */
  2063.     buffer_putsflush(buffer_2,"ABEND: data file suddenly gone.\n");
  2064.     exit(1);
  2065.   }
  2066.   /* now see if the data file changed.  If it did, map it anew. */
  2067.   if (new_data.st_size!=ss_data.st_size ||
  2068.       new_data.st_mtime!=ss_data.st_mtime ||
  2069.       new_data.st_ino!=ss_data.st_ino) {
  2070.     buffer_putsflush(buffer_2,"Data file changed, reloading.\n");
  2071.     mmap_unmap(map,filelen);
  2072.     /* If the new data file is corrupt, map_datafile calls exit.
  2073.      * I don't believe in limping on.  If something is broken on such a fundamental level,
  2074.      * it's better to bail so that the problem does not go unnoticed and things get even
  2075.      * worse. */
  2076.     map_datafile(datafilename);
  2077.     /* OK, now that we have the datafile reloaded, we need to clean our idea of a journal
  2078.      * and reload the journal from scratch. */
  2079. resetjournal:
  2080.     mduptab_reset(&attributes);
  2081.     mduptab_reset(&classes);
  2082.     readjournal();
  2083.     return;
  2084.   }
  2085.   /* the data file did not change.  Maybe the journal did. */
  2086.   if (stat("journal",&new_journal)==-1) {
  2087.     /* no journal; that means:
  2088.      * a) there never was one, totaly read-only data
  2089.      * b) there was one, but it has now been incorporated into the main database
  2090.      *    in this case: delete journal data
  2091.      */
  2092.     mduptab_reset(&attributes);
  2093.     mduptab_reset(&classes);
  2094.     return;
  2095.   }
  2096.   if (new_journal.st_size!=ss_journal.st_size ||
  2097.       new_journal.st_mtime!=ss_journal.st_mtime ||
  2098.       new_journal.st_ino!=ss_journal.st_ino) {
  2099.     /* Journal changed.  Since all we ever do is append, we just read the part from how
  2100.      * far we got last time, which happens to be ss_journal.st_size. */
  2101.  
  2102.     /* On the other hand, we should make a valiant effort to not break if someone edits
  2103.      * his journal manually. After all, that's why our journal is in text form.
  2104.      * We look for two clues that someone edited his journal:
  2105.      *   1. size is identical or smaller
  2106.      *   2. journal does not end with "\n\n"
  2107.      * If we detect meddling we just throw away our journal and read the new one. */
  2108.     int notkosher=0;
  2109.     if (new_journal.st_size>ss_journal.st_size && ss_journal.st_size>2) {
  2110.       int fd;
  2111.       fd=open("journal",O_RDONLY);
  2112.       if (fd!=-1) {
  2113.         char buf[2];
  2114.         lseek(fd,ss_journal.st_size-2,SEEK_SET);
  2115.         if (read(fd,buf,2)!=2)
  2116.           if (buf[0]=='\n' && buf[1]=='\n')
  2117.             notkosher=1;
  2118.         close(fd);
  2119.       }
  2120.     }
  2121.     if (notkosher) {
  2122.       buffer_putsflush(buffer_2,"Unsanctioned journal editing detected!  Re-reading journal.\n");
  2123.       goto resetjournal;
  2124.     }
  2125.     if (ldif_parse("journal",ss_journal.st_size,&ss_journal)) {
  2126.       buffer_putsflush(buffer_2,"Failed to parse journal!\n");
  2127.       exit(1);
  2128.     }
  2129.     ss_data=new_data;
  2130.   }
  2131. }
  2132.  
  2133. static int ldap_matchfilter_hn(struct hashnode* hn,struct Filter* f) {
  2134.   struct Filter* y=f->x;
  2135.   size_t i;
  2136.   if (!hn->n) return 0;
  2137.   if (!f) return 1;
  2138.   switch (f->type) {
  2139.   case AND:
  2140.     while (y) {
  2141.       if (!ldap_matchfilter_hn(hn,y)) return 0;
  2142.       y=y->next;
  2143.     }
  2144.     return 1;
  2145.   case OR:
  2146.     while (y) {
  2147.       if (ldap_matchfilter_hn(hn,y)) return 1;
  2148.       y=y->next;
  2149.     }
  2150.     return 0;
  2151.   case NOT:
  2152.     return !ldap_matchfilter_hn(hn,y);
  2153.   case PRESENT:
  2154.     if (f->attrofs==dn_ofs)
  2155.       return 1;
  2156.     for (i=0; i<hn->n; ++i)
  2157.       if (!matchstring(&f->ava.desc,(char*)hn->a[i].a))
  2158.         return 1;
  2159.     return 0;
  2160.   case EQUAL:
  2161.   case LESSEQUAL:
  2162.   case GREATEQUAL:
  2163.     if (f->attrofs==dn_ofs)
  2164.       return matchint(f,(char*)hn->dn);
  2165.     for (i=0; i<hn->n; ++i)
  2166.       if (!matchstring(&f->ava.desc,(char*)hn->a[i].a) &&
  2167.           matchint(f,(char*)hn->a[i].v)) return 1;
  2168.     return 0;
  2169.   case SUBSTRING:
  2170.     if (f->attrofs==dn_ofs)
  2171.       return substringmatch(f->substrings,(char*)hn->dn,f->attrflag&1);
  2172.     for (i=0; i<hn->n; ++i)
  2173.       if (!matchstring(&f->ava.desc,(char*)hn->a[i].a) &&
  2174.           substringmatch(f->substrings,(char*)hn->a[i].v,f->attrflag&1)) return 1;
  2175.     return 0;
  2176.   default:
  2177.     write(2,"unsupported query type\n",23);
  2178.     return 0;
  2179.   }
  2180.   return 1;
  2181. }
  2182.  
  2183. /* return 0 if they didn't match, otherwise return length in b */
  2184. static int match(const char* a,int len,const char* b) {
  2185.   const char* A=a+len;
  2186.   const char* B=b+str_len(b);
  2187.   while (len>0 && A>a && B>b) {
  2188.     --A; --B; --len;
  2189.     while (*A==' ' && A>a) { --A; --len; }
  2190.     while (*B==' ' && B>b) --B;
  2191.     if (tolower(*A) != tolower(*B))
  2192.       return 0;
  2193.   }
  2194.   return str_len(B);
  2195. }
  2196.  
  2197. static int matchhashnode(struct hashnode* hn,struct SearchRequest* sr) {
  2198.   size_t i,len=bstrlen((char*)hn->dn);
  2199.   unsigned char* c;
  2200.   if (sr->baseObject.l>len)
  2201.     /* baseObject is longer than dn */
  2202.     return 0;
  2203.   if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,(char*)hn->dn))
  2204.     /* baseObject is not a suffix of dn */
  2205.     return 0;
  2206.   switch (sr->scope) {
  2207.   case wholeSubtree: break;
  2208.   case baseObject: if (len==sr->baseObject.l) break; return 0;
  2209.   default:
  2210.     c=hn->dn+bstrstart((char*)hn->dn);
  2211.     for (i=0; i<len; ++i)
  2212.       if (c[i]==',')
  2213.         break;
  2214.     if (i+2>=len-sr->baseObject.l) break;
  2215.     return 0;
  2216.   }
  2217.   return ldap_matchfilter_hn(hn,sr->filter);
  2218. }
  2219.  
  2220. static void answerwith_hn(struct hashnode* hn,struct SearchRequest* sr,long messageid,int out) {
  2221.   struct SearchResultEntry sre;
  2222.   struct PartialAttributeList** pal=&sre.attributes;
  2223.  
  2224.   if (!hn->n) return;
  2225.   if (acls)
  2226.     byte_zero(acl_ec_subjects+filters,filters);
  2227.  
  2228.   if (acls && checkacl_hn(hn,(unsigned char*)map+dn_ofs,acl_read)!=1) return;
  2229.  
  2230.   sre.objectName.l=bstrlen(sre.objectName.s=(char*)hn->dn);
  2231.   sre.attributes=0;
  2232.  
  2233.   /* now go through list of requested attributes */
  2234.   {
  2235.     struct AttributeDescriptionList* adl=sr->attributes;
  2236.     if (!adl && hn->n && hn->n<HUGE_SIZE_FOR_SANITY_CHECKS/sizeof(*adl)) {
  2237.       /* did not ask for any attributes.  send 'em all. */
  2238.       /* to do that, construct a list of all attributes */
  2239.  
  2240.       uint32 i,j,k;
  2241.       adl=alloca(hn->n*sizeof(*adl));
  2242.       for (i=k=0; i<hn->n; ++i) {
  2243.         adl[k].a.s=(char*)hn->a[i].a;
  2244.         adl[k].a.l=str_len((char*)hn->a[i].a);
  2245.         adl[k].attrofs=0;
  2246.         adl[k].next=adl+k+1;
  2247.         for (j=0; j<i; ++j) {
  2248.           if (!strcmp((char*)hn->a[i].a,(char*)hn->a[j].a)) {
  2249.             --k;
  2250.             break;
  2251.           }
  2252.         }
  2253.         ++k;
  2254.       }
  2255.       if (k) adl[k-1].next=0;
  2256.     }
  2257.     while (adl) {
  2258.       const unsigned char* val=0;
  2259.       uint32 i=0;
  2260.  
  2261.       if (!acls || checkacl_hn(hn,(unsigned char*)adl->a.s,acl_read)==1) {
  2262.         if (!matchstring(&adl->a,"dn"))
  2263.           val=hn->dn;
  2264.         else {
  2265.           for (; i<hn->n; ++i)
  2266.             if (!matchstring(&adl->a,(char*)hn->a[i].a)) {
  2267.               val=hn->a[i].v;
  2268.               ++i;
  2269.               break;
  2270.             }
  2271.         }
  2272.         if (val) {
  2273.           *pal=malloc(sizeof(struct PartialAttributeList));
  2274.           if (!*pal) {
  2275. nomem:
  2276.             buffer_putsflush(buffer_2,"out of virtual memory!\n");
  2277.             exit(1);
  2278.           }
  2279.           (*pal)->type=adl->a;
  2280.           {
  2281.             struct AttributeDescriptionList** a;
  2282.             a=&(*pal)->values;
  2283. add_attribute:
  2284.             *a=malloc(sizeof(struct AttributeDescriptionList));
  2285.             if (!*a) goto nomem;
  2286.             (*a)->a.s=bstrfirst((char*)val);
  2287.             (*a)->a.l=bstrlen((char*)val);
  2288.             for (;i<hn->n; ++i)
  2289.               if (!matchstring(&adl->a,(char*)hn->a[i].a)) {
  2290.                 val=hn->a[i].v;
  2291.                 ++i;
  2292.                 a=&(*a)->next;
  2293.                 goto add_attribute;
  2294.               }
  2295.             (*a)->next=0;
  2296.           }
  2297.           (*pal)->next=0;
  2298.           pal=&(*pal)->next;
  2299.         }
  2300.       }
  2301.       adl=adl->next;
  2302.     }
  2303.   }
  2304.   {
  2305.     long l=fmt_ldapsearchresultentry(0,&sre);
  2306.     char *buf;
  2307.     long tmp;
  2308.     if (l<HUGE_SIZE_FOR_SANITY_CHECKS) {
  2309.       buf=alloca(l+300); /* you never know ;) */
  2310.       if (verbose) {
  2311.         buffer_puts(buffer_2,"sre len ");
  2312.         buffer_putulong(buffer_2,l);
  2313.         buffer_putsflush(buffer_2,".\n");
  2314.       }
  2315.       tmp=fmt_ldapmessage(buf,messageid,SearchResultEntry,l);
  2316.       fmt_ldapsearchresultentry(buf+tmp,&sre);
  2317.       write(out,buf,l+tmp);
  2318.     }
  2319.   }
  2320.   free_ldappal(sre.attributes);
  2321. }
  2322.  
  2323. static void answerwithjournal(struct SearchRequest* sr,long messageid,int out) {
  2324.   struct hashnode* hn=root;
  2325.   while (hn) {
  2326.     if (!hn->overwrite && matchhashnode(hn,sr))
  2327.       answerwith_hn(hn,sr,messageid,out);
  2328.     hn=hn->linear;
  2329.   }
  2330. }
  2331.  
  2332. /*
  2333.                  _
  2334.  _ __ ___   __ _(_)_ __
  2335. | '_ ` _ \ / _` | | '_ \
  2336. | | | | | | (_| | | | | |
  2337. |_| |_| |_|\__,_|_|_| |_|
  2338. */
  2339.  
  2340. int main(int argc,char* argv[]) {
  2341. #ifdef STANDALONE
  2342.   int sock;
  2343. #endif
  2344.  
  2345.   errmsg_iam("tinyldap");
  2346.  
  2347.   signal(SIGPIPE,SIG_IGN);
  2348.  
  2349.   map_datafile(argc>1?argv[1]:"data");
  2350.  
  2351.   readjournal();
  2352.  
  2353. #if 0
  2354.   ldif_parse("exp.ldif");
  2355.   if (!first) {
  2356.     buffer_putsflush(buffer_2,"no data?!");
  2357.   }
  2358. #endif
  2359.  
  2360. #ifdef STANDALONE
  2361.   if ((sock=socket_tcp6b())==-1) {
  2362.     buffer_putsflush(buffer_2,"socket failed!\n");
  2363.     exit(1);
  2364.   }
  2365.   {
  2366.     char ip[16];
  2367.     char* IP=(char*)V6any;
  2368.     char* x=getenv("IP");
  2369.     if (x && !x[scan_ip6(x,ip)])
  2370.       IP=ip;
  2371.     if (socket_bind6_reuse(sock,IP,389,0)) {
  2372.       buffer_putsflush(buffer_2,"bind failed!\n");
  2373.       exit(1);
  2374.     }
  2375.   }
  2376.   if (socket_listen(sock,32)) {
  2377.     buffer_putsflush(buffer_2,"listen failed!\n");
  2378.     exit(1);
  2379.   }
  2380.   for (;;) {
  2381.     char ip[16];
  2382.     uint16 port;
  2383.     uint32 scope_id;
  2384.     int asock;
  2385.     {
  2386.       int status;
  2387.       while ((status=waitpid(-1,0,WNOHANG))!=0 && status!=(pid_t)-1); /* reap zombies */
  2388.     }
  2389. #ifdef DEBUG
  2390. again:
  2391. #endif
  2392.     asock=socket_accept6(sock,ip,&port,&scope_id);
  2393.     if (asock==-1) {
  2394.       buffer_putsflush(buffer_2,"accept failed!\n");
  2395.       exit(1);
  2396.     }
  2397.     {
  2398.       int one=1;
  2399.       setsockopt(asock,IPPROTO_TCP,TCP_NODELAY,&one,sizeof(one));
  2400.     }
  2401.     update();
  2402. #ifdef DEBUG
  2403.     {
  2404.       struct pollfd p;
  2405.       p.fd=0;
  2406.       p.events=POLLIN;
  2407.       if (poll(&p,1,1)==1) return 0;
  2408.     }
  2409.     handle(asock,asock);
  2410.     goto again;
  2411. //    exit(0);
  2412. #else
  2413. #endif
  2414.     switch (fork()) {
  2415.     case -1: buffer_putsflush(buffer_2,"fork failed!\n"); exit(1);
  2416.     case 0: /* child */
  2417.       handle(asock,asock);
  2418.       exit(0); /* not reached */
  2419.     default:
  2420.       close(asock);
  2421.     }
  2422.   }
  2423. #else
  2424.   {
  2425.     int one=1;
  2426.     setsockopt(1,IPPROTO_TCP,TCP_NODELAY,&one,sizeof(one));
  2427.   }
  2428.   handle(0,1);
  2429. #endif
  2430.   return 0;
  2431. }
  2432.  
  2433. /* vim:tw=90:
  2434.  */