1 #include <stdlib.h>
2 #include <byte.h>
3 #include "ldap.h"
4 
5 #if 0
6         ModifyRequest ::= [APPLICATION 6] SEQUENCE {
7                 object          LDAPDN,
8                 modification    SEQUENCE OF SEQUENCE {
9                         operation       ENUMERATED {
10                                                 add     (0),
11                                                 delete  (1),
12                                                 replace (2) },
13                         modification    AttributeTypeAndValues } }
14 
15         AttributeTypeAndValues ::= SEQUENCE {
16                 type    AttributeDescription,
17                 vals    SET OF AttributeValue }
18 #endif
19 
scan_ldapmodifyrequest(const char * src,const char * max,struct ModifyRequest * m)20 size_t scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m) {
21   size_t res,tmp,oslen; /* outer sequence length */
22   struct Modification* last=0;
23   byte_zero(m,sizeof(*m));
24   if (!(res=scan_ldapstring(src,max,&m->object))) goto error;
25   if (!(tmp=scan_asn1SEQUENCE(src+res,max,&oslen))) goto error;
26   res+=tmp;
27   if (src+res+oslen>max) goto error;
28   max=src+res+oslen;
29   if (src+res>=max) goto error;		/* need at least one record */
30   do {
31     size_t islen, etmp;
32     if (last) {
33       struct Modification* cur;
34       if (!(cur=malloc(sizeof(struct Modification)))) goto error;
35       byte_zero(cur,sizeof(*cur));
36       last->next=cur; last=cur;
37     } else
38       last=&m->m;
39     last->next=0;
40     if (!(tmp=scan_asn1SEQUENCE(src+res,max,&islen))) goto error;
41     res+=tmp;
42     if (!(tmp=scan_asn1ENUMERATED(src+res,max,&etmp))) goto error;
43     if (etmp>2) goto error;
44     last->operation=etmp; res+=tmp;
45     {
46       size_t iislen;	/* urgh, _three_ levels of indirection */
47       const char* imax;
48       if (!(tmp=scan_asn1SEQUENCE(src+res,max,&iislen))) goto error;
49       res+=tmp;
50       imax=src+res+iislen;
51       if (imax>max) goto error;
52       if (!(tmp=scan_ldapstring(src+res,imax,&last->AttributeDescription))) goto error;
53       res+=tmp;
54       {
55 	size_t iiislen;	/* waah, _four_ levels of indirection!  It doesn't get more inefficient than this */
56 	const char* iimax;
57 	struct AttributeDescriptionList** ilast=0;
58 	if (!(tmp=scan_asn1SET(src+res,max,&iiislen))) goto error;
59 	res+=tmp;
60 	iimax=src+res+iiislen;
61 	if (src+res+iiislen!=imax) goto error;
62 	ilast=&last->vals;
63 	while (src+res<iimax) {
64 	  if (!(*ilast=malloc(sizeof(struct AttributeDescriptionList)))) goto error;
65 	  byte_zero(*ilast,sizeof(**ilast));
66 	  if (!(tmp=scan_ldapstring(src+res,imax,&(*ilast)->a))) goto error;
67 	  ilast=&(*ilast)->next;
68 	  res+=tmp;
69 	}
70       }
71     }
72     break;
73   } while (src+res<max);
74   return res;
75 error:
76   free_ldapmodifyrequest(m);
77   return 0;
78 }
79 
free_mod(struct Modification * m)80 static void free_mod(struct Modification* m) {
81   while (m) {
82     struct Modification* tmp=m->next;
83     free(m);
84     m=tmp;
85   }
86 }
87 
free_ldapmodifyrequest(struct ModifyRequest * m)88 void free_ldapmodifyrequest(struct ModifyRequest* m) {
89   free_ldapadl(m->m.vals);
90   free_mod(m->m.next);
91 }
92