libvbr(3)

πŸ’– NAME πŸ’–

okay bestie, say hi to libvbr β€” the libvbr(3) manual page. It's the whole squad of functions that make up the Vouch By Reference service facility:

  • vbr_init()
  • vbr_options()
  • vbr_close()
  • vbr_geterror()
  • vbr_getheader()
  • vbr_setcert()
  • vbr_settype()
  • vbr_setdomain()
  • vbr_trustedcerts()
  • vbr_query()
  • vbr_settimeout()
  • vbr_setcallbackint()
  • vbr_setcallbackctx()
  • vbr_setdnscallback()
  • vbr_dns_set_query_service()
  • vbr_dns_set_query_start()
  • vbr_dns_set_query_cancel()
  • vbr_dns_set_query_waitreply()
  • vbr_dns_set_query_waitreply()
  • vbr_dns_set_init()
  • vbr_dns_set_close()
  • vbr_dns_set_nslist()
  • vbr_dns_set_config()
  • vbr_dns_set_trustanchor()
  • vbr_dns_init()

(yep, vbr_dns_set_query_waitreply() is listed twice β€” that's canon, not a typo from me, iykyk πŸ˜­πŸ’…)


✨ SYNOPSIS ✨

first you gotta include the header, no cap:

       #include <vbr.h>

       VBR * vbr_init (void *(* mallocf )(void *, size_t), void (* freef )(void
       *, void *p), void * closure );

       void vbr_options (VBR * vbr , unsigned int opts );

       unsigned char * vbr_geterror (VBR * vbr );

       VBR_STAT vbr_getheader (VBR * vbr, unsigned char * hdr, size_t len );

       void vbr_setcert (VBR * vbr, unsigned char * cert );

       void vbr_settype (VBR * vbr, unsigned char * cert );

       void vbr_setdomain (VBR * vbr, unsigned char * cert );

       void vbr_trustedcerts (VBR * vbr, unsigned char ** cert );

       VBR_STAT vbr_query (VBR * vbr, unsigned char ** res, unsigned char **
       cert );

       VBR_STAT vbr_settimeout (VBR * vbr, unsigned int timeout );

       VBR_STAT vbr_setcallbackint (VBR * vbr, unsigned int cbint );

       VBR_STAT vbr_setcallbackctx (VBR *, vbr, void * ctx );

       VBR_STAT vbr_setdnscallback (VBR *, vbr, void (* func )(const void *));

       void * vbr_dns_set_query_service (VBR * vbr, void * svc );

       void vbr_dns_set_query_cancel (VBR * vbr, int (* func )(void *, void
       *));

       void vbr_dns_set_query_start (VBR * vbr, int (* func )(void *, int,
       unsigned char *, unsigned char *, size_t, void **));

       void vbr_dns_set_query_waitreply (VBR * vbr, int (* func )(void *, void
       *, struct timeval *, size_t *, int *, int *));

       void vbr_dns_set_init (VBR * vbr, int (* func )(void **);

       void vbr_dns_set_close (VBR * vbr, int (* func )(void *);

       void vbr_dns_set_config (VBR * vbr, int (* func )(void *, const char *);

       void vbr_dns_set_nslist (VBR * vbr, int (* func )(void *, const char *);

       void vbr_dns_set_trustanchor (VBR * vbr, int (* func )(void *, const
       char *);

       VBR_STAT vbr_dns_init (VBR * vbr );

       void vbr_close (VBR *);

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so these functions? They're your little interface to a facility that runs Vouch By Reference (VBR) queries and hands you back the results. VBR itself is defined in RFC5518, periodt. πŸ’–

First things first: your app initializes the package by calling vbr_init(). The optional mallocf param is a memory allocation function you provide, and it takes a pointer to a caller-provided opaque data structure (that's the closure param) plus a number of bytes to allocate. If you don't give it a mallocf, it just uses the default system memory allocator malloc(3). The optional freef param is the matching deallocator you provide, taking a pointer to a caller-provided opaque data structure (again, the closure param) and a pointer to the memory to be released. If no freef, the default system memory release function free(3) is used. You get back a handle for future use of that initialized library instance, or NULL on error and errno gets set to tell you what went wrong. πŸ’€

You can call vbr_options() to set query processing options. Scroll to the OPTIONS section for the deets, bestie.

vbr_geterror() is your little detective: poll the library for an error string that gives more description on the most recent failed operation. It's giving emotional support error message. 🫢

Call vbr_getheader() and it generates an RFC-compliant VBR-Info: header field based on data from the other accessor functions, namely vbr_setcert(), vbr_settype() and vbr_setdomain() (they're below, keep scrolling). First param is a library instance, second and third are a pointer to the destination buffer and its length. Heads up: only the value of the header field goes into the buffer, not its name. The standard name of the header field is available as the VBR_INFOHEADER macro. Iconic. ✨

vbr_setcert() takes a VBR library instance as its first argument and a colon-separated list of claimed vouching domains as its second. Same vibe: vbr_settype() sets the message type, and vbr_setdomain() sets the sending domain. These line up with the "mv", "mc" and "md" values from a received message's VBR-Info header field, respectively. The library instance uses these values when you call vbr_getheader() to generate VBR information header fields for outgoing messages, or when you call vbr_query() to check for a vouching reference. Important note: the library does no validation of the possible values of the message type (that's on purpose, so new message types can show up outside the original RFC), and it has no context to validate the domain. So don't come for it. πŸ™ˆ

vbr_trustedcerts() takes a VBR library instance as its first argument and a NULL-terminated array of pointers to certifier names as its second. It's used by vbr_query() to select the vouching services you trust. The intersection of these trusted certifiers and those claimed by an arriving message. The list starts out empty, btw. πŸŽ€

vbr_query() polls your trusted certifiers to see if any of them agree with the assertion the message sender made. The pointer res gets set to point to a result string once the query is resolved. That result is "pass" if any trusted certifier concurred with the sender's assertion. If cert is not NULL, it gets updated to point to the name of the trusted certifier that concurred when a "pass" result comes back. If queries were made but none of them resulted in concurrence, you get a result of "fail". And if no query was made because of errors, or because the trusted certifier set and the sender's certifier set had no vouchers in common, then cert is left unchanged. Periodt. πŸ’…

vbr_settimeout() changes the query timeout. Default is ten seconds. But bestie, listen: this timeout is applied for each voucher query, so a single call to vbr_query() can take longer than ten seconds if multiple queries need to be made. It's giving patient. ⏳

If you want the library to periodically call a function you provide as a little "hey, queries are still in progress" heads-up, register it with vbr_setdnscallback(). The function you give it should take a void context pointer as its only argument. vbr_setcallbackctx() tells the library which context pointer to use, and vbr_setcallbackint() tells it the frequency, in seconds, for calling that callback function. Each of these takes the corresponding VBR library handle as its first argument, and the obvious parameter as its second. Slay. 🌈

By default, the library uses the stock system resolver to conduct DNS queries. If you wanna use alternates, you can specify them with these functions:

vbr_dns_set_query_service() sets a context pointer to the query service to be used, if any. It gets passed as-is to the other DNS functions. It returns its previous value.

vbr_dns_set_query_cancel() sets a pointer to the function that should be called to cancel an open query. That function takes: a void pointer to the DNS query service to be used, and a void pointer to a query handle as previously returned by a call to vbr_dns_set_query_start(). It should return one of the DNS result codes described below.

vbr_dns_set_query_start() sets a pointer to the function called to initiate a new query. Its params: a void pointer to the DNS query service, a DNS record type (like T_TXT), a pointer to a string with the query to start, a pointer to a buffer where the reply gets written, the number of bytes available in that buffer, and a pointer to a void pointer that will be updated to hold a unique handle for that query once it's started. It should return one of the DNS result codes described below.

vbr_dns_set_query_waitreply() sets a pointer to the function called to wait for a reply to an open query. Its params: a void pointer to the DNS query service, a void pointer referencing the query of interest as previously returned by vbr_dns_set_query_start(), a pointer to a struct timeval structure saying how long to wait for a reply (or NULL if infinite waiting is acceptable), a pointer to a size_t that gets updated with the size of the received reply, a pointer to an integer that will contain an error code if the query fails (can be NULL if that info isn't interesting to you), and a pointer to an integer that will contain a DNSSEC status indication (also can be NULL if that info isn't interesting). It should return one of the DNS result codes described below.

vbr_dns_set_init() sets a pointer to the function called when a resolver needs to be initialized. That function should store a handle to the initialized resolver and return zero, or return non-zero if initialization couldn't be completed.

vbr_dns_set_close() sets a pointer to the function called when a resolver needs to be terminated. It receives a handle referencing the resolver to be terminated, and should return zero on success or non-zero on failure.

vbr_dns_set_nslist() sets a pointer to the function called when you need to change the set of nameservers used to resolve RBL queries. It receives a handle referencing the active resolver and a string with a comma-separated list of nameservers to use. Return zero on success and non-zero on failure.

vbr_dns_set_config() sets a pointer to the function called when you need to provide arbitrary configuration info to the resolver. It receives a handle referencing the active resolver and a string containing the configuration. Return zero on success and non-zero on failure.

vbr_dns_set_trustanchor() sets a pointer to the function called when you need to provide trust anchor info (supporting DNSSEC) to the resolver. It receives a handle referencing the active resolver and a string containing the trust anchor data. Return zero on success and non-zero on failure.

Calling vbr_dns_init() forces (re-)initialization of the resolver. Basically, it makes the library call whatever initialization function was defined by vbr_dns_set_init(). πŸ’«

When you're done with the library handle, pass it to vbr_close(). Clean up after yourself, bestie. 🧼


✨ OPTIONS ✨

okay so bestie, setting options? that's the vbr_options() function's whole job. the opts parameter is a bitwise-OR list of the available options your app is requesting. and right now, the currently supported option is literally just this one:

  • VBR_FLAG_TRUSTEDONLY β€” by default, a VBR query gets sent to the intersection of the trusted certifiers (provided by the vbr_trustedcerts() function) and the list of certifiers claimed on a message (provided by the vbr_sercert() function). with this option enabled, the trusted certifiers will be checked and the provided certifiers will be ignored. periodt, no in-between.

πŸ’– RETURN VALUES πŸ’–

the following return codes, of type VBR_STAT, can be returned:

  • VBR_STAT_OK β€” successful completion. we love a clean finish, slay πŸ’…
  • VBR_STAT_INVALID β€” operation failed because an invalid parameter was provided. it's giving "whoops, wrong input" 😭
  • VBR_STAT_DNSERROR β€” operation could not be completed because of errors requesting or receiving a DNS reply; note that this does not include a successful reply that contains a "no record found" result, which is a successful answer. okay so important: "no record found" is still a successful answer, not an error. no cap.
  • VBR_STAT_NORESOURCE β€” a caller-provided buffer was too small to complete the requested operation, or a memory or file descriptor allocation failed. it's giving "out of space/resources" energy πŸ˜΅β€πŸ’«
  • VBR_STAT_NOTIMPLEMENT β€” an optional library feature was not selected at compilation time. so that feature simply wasn't built in, bestie πŸ™ˆ

🌈 DNS RETURN CODES 🌈

any registered DNS functions should return one of the following result codes:

  • VBR_DNS_ERROR β€” an error occurred. the cause of the error can be retrieved using vbr_geterror(). go ask it what's wrong, iykyk.
  • VBR_DNS_SUCCESS β€” the operation was successful. iconic. ✨
  • VBR_DNS_REPLY β€” a reply is available (returned by the "waitreply" function). oh we got a reply? main character energy.
  • VBR_DNS_NOREPLY β€” no reply was received by the time the query timeout was reached (returned by the "waitreply" function). ghosted by the resolver, fr fr πŸ’€
  • VBR_DNS_EXPIRED β€” the query expired completely (returned by the "waitreply" function). Some resolvers set an overall timeout for the query at start time in addition to one for each single wait request; this code indicates the former timeout expired. so the whole query timed out, not just one lil wait. oof.

Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved.


πŸ¦‹ SEE ALSO πŸ¦‹


okay bestie, that's the whole vibe. this page is from libvbr(3), and the footer date? it didn't show up in this copy, but the source/version is right there holding it down. bye, stay slay, and may your DNS replies always be successful πŸ’–βœ¨

πŸ“¦ where this page comes from