ARPA2 Common Libraries  2.2.25
identity.h
1 
37 #ifndef ARPA2_IDENTITY_H
38 #define ARPA2_IDENTITY_H
39 
40 
41 #include <stdbool.h>
42 #include <stdint.h>
43 
44 #include <time.h>
45 
46 
47 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
51 
56 void a2id_init (void);
57 
58 
63 void a2id_fini (void);
64 
65 
66 /* Maximum identity length is:
67  * - local-part in 64 bytes
68  * - one byte AT symbol
69  * - domain in 255 Punycode chars
70  * - one Punycode char yields up to 4 bytes
71  * Buffers add one for a trailing NUL.
72  */
73 #define A2ID_MAXLEN ( 64 + 1 + 4*255 )
74 #define A2ID_BUFSIZE ( 64 + 1 + 4*255 + 1 )
75 //
76 #define A2SEL_MAXLEN ( 64 + 1 + 4*255 )
77 #define A2SEL_BUFSIZE ( 64 + 1 + 4*255 + 1 )
78 
79 
128 typedef enum {
129  /* Option #0 is a local-part "+svccmd+svcargs[+FLGEXPSIG+]" */
130  A2ID_OFS_PLUS_SERVICE, /* "[+svccmd+svcargs][+FLGEXPSIG+]@domain" */
131  A2ID_OFS_SERVICE, /* "[svccmd+svcargs][+FLGEXPSIG+]@domain" */
132  A2ID_OFS_PLUS_SVCARGS, /* "[+svcargs][+FLGEXPSIG+]@domain" */
133  A2ID_OFS_SVCARGS, /* "[svcargs][+FLGEXPSIG+]@domain" */
134  /* Option #1 is a local-part "userid+aliases[+FLGEXPSIG+]" */
135  A2ID_OFS_USERID, /* "[userid+aliases][+FLGEXPSIG+]@domain" */
136  A2ID_OFS_PLUS_ALIASES, /* "[+aliases][+FLGEXPSIG+]@domain" */
137  A2ID_OFS_ALIASES, /* "[aliases][+FLGEXPSIG+]@domain" */
138  /* Selectors may have an open ended '+' */
139  A2ID_OFS_OPEN_END, /* "+[+FLGEXPSIG+]" */
140  /* Both the local-part grammars fallback to "[+FLGEXPSIG+]" */
141  A2ID_OFS_PLUS_SIG, /* "[+FLGEXPSIG+]@domain" */
142  A2ID_OFS_SIGFLAGS, /* "[FLGEXPSIG+]@domain" */
143  A2ID_OFS_SIGEXPIRE, /* "[EXPSIG+]@domain" */
144  A2ID_OFS_SIGVALUE, /* "[SIG+]@domain" */
145  A2ID_OFS_SIGPLUS, /* "[+]@domain" */
146  A2ID_OFS_AT_DOMAIN, /* "@domain" */
147  /* Selectors can place a dot before the domain */
148  A2ID_OFS_DOT_DOMAIN, /* "[.]domain" */
149  A2ID_OFS_DOMAIN, /* "domain" */
150  A2ID_OFS_END, /* "" */
151  A2ID_OFS_BUFSIZE, /* Buffersize used, with a terminating NUL */
152  //
153  A2ID_OFS_COUNT
154 } a2id_offset_t;
155 
156 
165 typedef struct {
166  uint32_t sigflags, expireday;
167  uint16_t ofs [A2ID_OFS_COUNT];
168  char txt [A2SEL_BUFSIZE];
169  time_t expiration;
170 } a2sel_t;
171 
172 
182 typedef a2sel_t a2id_t;
183 
184 
207 typedef a2id_t a2act_t;
208 
209 
232 bool a2id_parse (a2id_t *out, const char *in, unsigned inlen);
233 
234 
258 bool a2id_parse_remote (a2id_t *out, const char *in, unsigned inlen);
259 
260 
288 bool a2sel_parse (a2sel_t *out, const char *in, unsigned inlen);
289 
290 
328 bool a2act_parse (a2act_t *out, const char *in, unsigned inlen, unsigned nact);
329 
330 
336 static inline bool a2act_isempty (const a2act_t *tested) {
337  return (* tested->txt == '\0');
338 }
339 
340 
346 static inline bool a2act_isstatic (const a2act_t *tested) {
347  return (tested->ofs [A2ID_OFS_ALIASES ] < tested->ofs [A2ID_OFS_PLUS_SIG]) &&
348  (tested->ofs [A2ID_OFS_PLUS_SIG] == tested->ofs [A2ID_OFS_AT_DOMAIN]);
349 }
350 
351 
357 static inline bool a2act_isdynamic (const a2act_t *tested) {
358  return (tested->ofs [A2ID_OFS_PLUS_ALIASES] == tested->ofs [A2ID_OFS_PLUS_SIG]) &&
359  (tested->ofs [A2ID_OFS_SIGPLUS ] < tested->ofs [A2ID_OFS_AT_DOMAIN]);
360 }
361 
362 
369 static inline bool a2act_isdynamicrecipe (const a2act_t *tested) {
370  return a2act_isdynamic (tested) &&
371  (tested->ofs [A2ID_OFS_SIGVALUE] == tested->ofs [A2ID_OFS_SIGPLUS]);
372 }
373 
374 
383 #define a2id_equal(a,b) (0 == strcmp ((a)->txt, (b)->txt))
384 
385 
394 #define a2sel_equal(a,b) (0 == strcmp ((a)->txt, (b)->txt))
395 
396 
408 // bool a2id_match (a2id_t *id, a2sel_t *sel);
409 //
410 #define a2id_match(id,sel) (a2sel_subseteq ((id),(sel)))
411 //
412 #define a2id_member(id,sel) (a2id_match ((id),(sel)))
413 
414 
434 bool a2sel_special (const a2sel_t *special, const a2sel_t *general);
435 //
436 #define a2sel_subseteq(s,g) a2sel_special ((s), (g))
437 
438 
439 
452 bool a2sel_textshift (a2id_t *shifty, a2id_offset_t ofsidx,
453  uint16_t newofs, bool before);
454 
455 
456 
509 bool a2sel_iterate_init (const a2sel_t *start, a2sel_t *cursor);
510 
513 bool a2sel_iterate_next (const a2sel_t *start, a2sel_t *cursor);
514 
517 #define a2id_iterate_init(in,cursor) a2sel_iterate_init ((const a2sel_t *) (start), (cursor))
518 
521 #define a2id_iterate_next(in,cursor) a2sel_iterate_next ((const a2sel_t *) (start), (cursor))
522 
523 
526 typedef struct {
527  const a2sel_t *src;
528  const char *uid;
529  int uidlen;
530  const char *dom;
532 
558 
562 
563 
587 bool a2sel_abstractions (const a2sel_t *specific, const a2sel_t *generic, uint16_t *steps);
588 //
589 #define a2sel_abstractions_domain(steps) ((steps) >> 7)
590 #define a2sel_abstractions_username(steps) ((steps) & 0x007f)
591 
592 
593 
631 bool a2id_addkey (int keyfd);
632 
633 
640 void a2id_dropkeys (void);
641 
642 
654 typedef enum {
655  //
656  // char #0, bits 0..3, index values 0..3
657  A2ID_SIGDATA_EXPIRATION, /* Include expiration timer (EXP), in days since key creation */
658  A2ID_SIGDATA_REMOTE_DOMAIN, /* UTF-8 String, from _DOT_DOMAIN to _END */
659  A2ID_SIGDATA_REMOTE_USERID, /* UTF-8 String, up to _AT_DOMAIN, may be case-sensitive!!! */
660  A2ID_SIGDATA_LOCAL_ALIASES, /* UTF-8 String from _PLUS_ALIASES to _PLUS_SIG
661  or, if that is empty, _PLUS_SVCARGS to _PLUS_SIG */
662  //
663  // char #1, bits 0..3, index values 4..7
664  A2ID_SIGDATA_SESSIONID, /* Machine-generated, protocol-specific session identity */
665  A2ID_SIGDATA_SUBJECT, /* Human-entered, protocol-specific, aim for a canonical form */
666  A2ID_SIGDATA_TOPIC, /* Automation-friendly, protocol-specific, like [TOPIC] in subject */
667  A2ID_SIGDATA_CRYPTLOCAL, /* Encrypted string from A2ID_OFS_USERID to A2ID_OFS_PLUS_SIG */
668  //
669  // No futher assigments yet
670  A2ID_SIGDATA_COUNT
672 //
673 #define A2ID_SIGFLAG_EXPIRATION ( 1 << A2ID_SIGDATA_EXPIRATION )
674 #define A2ID_SIGFLAG_REMOTE_DOMAIN ( 1 << A2ID_SIGDATA_REMOTE_DOMAIN )
675 #define A2ID_SIGFLAG_REMOTE_USERID ( 1 << A2ID_SIGDATA_REMOTE_USERID )
676 #define A2ID_SIGFLAG_LOCAL_ALIASES ( 1 << A2ID_SIGDATA_LOCAL_ALIASES )
677 #define A2ID_SIGFLAG_SESSIONID ( 1 << A2ID_SIGDATA_SESSIONID )
678 #define A2ID_SIGFLAG_SUBJECT ( 1 << A2ID_SIGDATA_SUBJECT )
679 #define A2ID_SIGFLAG_TOPIC ( 1 << A2ID_SIGDATA_TOPIC )
680 #define A2ID_SIGFLAG_CRYPTLOCAL ( 1 << A2ID_SIGDATA_CRYPTLOCAL )
681 
682 
720  void *cbdata, const a2id_t *id,
721  uint8_t *buf, uint16_t *buflen);
722 
723 
748  void *cbdata_rid, const a2id_t *lid,
749  uint8_t *buf, uint16_t *buflen);
750 
751 
798 bool a2id_sign (a2id_t *tbs,
799  a2id_sigdata_cb cb, void *cbdata);
800 
801 
841 bool a2id_verify (a2id_t *a2id_to_be_verified,
842  a2id_sigdata_cb cb, void *cbdata);
843 
844 
862 #ifndef DEBUG_DETAIL
863 #define a2sel_detail(descr,id) do { ; } while (0)
864 #define a2id_detail(descr,id) a2sel_detail ((descr), (a2sel_t *) (id))
865 #else
866 #include <arpa2/except.h>
867 static inline void a2sel_detail (char *descr, const a2sel_t *sel) {
868  int arrows = A2ID_OFS_COUNT;
869  int buflen = sel->ofs [A2ID_OFS_END] + arrows + 1;
870  char buf [buflen];
871  int bufofs = 0;
872  int selofs = 0;
873  /* Print all but the final _BUFSIZE after the NUL char */
874  while (arrows > 0) {
875  assertxt (sel->ofs [A2ID_OFS_COUNT - arrows] >= selofs,
876  "A2ID_OFS_xxx are not monotonically rising");
877  if (sel->ofs [A2ID_OFS_COUNT - arrows] == selofs) {
878  buf [bufofs++] = '|';
879  arrows--;
880  continue;
881  }
882  buf [bufofs++] = sel->txt [selofs++];
883  }
884  buf [bufofs] = '\0';
885  log_detail ("%s: %s", descr, buf);
886 }
887 #endif /* DEBUG_DETAIL */
888 
889 #ifdef __cplusplus
890 }
891 #endif
892 
893 #endif /* ARPA2_IDENTITY_H */
894 
#define log_detail(fmt,...)
log_detail(fmt,...)
Definition: except.h:288
#define assertxt(test, fmt,...)
assertxt(test,fmt,...)
Definition: except.h:88
bool a2sel_abstractions(const a2sel_t *specific, const a2sel_t *generic, uint16_t *steps)
Count the number of abstractions to go from one ARPA2 Selector (or Identity) to another ARPA2 Selecto...
bool a2sel_iterate_init(const a2sel_t *start, a2sel_t *cursor)
Iterate an ARPA2 Selector or ARPA2 Identity.
bool a2sel_quickiter_next(a2sel_quickiter *iter)
Iterate to the next Quick Iterator value.
bool a2sel_quickiter_init(a2sel_quickiter *iter)
Lightweight / Lightning-fast ARPA2 Selector and Identity iteration.
bool a2sel_iterate_next(const a2sel_t *start, a2sel_t *cursor)
Progress to the next Iterator value.
bool a2id_sign(a2id_t *tbs, a2id_sigdata_cb cb, void *cbdata)
Possibly attach a signature to an ARPA2 Identity, by adding extra characters to its username.
void a2id_dropkeys(void)
Wipe all keys clean.
a2id_sigdata_t
Signature data types.
Definition: identity.h:654
bool a2id_sigdata_cb(a2id_sigdata_t sd, void *cbdata, const a2id_t *id, uint8_t *buf, uint16_t *buflen)
Callback function prototype to retrieve signature data.
Definition: identity.h:719
bool a2id_addkey(int keyfd)
Add a key to be used for signed identities.
bool a2id_sigdata_base(a2id_sigdata_t sd, void *cbdata_rid, const a2id_t *lid, uint8_t *buf, uint16_t *buflen)
Basic callback function for a signed ARPA2 Identity.
bool a2id_verify(a2id_t *a2id_to_be_verified, a2id_sigdata_cb cb, void *cbdata)
Try to verify a signature on an ARPA2 Identity.
static bool a2act_isdynamicrecipe(const a2act_t *tested)
Test if an a2act_t is a recipe for a Dynamic Actor Identity.
Definition: identity.h:369
static bool a2act_isdynamic(const a2act_t *tested)
Test if an a2act_t is a Dynamic Actor Identity.
Definition: identity.h:357
bool a2id_parse(a2id_t *out, const char *in, unsigned inlen)
Parse and normalise a string into an ARPA2 Identity.
static void a2sel_detail(char *descr, const a2sel_t *sel)
Print a parsed ARPA2 Identity structure on the detail debugging output.
Definition: identity.h:867
bool a2id_parse_remote(a2id_t *out, const char *in, unsigned inlen)
Parse and normalise a string into a remote ARPA2 Identity.
bool a2sel_parse(a2sel_t *out, const char *in, unsigned inlen)
Parse and normalise a string into an ARPA2 Selector.
a2sel_t a2id_t
ARPA2 Identity.
Definition: identity.h:182
a2id_offset_t
Offsets into parsed identity strings.
Definition: identity.h:128
bool a2act_parse(a2act_t *out, const char *in, unsigned inlen, unsigned nact)
Parse and normalise a string into an ARPA2 Actor Identity.
bool a2sel_textshift(a2id_t *shifty, a2id_offset_t ofsidx, uint16_t newofs, bool before)
Shift text in an ARPA2 Selector.
static bool a2act_isstatic(const a2act_t *tested)
Test if an a2act_t is a Static Actor Identity.
Definition: identity.h:346
bool a2sel_special(const a2sel_t *special, const a2sel_t *general)
Test if the left ARPA2 Selector is a specialised form of the right ARPA2 Selector.
static bool a2act_isempty(const a2act_t *tested)
Test if an a2act_t is an empty Actor Identity.
Definition: identity.h:336
a2id_t a2act_t
ARPA2 Actor Identity.
Definition: identity.h:207
void a2id_init(void)
Initialise the ARPA2 Identity system.
void a2id_fini(void)
Finalise the ARPA2 Identity system.
Storage structure for Quick Iteration.
Definition: identity.h:526
ARPA2 Selector.
Definition: identity.h:165