integrate LDIF parsing and write a matching routine.
Make tinyldap call the matching routine.
This commit is contained in:
4
Makefile
4
Makefile
@@ -14,7 +14,7 @@ scan_ldapstring.o scan_ldapsearchfilter.o scan_ldapsearchrequest.o \
|
||||
freefilter.o freeava.o scan_ldapava.o fmt_ldapsearchresultentry.o \
|
||||
fmt_ldapstring.o freepal.o scan_ldapsearchresultentry.o \
|
||||
|
||||
ldif.a: ldif_parse.o
|
||||
ldif.a: ldif_parse.o ldap_match.o strduptab.o strstorage.o
|
||||
|
||||
DIET=diet -Os
|
||||
CC=gcc
|
||||
@@ -33,7 +33,7 @@ endif
|
||||
%: %.c
|
||||
$(DIET) $(CC) $(CFLAGS) -o $@ $^ -lowfat
|
||||
|
||||
t1: strduptab.o strstorage.o
|
||||
t1:
|
||||
t2: ldap.a asn1.a
|
||||
bindrequest tinyldap ldapclient: ldap.a asn1.a
|
||||
|
||||
|
||||
13
README
13
README
@@ -1,14 +1,17 @@
|
||||
Please read ldap.h and asn1.h for an overview of the API.
|
||||
|
||||
Example code using the high level API is in tinyldap and ldapclient.
|
||||
This will be encapsulated some more eventually. The next steps are:
|
||||
This will be encapsulated some more eventually.
|
||||
|
||||
Tinyldap now not only parses incoming search requests, it also performs
|
||||
a search on the data structure we parsed from the flat LDIF file! When
|
||||
I plug in fmt_ldapsearchresultentry and fmt_ldapsearchresultdone, we
|
||||
have a minimal LDAP server!
|
||||
|
||||
The next steps are:
|
||||
|
||||
- integrate the LDIF parser from t1.c
|
||||
- write fmt_ldapsearchresponse
|
||||
- write fmt_ldapsearchrequest and scan_ldapsearchresponse
|
||||
|
||||
Then we will have a minimal LDAP server!
|
||||
|
||||
ldapclient is the client test application. It connects to localhost,
|
||||
makes a BindRequest and dumps the BindResponse in human readable form.
|
||||
|
||||
|
||||
92
ldap_match.c
Normal file
92
ldap_match.c
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "ldap.h"
|
||||
#include "ldif.h"
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* behave like strcmp */
|
||||
static int matchstring(struct string* s,const char* c) {
|
||||
int l,l1,i;
|
||||
if (!c) return -1;
|
||||
l1=l=strlen(c);
|
||||
if (s->l<l1) l1=s->l;
|
||||
i=byte_diff(s->s,l1,c);
|
||||
if (i) return i;
|
||||
/* one is a prefix of the other */
|
||||
if (l==s->l) return 0;
|
||||
if (c[l1]) /* is c the longer string? */
|
||||
return c[l1];
|
||||
return -(int)(s->s[l1]);
|
||||
}
|
||||
|
||||
/* look up value of an attribute for an LDIF record.
|
||||
* Return NULL if not found */
|
||||
static const char* findattr(struct ldaprec* f,struct string* name) {
|
||||
int i;
|
||||
if (!matchstring(name,"dn")) return f->dn;
|
||||
if (!matchstring(name,"mail")) return f->mail;
|
||||
if (!matchstring(name,"sn")) return f->sn;
|
||||
if (!matchstring(name,"cn")) return f->cn;
|
||||
for (i=0; i<ATTRIBS; ++i)
|
||||
if (!matchstring(name,f->a[i].name))
|
||||
return f->a[i].value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return non-zero if the record matches the search filter */
|
||||
int ldap_matchfilter(struct ldaprec* s,struct Filter* f) {
|
||||
struct Filter* y=f->x;
|
||||
if (!f) return 1;
|
||||
switch (f->type) {
|
||||
case AND:
|
||||
while (y) {
|
||||
if (!ldap_matchfilter(s,y)) return 0;
|
||||
y=y->next;
|
||||
}
|
||||
return 1;
|
||||
case OR:
|
||||
while (y) {
|
||||
if (ldap_matchfilter(s,y)) return 1;
|
||||
y=y->next;
|
||||
}
|
||||
return 0;
|
||||
case NOT:
|
||||
return !ldap_matchfilter(s,f->x);
|
||||
case EQUAL:
|
||||
// printf(" -> \"%s\" vs. \"%.*s\"\n",findattr(s,&f->ava.desc),f->ava.value.l,f->ava.value.s);
|
||||
if (matchstring(&f->ava.value,findattr(s,&f->ava.desc))) return 0;
|
||||
// puts("yes!!!");
|
||||
break;
|
||||
default:
|
||||
write(2,"foo\n",4);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return non-zero if the record matches the search request */
|
||||
int ldap_match(struct ldaprec* r,struct SearchRequest* sr) {
|
||||
int l=strlen(r->dn);
|
||||
int i;
|
||||
// printf("comparing \"%s\" and \"%.*s\"\n",r->dn,(int)sr->baseObject.l,sr->baseObject.s);
|
||||
/* first see if baseObject is a suffix of dn */
|
||||
if (sr->baseObject.l>l) {
|
||||
// puts("fail: baseObject longer than dn");
|
||||
return 0;
|
||||
}
|
||||
if (!byte_equal(sr->baseObject.s,sr->baseObject.l,r->dn+l-sr->baseObject.l)) {
|
||||
// puts("fail: not suffix");
|
||||
return 0;
|
||||
}
|
||||
/* it is. If scope==wholeSubtree, the scope check is also done */
|
||||
switch (sr->scope) {
|
||||
case wholeSubtree: break;
|
||||
case baseObject: if (l==sr->baseObject.l) break; return 0;
|
||||
default:
|
||||
i=str_chr(r->dn,',');
|
||||
if (i+2>=sr->baseObject.l-l) break;
|
||||
return 0;
|
||||
}
|
||||
return ldap_matchfilter(r,sr->filter);
|
||||
}
|
||||
2
ldif.h
2
ldif.h
@@ -17,7 +17,7 @@ struct ldaprec {
|
||||
extern const char* dn,* mail,* sn,* cn,* objectClass;
|
||||
extern struct ldaprec *first;
|
||||
|
||||
int parse_ldif(const char* filename);
|
||||
int ldif_parse(const char* filename);
|
||||
|
||||
/* return non-zero if the record matches the search request */
|
||||
int ldap_match(struct ldaprec* r,struct SearchRequest* sr);
|
||||
|
||||
37
tinyldap.c
37
tinyldap.c
@@ -9,12 +9,14 @@
|
||||
int main() {
|
||||
char buf[BUFSIZE];
|
||||
int len=0;
|
||||
ldif_parse("exp.ldif");
|
||||
for (;;) {
|
||||
int tmp=read(0,buf+len,BUFSIZE-len);
|
||||
int res;
|
||||
long messageid,op,Len;
|
||||
if (tmp==0) { write(2,"eof!\n",5); return 0; }
|
||||
if (tmp<1) { write(2,"error!\n",7); return 1; }
|
||||
if (tmp==0)
|
||||
if (!len) { write(2,"eof!\n",5); return 0; }
|
||||
if (tmp<0) { write(2,"error!\n",7); return 1; }
|
||||
len+=tmp;
|
||||
res=scan_ldapmessage(buf,buf+len,&messageid,&op,&Len);
|
||||
if (res>0) {
|
||||
@@ -30,8 +32,9 @@ int main() {
|
||||
{
|
||||
long version,method;
|
||||
struct string name;
|
||||
res=scan_ldapbindrequest(buf+res,buf+res+len,&version,&name,&method);
|
||||
if (res>=0) {
|
||||
int tmp;
|
||||
tmp=scan_ldapbindrequest(buf+res,buf+res+len,&version,&name,&method);
|
||||
if (tmp>=0) {
|
||||
buffer_puts(buffer_2,"bind request: version ");
|
||||
buffer_putulong(buffer_2,version);
|
||||
buffer_puts(buffer_2," for name \"");
|
||||
@@ -49,11 +52,33 @@ int main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SearchRequest:
|
||||
{
|
||||
struct SearchRequest br;
|
||||
int tmp;
|
||||
if ((tmp=scan_ldapsearchrequest(buf+res,buf+res+len,&br))) {
|
||||
struct ldaprec* r=first;
|
||||
while (r) {
|
||||
if (ldap_match(r,&br)) {
|
||||
buffer_puts(buffer_2,"found: ");
|
||||
buffer_puts(buffer_2,r->dn);
|
||||
buffer_putsflush(buffer_2,"\n");
|
||||
}
|
||||
r=r->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
Len+=res;
|
||||
if (Len<len) {
|
||||
byte_copyr(buf,len-Len,buf+len);
|
||||
byte_copy(buf,len-Len,buf+Len);
|
||||
len-=Len;
|
||||
}
|
||||
}
|
||||
} else
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user