sprinkle some attributes

This commit is contained in:
leitner
2024-11-26 16:23:20 +00:00
parent 79c86ae7eb
commit a4a0d74dda
11 changed files with 60 additions and 15 deletions

33
asn1.h
View File

@@ -6,6 +6,8 @@
#include <stddef.h>
#include <libowfat/compiler.h>
enum asn1_tagclass {
UNIVERSAL=(0<<6),
APPLICATION=(1<<6),
@@ -34,34 +36,41 @@ enum asn1_tag {
};
/* write variable length integer in the encoding used in tag and oid */
att_write(1)
size_t fmt_asn1tagint(char* dest,unsigned long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 tag */
att_write(1)
size_t fmt_asn1tag(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
unsigned long tag);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 length */
att_write(1)
size_t fmt_asn1length(char* dest,size_t l);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER. This only does the payload, not the tag
* and length headers! */
att_write(1)
size_t fmt_asn1intpayload(char* dest,unsigned long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER. This only does the payload, not the tag
* and length headers! */
att_write(1)
size_t fmt_asn1sintpayload(char* dest,signed long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER or ENUMERATED. */
att_write(1)
size_t fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,unsigned long val);
/* write int in least amount of bytes, return number of bytes */
/* as used in ASN.1 INTEGER or ENUMERATED. */
att_write(1)
size_t fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,signed long val);
@@ -71,16 +80,19 @@ size_t fmt_asn1sint(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
/* does not wrote the payload itself, just the header! First construct
* the sequence/octet string so you know the length, then use
* fmt_asn1transparent to write the header before it */
att_write(1)
size_t fmt_asn1transparent(char* dest,enum asn1_tagclass tc,
enum asn1_tagtype tt,enum asn1_tag tag,size_t len);
/* write string in least amount of bytes, return number of bytes */
/* as used in ASN.1 OCTET STRING. */
att_write(1)
size_t fmt_asn1string(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,const char* c,size_t l);
/* same but for bitstrings.
* l in this case means the number of BITS in c, not bytes */
att_write(1)
size_t fmt_asn1bitstring(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
enum asn1_tag tag,const char* c,size_t l);
@@ -102,6 +114,7 @@ size_t fmt_asn1bitstring(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,
/* write ASN.1 SET */
#define fmt_asn1SET(dest,l) fmt_asn1transparent(dest,UNIVERSAL,CONSTRUCTED,SET_OF,l)
att_write(1) __bufin(5,6)
size_t fmt_asn1OID(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,const size_t* array,size_t len);
@@ -111,61 +124,78 @@ size_t fmt_asn1OID(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum as
* the return value is the number of bytes parsed or 0 for parse error */
/* parse ASN.1 variable length integer as used in tag and oid */
att_read(1) att_write(3)
size_t scan_asn1tagint(const char* src,const char* max,unsigned long* val);
/* parse ASN.1 tag into a tag class, tag type and tag number */
att_read(1) att_write(3) att_write(4) att_write(5)
size_t scan_asn1tag(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag);
/* parse ASN.1 length */
/* only return success if source buffer is large enough to hold length bytes */
att_read(1) att_write(3)
size_t scan_asn1length(const char* src,const char* max,size_t* length);
/* Same but does not check the source buffer is large enough to hold
* length bytes. Useful to find out how many more bytes we need to read
* from network */
att_read(1) att_write(3)
size_t scan_asn1length_nolengthcheck(const char* src,const char* max, size_t* length);
/* helper for scan_asn1INT, scan_asn1ENUMERATED and scan_asn1BOOLEAN */
att_read(1) att_write(3) att_write(4) att_write(5) att_write(6)
size_t scan_asn1int(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt, unsigned long* tag,
long* val);
/* parse raw integer (payload after tag and length); internal helper */
/* internal helper; parse raw integer (payload after tag and length) */
att_read(1) att_write(4)
size_t scan_asn1rawint(const char* src,const char* max,size_t len,long* val);
/* parse string with tag and length.
* Points s to the first byte in the string, and writes the length of
* the string to l. */
att_read(1) att_write(3) att_write(4) att_write(5) att_write(6) att_write(7)
size_t scan_asn1string(const char* src,const char* max,
enum asn1_tagclass* tc,enum asn1_tagtype* tt,unsigned long* tag,
const char** s,size_t* l);
/* the following expect a specific universal type and return a parse
* error if the tag does not match that type */
att_read(1) att_write(3)
size_t scan_asn1BOOLEAN(const char* src,const char* max,int* l);
att_read(1) att_write(3)
size_t scan_asn1INTEGER(const char* src,const char* max,signed long* l);
att_read(1) att_write(3)
size_t scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* l);
att_read(1) att_write(3) att_write(4)
size_t scan_asn1STRING(const char* src,const char* max,const char** s,size_t* l);
att_read(1) att_write(3) att_write(4)
size_t scan_asn1BITSTRING(const char* src,const char* max,const char** s,size_t* l);
/* note: these only parse the header. src + return value points to first element */
att_read(1) att_write(3)
size_t scan_asn1SEQUENCE(const char* src,const char* max,size_t* len);
/* scan_asn1SEQUENCE will only return success if the header and the
* whole contents fit into src..max; this function will only parse the
* outer sequence header and return the number of bytes it say it wants.
* For finding out how much more data you need to read from the socket. */
att_read(1) att_write(3)
size_t scan_asn1SEQUENCE_nolengthcheck(const char* src,const char* max,size_t* len);
att_read(1) att_write(3)
size_t scan_asn1SET(const char* src,const char* max,size_t* len);
/* scan an ASN.1 OID and put the numbers into array.
* Return numbers of bytes parsed or 0 on error.
* Put at most arraylen longs into array; if the OID is longer, or if array is NULL, return real number in arraylen and return 0
* If 0 is returned and arraylen is also 0, there was a parse error */
att_read(1) att_write(3) att_mangle(4)
size_t scan_asn1oid(const char* src,const char* max,size_t* array,size_t* arraylen);
/* internal helper, assumes you already read tag and length and max=src+length */
/* call with *arraylen = sizeof(array)/sizeof(array[0]) */
/* returns needed array size in *arraylen */
/* rule of thumb: (number of bytes in input + 1) needed */
att_read(1) att_write(3) att_mangle(4)
size_t scan_asn1rawoid(const char* src,const char* max,size_t* array,size_t* arraylen);
struct string {
@@ -217,6 +247,7 @@ extern const struct oidlookup {
enum x509_oid id;
} oid2string[];
__strin(1) att_pure
size_t lookupoid(const char* oid,size_t l);
/* Generic parser and formatter routines: */

6
bstr.h
View File

@@ -1,4 +1,5 @@
#include <stddef.h>
#include <libowfat/compiler.h>
/* The LDAP read-only data store is mmapped and trusted, because it
* takes higher privileges than tinyldap has to modify it.
@@ -12,13 +13,18 @@
* This means we need small wrappers around strlen and strcmp.
* These are those small wrappers. */
__strin(1) __strin(2) att_pure
int bstr_diff(const char* a,const char* b);
#define bstr_equal(s,t) (!bstr_diff((s),(t)))
__strin(1) __strnin(2,3) att_pure
int bstr_diff2(const char* a,const char* b,size_t blen);
#define bstr_equal2(s,t,l) (!bstr_diff2((s),(t),(l)))
__strin(1) att_pure
size_t bstrlen(const char* a);
__strin(1) att_pure
size_t bstrstart(const char* a); /* offset of first byte of bstring */
__strin(1) att_pure
const char* bstrfirst(const char* a); /* pointer to first byte of bstring */

18
ldap.h
View File

@@ -4,16 +4,22 @@
#include <stddef.h>
#include <inttypes.h>
#include "asn1.h"
// asn1.h includes libowfat/compiler.h, so don't include it again here
/* return zero if same, otherwise nonzero */
int matchstring(struct string* s,const char* c);
int matchcasestring(struct string* s,const char* c);
int matchprefix(struct string* s,const char* c);
int matchcaseprefix(struct string* s,const char* c);
att_read(1) __strin(2)
int matchstring(const struct string* s,const char* c);
att_read(1) __strin(2)
int matchcasestring(const struct string* s,const char* c);
att_read(1) __strin(2)
int matchprefix(const struct string* s,const char* c);
att_read(1) __strin(2)
int matchcaseprefix(const struct string* s,const char* c);
/* "ou=fnord; O=fefe; c=de" -> "ou=fnord,o=fefe,c=de" */
/* returns the length of the new string */
size_t normalize_dn(char* dest,const char* src,int len);
att_write(1) __strnin(2,3)
size_t normalize_dn(char* dest,const char* src,size_t len);
struct AttributeValueAssertion {
struct string desc, value;
@@ -55,7 +61,7 @@ struct Filter {
struct SearchRequest {
struct string baseObject;
enum { baseObject=0, singleLevel=1, wholeSubtree=2 } scope;
enum { baseObjectOnly=0, singleLevel=1, wholeSubtree=2 } scope;
enum {
neverDerefAliases=0,
derefInSearching=1,

View File

@@ -190,7 +190,7 @@ int ldap_match_mapped(uint32 ofs,struct SearchRequest* sr) {
/* 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;
case baseObjectOnly: if (l==sr->baseObject.l) break; return 0;
default:
i=str_chr(map+k,',');
if (i+2>=l-sr->baseObject.l) break;

View File

@@ -154,7 +154,7 @@ int ldap_match_sre(struct SearchResultEntry* sre,struct SearchRequest* sr) {
return 0;
switch (sr->scope) {
case wholeSubtree: break;
case baseObject: if (sre->objectName.l==sr->baseObject.l) break; return 0;
case baseObjectOnly: if (sre->objectName.l==sr->baseObject.l) break; return 0;
default:
for (i=0; i<sre->objectName.l; ++i)
if (sre->objectName.s[i]==',')

View File

@@ -267,7 +267,9 @@ lookagain:
#endif
}
}
if (!m) if (!(m=malloc(sizeof(struct ldaprec)))) return 2;
if (!m)
if (!(m=malloc(sizeof(struct ldaprec))))
return 2;
(*l)->next=m;
m->n=0; m->dn=-1; m->next=0;

View File

@@ -4,7 +4,7 @@
#include <libowfat/str.h>
/* behave like strcmp, but also return 0 if s is a prefix of c. */
int matchcaseprefix(struct string* s,const char* c) {
int matchcaseprefix(const struct string* s,const char* c) {
unsigned int l,l1,i;
if (!c) return -1;
l1=l=str_len(c);

View File

@@ -3,7 +3,7 @@
#include "ldif.h"
/* like matchstring, but case insensitively */
int matchcasestring(struct string* s,const char* c) {
int matchcasestring(const struct string* s,const char* c) {
unsigned int l,l1,i;
if (!c) return -1;
l1=l=bstrlen(c);

View File

@@ -3,7 +3,7 @@
#include "bstr.h"
/* behave like strcmp, but also return 0 if s is a prefix of c. */
int matchprefix(struct string* s,const char* c) {
int matchprefix(const struct string* s,const char* c) {
unsigned int l,l1,i;
if (!c) return -1;
l1=l=bstrlen(c);

View File

@@ -3,7 +3,7 @@
#include "ldif.h"
/* behave like strcmp */
int matchstring(struct string* s,const char* c) {
int matchstring(const struct string* s,const char* c) {
unsigned int l,l1,i;
if (!c) return -1;
l1=l=bstrlen(c);

View File

@@ -3,7 +3,7 @@
/* "ou=fnord; O=fefe; c=de" -> "ou=fnord,o=fefe,c=de" */
/* returns the length of the new string */
size_t normalize_dn(char* dest,const char* src,int len) {
size_t normalize_dn(char* dest,const char* src,size_t len) {
int makelower=1;
char* orig=dest;
while (len) {