From a4a0d74dda026ae04d62ee8c8e338402b19cade3 Mon Sep 17 00:00:00 2001 From: leitner Date: Tue, 26 Nov 2024 16:23:20 +0000 Subject: [PATCH] sprinkle some attributes --- asn1.h | 33 ++++++++++++++++++++++++++++++++- bstr.h | 6 ++++++ ldap.h | 18 ++++++++++++------ ldap_match_mapped.c | 2 +- ldap_match_sre.c | 2 +- ldif_parse.c | 4 +++- matchcaseprefix.c | 2 +- matchcasestring.c | 2 +- matchprefix.c | 2 +- matchstring.c | 2 +- normalize_dn.c | 2 +- 11 files changed, 60 insertions(+), 15 deletions(-) diff --git a/asn1.h b/asn1.h index a2da766..447a307 100644 --- a/asn1.h +++ b/asn1.h @@ -6,6 +6,8 @@ #include +#include + 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: */ diff --git a/bstr.h b/bstr.h index 8b4bf6d..686dff0 100644 --- a/bstr.h +++ b/bstr.h @@ -1,4 +1,5 @@ #include +#include /* 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 */ diff --git a/ldap.h b/ldap.h index 11b978a..d53bddf 100644 --- a/ldap.h +++ b/ldap.h @@ -4,16 +4,22 @@ #include #include #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, diff --git a/ldap_match_mapped.c b/ldap_match_mapped.c index a8929b2..492f0ea 100644 --- a/ldap_match_mapped.c +++ b/ldap_match_mapped.c @@ -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; diff --git a/ldap_match_sre.c b/ldap_match_sre.c index 283b63b..478701a 100644 --- a/ldap_match_sre.c +++ b/ldap_match_sre.c @@ -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; iobjectName.l; ++i) if (sre->objectName.s[i]==',') diff --git a/ldif_parse.c b/ldif_parse.c index c5c24aa..650278f 100644 --- a/ldif_parse.c +++ b/ldif_parse.c @@ -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; diff --git a/matchcaseprefix.c b/matchcaseprefix.c index 861d0d3..88d20a9 100644 --- a/matchcaseprefix.c +++ b/matchcaseprefix.c @@ -4,7 +4,7 @@ #include /* 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); diff --git a/matchcasestring.c b/matchcasestring.c index f3a33bc..b593896 100644 --- a/matchcasestring.c +++ b/matchcasestring.c @@ -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); diff --git a/matchprefix.c b/matchprefix.c index 659191f..fbc3361 100644 --- a/matchprefix.c +++ b/matchprefix.c @@ -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); diff --git a/matchstring.c b/matchstring.c index 693c2ac..21f8242 100644 --- a/matchstring.c +++ b/matchstring.c @@ -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); diff --git a/normalize_dn.c b/normalize_dn.c index 0cdf47e..cbc3845 100644 --- a/normalize_dn.c +++ b/normalize_dn.c @@ -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) {