summaryrefslogtreecommitdiffstats
path: root/scan_ldapmodifyrequest.c
blob: 8a08388890e04a1e9d0a1a64b65e045913c2c618 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <stdlib.h>
#include "ldap.h"

#if 0
        ModifyRequest ::= [APPLICATION 6] SEQUENCE {
                object          LDAPDN,
                modification    SEQUENCE OF SEQUENCE {
                        operation       ENUMERATED {
                                                add     (0),
                                                delete  (1),
                                                replace (2) },
                        modification    AttributeTypeAndValues } }

        AttributeTypeAndValues ::= SEQUENCE {
                type    AttributeDescription,
                vals    SET OF AttributeValue }
#endif

size_t scan_ldapmodifyrequest(const char* src,const char* max,struct ModifyRequest* m) {
  size_t res,tmp,oslen; /* outer sequence length */
  struct Modification* last=0;
  m->m.next=0;
  if (!(res=scan_ldapstring(src,max,&m->object))) goto error;
  if (!(tmp=scan_asn1SEQUENCE(src+res,max,&oslen))) goto error;
  res+=tmp;
  if (src+res+oslen>max) goto error;
  max=src+res+oslen;
  if (src+res>=max) goto error;		/* need at least one record */
  do {
    size_t islen;
    unsigned long etmp;
    if (last) {
      struct Modification* cur;
      if (!(cur=malloc(sizeof(struct Modification)))) goto error;
      last->next=cur; last=cur;
    } else
      last=&m->m;
    last->next=0;
    if (!(tmp=scan_asn1SEQUENCE(src+res,max,&islen))) goto error;
    res+=tmp;
    if (!(tmp=scan_asn1ENUMERATED(src+res,max,&etmp))) goto error;
    if (etmp>2) goto error; last->operation=etmp; res+=tmp;
    {
      size_t iislen;	/* urgh, _three_ levels of indirection */
      const char* imax;
      if (!(tmp=scan_asn1SEQUENCE(src+res,max,&iislen))) goto error;
      res+=tmp;
      imax=src+res+iislen;
      if (imax>max) goto error;
      if (!(tmp=scan_ldapstring(src+res,imax,&last->AttributeDescription))) goto error;
      res+=tmp;
      {
	size_t iiislen;	/* waah, _four_ levels of indirection!  It doesn't get more inefficient than this */
	const char* iimax;
	struct AttributeDescriptionList** ilast=0;
	if (!(tmp=scan_asn1SET(src+res,max,&iiislen))) goto error;
	res+=tmp;
	iimax=src+res+iiislen;
	if (src+res+iiislen!=imax) goto error;
	ilast=&last->vals;
	while (src+res<iimax) {
	  if (!(*ilast=malloc(sizeof(struct AttributeDescriptionList)))) goto error;
	  if (!(tmp=scan_ldapstring(src+res,imax,&(*ilast)->a))) goto error;
	  (*ilast)->next=0;
	  ilast=&(*ilast)->next;
	  res+=tmp;
	}
      }
    }
    break;
  } while (src+res<max);
  return res;
error:
  free_ldapmodifyrequest(m);
  return 0;
}

static void free_mod(struct Modification* m) {
  while (m) {
    struct Modification* tmp=m->next;
    free(m);
    m=tmp;
  }
}

void free_ldapmodifyrequest(struct ModifyRequest* m) {
  free_ldapadl(m->m.vals);
  free_mod(m->m.next);
}