#ifndef __HTTPAUTHD_H__ #define __HTTPAUTHD_H__ #include /* ----------------------------------------------------------------------- * Memory Buffers */ struct ha_buffer_internal; /* A buffer which owns memory */ typedef struct ha_buffer { struct ha_buffer_internal* _ft; struct ha_buffer_internal* _dt; char* _pp; char* _rp; } ha_buffer_t; /* Initializes a buffer */ void ha_bufinit(ha_buffer_t* buf); /* Frees all memory associated with a buffer */ void ha_buffree(ha_buffer_t* buf); /* Resets a buffer for later reuse */ void ha_bufreset(ha_buffer_t* buf); #define ha_buflen(buf) \ ((buf)->_rp - (buf)->_pp) #define ha_bufchar(buf) \ ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? *((buf)->_pp) : '\0' ) #define ha_bufdata(buf) \ ((buf)->_pp) #define ha_buferr(buf) \ ((buf)->_dt == NULL) /* Buffer input functions ------------------------------------------------ */ /* Read a line from an input handle */ int ha_bufreadline(int fd, ha_buffer_t* buf); /* Parse the current line */ char* ha_bufparseline(ha_buffer_t* buf, int trim); /* Parse a word from the current block */ char* ha_bufparseword(ha_buffer_t* buf, const char* delims); #define ha_bufskip(buf) \ ((buf)->_pp = (buf)->_rp) #define ha_bufeat(buf) \ ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? ++((buf)->_pp) : (buf)->_pp) /* Buffer output functions ----------------------------------------------- */ /* Adds multiple strings together */ char* ha_bufmcat(ha_buffer_t* buf, ...); /* Copies a string to the buffer */ char* ha_bufcpy(ha_buffer_t* buf, const char* src); /* Copies a portion of a string to the buffer */ char* ha_bufncpy(ha_buffer_t* buf, const char* src, size_t len); /* Opens up the end of the current block so it can be joined by more data */ #define ha_bufjoin(buf) \ ((buf)->_rp && ((buf)->_rp != (buf)->_pp) ? (buf)->_rp-- : (buf)->_rp) #define ha_bufcat ha_bufcpy /* Buffer allocation functions ------------------------------------------- */ /* Memory allocation */ void* ha_bufmalloc(ha_buffer_t* buf, size_t bytes); void* ha_bufmemdup(ha_buffer_t* buf, const void* src, size_t bytes); /* Buffer Encoding Functions --------------------------------------------- */ /* Encode an array of bytes in base 64 */ char* ha_bufenc64(ha_buffer_t* buf, const void* src, size_t bytes); /* Decode an array of bytes from base 64 */ void* ha_bufdec64(ha_buffer_t* buf, const char* src, size_t* bytes); /* Encode an array of bytes in hex */ char* ha_bufenchex(ha_buffer_t* buf, const void* src, size_t bytes); /* Decode an array of bytes in hex */ void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t* bytes); /* ----------------------------------------------------------------------- * HTTP Auth Handlers */ struct ha_context; struct ha_request; /* * This function initializes the handler. It gets called * after the configuration gets loaded so if a config func * is registered it'll get called before this. */ typedef int (*auth_init_t)(struct ha_context* ctx); /* * This function is called when the app exits. All threads * should have completed at this point, so it's not necessary * to be thread safe in here */ typedef void (*auth_destroy_t)(struct ha_context* ctx); /* * Called once for each configuration parameter. This is * called before the initialization function. 'name' will * always be lower case. White space will always be trimmed * from the value. */ typedef int (*auth_config_t)(struct ha_context* ctx, const char* name, const char* value); /* * Called for each authentication request that is designated * for this handler. Note that all data access in this * function must be thread-safe. */ typedef int (*auth_process_t)(struct ha_request* rq); /* An authentication handler */ typedef struct ha_handler { const char* type; auth_init_t f_init; /* #1 Called to initialize handler */ auth_destroy_t f_destroy; /* #3 Called when exiting */ auth_config_t f_config; /* #0 Called for each config param */ auth_process_t f_process; /* #2 Called for each auth request */ const void* context_default; /* The default context */ const size_t context_size; /* Bytes of extra context needed */ } ha_handler_t; /* * OK signifies that things went according to plan. */ #define HA_OK 0 /* * FALSE: the process failed but it wasn't an error. */ #define HA_FALSE 1 /* * ERROR means a bad error happened which will kill the * current processing thread. Examples are out of memory * errors or the like. */ #define HA_CRITERROR -1 /* * FAILED: something internal to the server failed. */ #define HA_FAILED -2 /* * BADREQ means that we got a bad request or call. */ #define HA_BADREQ -3 /* Context passed to the handler functions above */ typedef struct ha_context { const char* name; /* A name assigned by the configuration file */ const ha_handler_t* handler; /* The original handler structure */ void* ctx_data; /* Handler specific data */ /* Context specific options */ unsigned int allowed_types; int cache_timeout; int cache_max; /* For basic and digest auth: */ const char* realm; /* For digest auth: */ unsigned int digest_ignoreuri : 1; unsigned int digest_ignorenc : 1; const char* digest_debugnonce; } ha_context_t; /* ----------------------------------------------------------------------- * HTTP Auth Structures and Constants */ /* * The maximum number of commands in any httpauth * command. This is defined by the protocol. There * should be no need to change it unless we're * adding or removing commands */ #define HA_MAX_ARGS 4 /* * The maximum number of pertinent headers to read * from the client. If you need to add valid headers * make sure to update this number *and* the list * of valid headers in httpauthd.c */ #define HA_MAX_HEADERS 2 /* * The maximum number of handlers. If you add * handlers make sure to update this number. */ #define HA_MAX_HANDLERS 4 /* A single header in memory */ typedef struct ha_header { const char* name; const char* data; } ha_header_t; /* The various command codes */ #define REQTYPE_IGNORE 0 #define REQTYPE_QUIT 1 #define REQTYPE_AUTH 2 #define REQTYPE_SET 3 #define AUTH_ARG_CONN 0 #define AUTH_ARG_METHOD 1 #define AUTH_ARG_URI 2 /* A single request from client along with response */ typedef struct ha_request { unsigned int id; /* Unique connection identifier */ int req_type; /* The command type */ const char* req_args[HA_MAX_ARGS]; /* Arguments for the command */ ha_header_t req_headers[HA_MAX_HEADERS]; /* Headers for command */ /* Additional request info */ ha_context_t* context; const char* digest_domain; /* The buffer in use */ ha_buffer_t* buf; int resp_code; /* The response code */ const char* resp_detail; /* The details for response */ ha_header_t resp_headers[HA_MAX_HEADERS]; /* Headers for the response */ } ha_request_t; /* The various response codes for the client */ #define HA_SERVER_READY 100 #define HA_SERVER_OK 200 #define HA_SERVER_ACCEPTED 202 #define HA_SERVER_DECLINE 401 #define HA_SERVER_BADREQ 400 #define HA_SERVER_BUSY 500 /* Request functions */ const ha_header_t* ha_findheader(const ha_request_t* rq, const char* name); const char* ha_getheader(const ha_request_t* rq, const char* name, const char* prefix); /* Response functions */ void ha_addheader(ha_request_t* rq, const char* name, const char* data); /* Configuration functions */ int ha_confbool(const char* name, const char* conf, int* value); int ha_confint(const char* name, const char* conf, int min, int max, int* value); /* ----------------------------------------------------------------------- * Error Handling */ void ha_message(const ha_request_t* rq, int level, const char* msg, ...); void ha_messagex(const ha_request_t* rq, int level, const char* msg, ...); /* ----------------------------------------------------------------------- * Authentication types */ /* The various types of authentication */ #define HA_TYPE_BASIC 1 << 1 #define HA_PREFIX_BASIC "Basic " #define HA_TYPE_DIGEST 1 << 2 #define HA_PREFIX_DIGEST "Digest " #define HA_TYPE_NTLM 1 << 3 #define HA_PREFIX_NTLM "NTLM " /* ----------------------------------------------------------------------- * URI Parse Support */ typedef struct ha_uri { const char* scheme; const char* user; const char* pw; const char* host; unsigned short port; const char* path; const char* query; const char* fragment; } ha_uri_t; char* ha_uriformat(ha_buffer_t* buf, const ha_uri_t* uri); int ha_uriparse(ha_buffer_t* buf, const char* suri, ha_uri_t* uri); int ha_uricmp(ha_uri_t* one, ha_uri_t* two); /* ----------------------------------------------------------------------- * Locking */ void ha_lock(); void ha_unlock(); /* ----------------------------------------------------------------------- * Miscellaneous */ int ha_genrandom(unsigned char* data, size_t len); #endif /* __HTTPAUTHD_H__ */