#ifndef __HTTPAUTHD_H__ #define __HTTPAUTHD_H__ /* ----------------------------------------------------------------------- * Memory Buffers */ /* A buffer which owns memory */ typedef struct ha_buffer { int _al; char* _dt; char* _pp; char* _rp; } ha_buffer_t; void ha_bufinit(ha_buffer_t* buf); void ha_buffree(ha_buffer_t* buf); void ha_bufreset(ha_buffer_t* buf); /* Buffer input functions */ int ha_readline(int fd, ha_buffer_t* buf); char* ha_parseline(ha_buffer_t* buf, int trim); char* ha_parseword(ha_buffer_t* buf, const char* delims); /* Buffer output functions */ void ha_bufnext(ha_buffer_t* buf); void ha_bufcat(ha_buffer_t* buf, ...); /* Buffer encoding functions */ void ha_bufenc64(ha_buffer_t* buf, const const char* src, size_t len); void ha_bufdec64(ha_buffer_t* buf, const char* src, size_t len); void ha_bufenchex(ha_buffer_t* buf, const unsigned char* src, size_t len); void ha_bufdechex(ha_buffer_t* buf, const char* src, size_t len); /* Memory allocation functions */ void* ha_bufmalloc(ha_buffer_t* buf, size_t sz); #define ha_bufskip(buf) \ ((buf)->_pp = (buf)->_rp) #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_bufeat(buf) \ ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? ++((buf)->_pp) : (buf)->_pp) #define ha_buferr(buf) \ ((buf)->_dt == NULL) /* ----------------------------------------------------------------------- * HTTP Auth Handlers */ typedef struct ha_context_t; /* * 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)(ha_context_t* 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)(ha_context_t* 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)(ha_context_t* 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)(ha_context_t* ctx, ha_request_t* req, ha_response_t* resp, ha_buffer_t* mem); /* 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 */ size_t context_size; /* Bytes of extra context needed */ } ha_handler_t; /* * OK signifies that things went according to plan. Return * this even if authentication fails (send auth to user) * unless something unexpected happens. */ #define HA_OK 1 /* * FALSE signifies that we couldn't process but it wasn't * an error. */ #define HA_FALSE 0 /* * ERROR means a bad error happened which will kill the * current processing thread. Examples are out of memory * errors or the like. */ #define HA_ERROR -1 struct ha_options; /* Context passed to the handler functions below */ typdef struct ha_context { const char* name; /* A name assigned by the configuration file */ ha_handler_t* handler; /* The original handler structure */ unsigned int types; /* The types of authentication allowed */ int timeout; /* Timeout for cached connections */ void* data; /* Handler specific data */ } 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 MAX_ARGS 2 /* * 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 MAX_HEADERS 2 /* * The maximum number of handlers. If you add * handlers make sure to update this number. */ #define 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 /* A single request from client */ typedef struct ha_request { int type; const char* args[MAX_ARGS]; ha_header_t headers[MAX_HEADERS]; } ha_request_t; /* The various response codes */ #define HA_SERVER_READY 100 #define HA_SERVER_ACCEPT 200 #define HA_SERVER_DECLINE 401 #define HA_SERVER_BADREQ 402 #define HA_SERVER_ERROR 500 #define HA_SERVER_BUSY 500 /* A response to the client */ typedef struct ha_response { int code; const char* detail; ha_header_t headers[MAX_HEADERS]; } ha_response_t; /* Request functions */ ha_header_t* ha_findheader(ha_request_t* req, const char* name); const char* ha_getheader(ha_request_t* req, const char* name, const char* prefix); /* Response functions */ void ha_addheader(ha_response_t* resp, 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); /* A little hashing */ #ifndef MD5_LEN #define MD5_LEN 16 #endif void ha_md5string(const char* data, unsigned char* hash); /* ----------------------------------------------------------------------- * Error Handling */ void ha_message(int level, const char* msg, ...); void ha_messagex(int level, const char* msg, ...); /* ----------------------------------------------------------------------- * Authentication types */ /* The various types of authentication */ #define HA_TYPE_BASIC 1 << 1 #define HA_PREFIX_BASIC "Basic " typedef struct ha_basic_header { const char* user; const char* password; unsigned char key[MD5_LEN]; } ha_basic_header_t; int ha_parsebasic(char* header, ha_buffer_t* buf, ha_basic_header_t* rec); #define HA_TYPE_DIGEST 1 << 2 #define HA_PREFIX_DIGEST "Digest " #define HA_DIGEST_NONCE_LEN MD5_LEN * 2 /* Parsed Digest response from the client */ typedef struct ha_digest_header { const char* scheme; const char* realm; const char* username; const char* nonce; const char* uri; const char* method; const char* digest; const char* algorithm; const char* cnonce; const char* opaque; const char* message_qop; const char* nc; unsigned char key[MD5_LEN]; } ha_digest_header_t; /* Kept by the server for validating the client */ typedef struct ha_digest_record { unsigned char nonce[HA_DIGEST_NONCE_LEN]; unsigned char userhash[MD5_LEN]; unsigned char ha1[MD5_LEN]; unsigned int nc; } ha_digest_record_t; int ha_digestparse(char* header, ha_buffer_t* buf, ha_digest_header_t* rec); int ha_digestcheck(const char* realm, const char* method, const char* uri, ha_buffer_t* buf, ha_digest_header_t* header, ha_digest_record_t* rec); #define HA_TYPE_NTLM 1 << 3 #define HA_PREFIX_NTLM "NTLM " /* ----------------------------------------------------------------------- * URI Parse Support */ struct ha_uri_t { /* Note: We only support HTTP uris */ const char* user; const char* pw; const char* host; unsigned short port; const char* path; const char* query; const char* bookmark; }; char* ha_uriformat(const ha_uri_t* uri, ha_buffer_t* buf); int ha_uriparse(const char* str, ha_uri_t* uri); /* ----------------------------------------------------------------------- * Locking */ void ha_lock(); void ha_unlock(); #endif /* __HTTPAUTHD_H__ */