searchrequest scope handling (fixed by Thomas Walpuski)
add (primitive) auth support
This commit is contained in:
@@ -12,3 +12,8 @@ data
|
||||
dumpidx
|
||||
parse
|
||||
tinyldap_debug
|
||||
attic
|
||||
doit
|
||||
idx2ldif
|
||||
ldap-capture
|
||||
server
|
||||
|
||||
4
Makefile
4
Makefile
@@ -23,6 +23,8 @@ ldif.a: ldif_parse.o ldap_match.o ldap_match_mapped.o
|
||||
|
||||
storage.a: strstorage.o strduptab.o mstorage_add.o mduptab_add.o
|
||||
|
||||
auth.a: auth.o
|
||||
|
||||
DIET=/opt/diet/bin/diet -Os
|
||||
CC=gcc
|
||||
CFLAGS=-pipe -I. -Wall -W
|
||||
@@ -43,7 +45,7 @@ endif
|
||||
t1 parse: ldif.a storage.a
|
||||
t2: ldap.a asn1.a
|
||||
t3 t4 t5 addindex: storage.a
|
||||
tinyldap tinyldap_standalone tinyldap_debug: ldif.a storage.a
|
||||
tinyldap tinyldap_standalone tinyldap_debug: ldif.a storage.a auth.a
|
||||
bindrequest tinyldap tinyldap_standalone tinyldap_debug ldapclient ldapclient_str: ldap.a asn1.a
|
||||
|
||||
tinyldap_standalone: tinyldap.c
|
||||
|
||||
2
THANKS
2
THANKS
@@ -3,3 +3,5 @@ Trevor Harrison found a bug in fmt_asn1tag for the multibyte encoding.
|
||||
David Lichteblau found lots of problems in the ASN.1 code.
|
||||
|
||||
Özgür Kesim helped fix the substring search.
|
||||
|
||||
Thomas Walpuski has found lots of problems with the LDAP code.
|
||||
|
||||
12
addindex.c
12
addindex.c
@@ -56,7 +56,10 @@ int main(int argc,char* argv[]) {
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j;
|
||||
uint32_unpack(x,&j);
|
||||
if (!strcmp(map+j,argv[2])) {
|
||||
buffer_puts(buffer_1,map+j); buffer_putsflush(buffer_1,"\n");
|
||||
if (!strcasecmp(map+j,"dn")) dn=j;
|
||||
if (!strcasecmp(map+j,"objectClass")) objectClass=j;
|
||||
if (!strcasecmp(map+j,argv[2])) {
|
||||
buffer_putsflush(buffer_2,"found attribute!\n");
|
||||
wanted=j; casesensitive=x+attribute_count*4-map;
|
||||
uint32_unpack(map+casesensitive,&j);
|
||||
@@ -64,10 +67,7 @@ int main(int argc,char* argv[]) {
|
||||
buffer_putsflush(buffer_2,"case sensitivity flag is nonzero?!\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (!strcmp(map+j,"dn"))
|
||||
dn=j;
|
||||
else if (!strcmp(map+j,"objectClass"))
|
||||
objectClass=j;
|
||||
}
|
||||
x+=4;
|
||||
}
|
||||
if (!wanted) {
|
||||
@@ -90,10 +90,12 @@ int main(int argc,char* argv[]) {
|
||||
uint32_unpack(x+8,&k);
|
||||
mstorage_add(&idx,(char*)&k,4);
|
||||
++counted;
|
||||
x+=j*8;
|
||||
} else if (wanted==objectClass) {
|
||||
uint32_unpack(x+12,&k);
|
||||
mstorage_add(&idx,(char*)&k,4);
|
||||
++counted;
|
||||
x+=j*8;
|
||||
} else {
|
||||
x+=16;
|
||||
for (; j>2; --j) {
|
||||
|
||||
22
auth.c
Normal file
22
auth.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <md5.h>
|
||||
#include "ldap.h"
|
||||
#include "auth.h"
|
||||
#include "str.h"
|
||||
#include "textcode.h"
|
||||
#include "byte.h"
|
||||
|
||||
int check_password(const char* fromdb,struct string* plaintext) {
|
||||
if (str_start(fromdb,"{MD5}")) {
|
||||
char digest[17];
|
||||
char md5[40];
|
||||
MD5_CTX c;
|
||||
MD5Init(&c);
|
||||
MD5Update(&c,plaintext->s,plaintext->l);
|
||||
MD5Final(digest,&c);
|
||||
digest[16]=0;
|
||||
fmt_hexdump(md5,digest,16);
|
||||
if (byte_equal(md5,32,fromdb+5))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
7
auth.h
Normal file
7
auth.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
/* return non-zero if the password matches */
|
||||
int check_password(const char* fromdb,struct string* plaintext);
|
||||
|
||||
#endif
|
||||
@@ -50,6 +50,17 @@ int ldap_match_present(uint32 ofs,uint32 attrofs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs) {
|
||||
uint32 j,k;
|
||||
if (attrofs==dn_ofs) return uint32_read(map+ofs+8);
|
||||
if (attrofs==objectClass_ofs) return uint32_read(map+ofs+12);
|
||||
uint32_unpack(map+ofs,&j);
|
||||
for (k=2; k<j; ++k)
|
||||
if (uint32_read(map+ofs+k*8)==attrofs)
|
||||
return uint32_read(map+ofs+k*8+4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return non-zero if the record matches the search filter */
|
||||
int ldap_matchfilter_mapped(uint32 ofs,struct Filter* f) {
|
||||
struct Filter* y=f->x;
|
||||
@@ -165,7 +176,7 @@ int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr) {
|
||||
return 0;
|
||||
}
|
||||
/* we want "o=foo, o=bar" and "o=FOO,o=baR" to be equal */
|
||||
if (sr->baseObject.l && !(l=match(sr->baseObject.s,sr->baseObject.l,map+k))) {
|
||||
if (sr->baseObject.l && !match(sr->baseObject.s,sr->baseObject.l,map+k)) {
|
||||
// puts("fail: not suffix");
|
||||
return 0;
|
||||
}
|
||||
@@ -175,7 +186,7 @@ int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr) {
|
||||
case baseObject: if (l==sr->baseObject.l) break; return 0;
|
||||
default:
|
||||
i=str_chr(map+k,',');
|
||||
if (i+2>=sr->baseObject.l-l) break;
|
||||
if (i+2>=l-sr->baseObject.l) break;
|
||||
return 0;
|
||||
}
|
||||
return ldap_matchfilter_mapped(ofs,sr->filter);
|
||||
|
||||
1
ldif.h
1
ldif.h
@@ -25,3 +25,4 @@ int ldif_parse(const char* filename);
|
||||
int ldap_match(struct ldaprec* r,struct SearchRequest* sr);
|
||||
int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr);
|
||||
int ldap_match_present(uint32 ofs,uint32 attrofs);
|
||||
uint32 ldap_find_attr_value(uint32 ofs,uint32 attrofs);
|
||||
|
||||
75
tinyldap.c
75
tinyldap.c
@@ -1,5 +1,6 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "byte.h"
|
||||
#include "buffer.h"
|
||||
#include "ldap.h"
|
||||
@@ -7,13 +8,14 @@
|
||||
#include "open.h"
|
||||
#include "mmap.h"
|
||||
#include "uint32.h"
|
||||
#include "auth.h"
|
||||
#ifdef STANDALONE
|
||||
#include "socket.h"
|
||||
#include "ip6.h"
|
||||
#include <wait.h>
|
||||
#endif
|
||||
|
||||
#define verbose 0
|
||||
#define verbose 1
|
||||
#define debug 1
|
||||
|
||||
char* map;
|
||||
@@ -24,7 +26,7 @@ uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table;
|
||||
uint32 record_set_length;
|
||||
|
||||
/* some pre-looked-up attribute offsets to speed up ldap_match_mapped */
|
||||
uint32 dn_ofs,objectClass_ofs;
|
||||
uint32 dn_ofs,objectClass_ofs,userPassword_ofs;
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
@@ -215,8 +217,9 @@ static uint32 findrec(uint32 dat) {
|
||||
while ((top>=bottom)) {
|
||||
uint32 mid=(top+bottom)/2;
|
||||
uint32 l;
|
||||
|
||||
l=uint32_read(map+uint32_read(&records[mid])+8);
|
||||
if (l<dat) {
|
||||
if (l<=dat) {
|
||||
if (mid>=record_count-1)
|
||||
l=uint32_read(map+uint32_read(&records[0])+12);
|
||||
else
|
||||
@@ -548,6 +551,64 @@ int handle(int in,int out) {
|
||||
buffer_putulong(buffer_2,method);
|
||||
buffer_putsflush(buffer_2,".\n");
|
||||
}
|
||||
if (name.l) {
|
||||
struct Filter f;
|
||||
struct string password;
|
||||
f.type=EQUAL; f.attrofs=dn_ofs;
|
||||
scan_ldapstring(buf+res+tmp,buf+res+len,&password);
|
||||
f.ava.desc.l=2; f.ava.desc.s="dn";
|
||||
f.ava.value=name;
|
||||
f.next=0;
|
||||
|
||||
if (!indexable(&f)) {
|
||||
authfailure:
|
||||
{
|
||||
char outbuf[1024];
|
||||
int s=100;
|
||||
int len=fmt_ldapbindresponse(outbuf+s,48,"","authentication failure","");
|
||||
int hlen=fmt_ldapmessage(0,messageid,BindResponse,len);
|
||||
fmt_ldapmessage(outbuf+s-hlen,messageid,BindResponse,len);
|
||||
write(out,outbuf+s-hlen,len+hlen);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
unsigned long* result;
|
||||
unsigned long i,done;
|
||||
result=alloca(record_set_length*sizeof(unsigned long));
|
||||
useindex(&f,result);
|
||||
done=0;
|
||||
for (i=0; i<record_set_length; ++i)
|
||||
if (result[i])
|
||||
done=1;
|
||||
done=0;
|
||||
for (i=0; i<record_count; ) {
|
||||
if (!result[i/(8*sizeof(long))]) {
|
||||
i+=8*sizeof(long);
|
||||
continue;
|
||||
}
|
||||
for (; i<record_count; ++i) {
|
||||
if (isset(result,i)) {
|
||||
uint32 j;
|
||||
const char* c;
|
||||
uint32_unpack(map+indices_offset+4*i,&j);
|
||||
if (!(j=ldap_find_attr_value(j,userPassword_ofs)))
|
||||
goto authfailure;
|
||||
c=map+j;
|
||||
#if 0
|
||||
buffer_puts(buffer_2,"compare ");
|
||||
buffer_puts(buffer_2,c);
|
||||
buffer_puts(buffer_2," with ");
|
||||
buffer_put(buffer_2,f.ava.value.s,f.ava.value.l);
|
||||
buffer_putsflush(buffer_2,".\n");
|
||||
#endif
|
||||
if (check_password(c,&password))
|
||||
done=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!done) goto authfailure;
|
||||
}
|
||||
}
|
||||
{
|
||||
char outbuf[1024];
|
||||
int s=100;
|
||||
@@ -600,7 +661,6 @@ int handle(int in,int out) {
|
||||
#if (debug != 0)
|
||||
if (debug) buffer_putsflush(buffer_2,"query can be answered with index!\n");
|
||||
#endif
|
||||
record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
|
||||
result=alloca(record_set_length*sizeof(unsigned long));
|
||||
/* Use the index to find matching data. Put the offsets
|
||||
* of the matches in a table. Use findrec to locate
|
||||
@@ -719,19 +779,22 @@ int main() {
|
||||
uint32_unpack(map+2*4,&record_count);
|
||||
uint32_unpack(map+3*4,&indices_offset);
|
||||
uint32_unpack(map+4*4,&size_of_string_table);
|
||||
record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8);
|
||||
|
||||
/* look up "dn" and "objectClass" */
|
||||
{
|
||||
char* x=map+5*4+size_of_string_table;
|
||||
unsigned int i;
|
||||
dn_ofs=objectClass_ofs=0;
|
||||
dn_ofs=objectClass_ofs=userPassword_ofs=0;
|
||||
for (i=0; i<attribute_count; ++i) {
|
||||
uint32 j;
|
||||
j=uint32_read(x);
|
||||
if (!strcmp("dn",map+j))
|
||||
dn_ofs=j;
|
||||
else if (!strcmp("objectClass",map+j))
|
||||
else if (!strcasecmp("objectClass",map+j))
|
||||
objectClass_ofs=j;
|
||||
else if (!strcasecmp("userPassword",map+j))
|
||||
userPassword_ofs=j;
|
||||
x+=4;
|
||||
}
|
||||
if (!dn_ofs || !objectClass_ofs) {
|
||||
|
||||
Reference in New Issue
Block a user