diff options
Diffstat (limited to 'daemon/httpauthd.c')
-rw-r--r-- | daemon/httpauthd.c | 2021 |
1 files changed, 1007 insertions, 1014 deletions
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c index c238a1a..17ed15c 100644 --- a/daemon/httpauthd.c +++ b/daemon/httpauthd.c @@ -36,15 +36,15 @@ extern ha_handler_t ntlm_handler; /* This is the list of all available handlers */ ha_handler_t* g_handlerlist[] = { - &simple_handler, - &ldap_handler, - &ntlm_handler + &simple_handler, + &ldap_handler, + &ntlm_handler }; typedef struct httpauth_loaded { - ha_context_t ctx; - struct httpauth_loaded* next; + ha_context_t ctx; + struct httpauth_loaded* next; } httpauth_loaded_t; @@ -58,34 +58,34 @@ httpauth_loaded_t* g_handlers = NULL; /* A command definition. Used in parsing */ typedef struct httpauth_command { - const char* name; - int code; - int word_args; /* Arguments to be parsed as words */ - int rest_arg; /* Parse remainder as one arg? */ - const char** headers; /* Headers needed/allowed */ + const char* name; + int code; + int word_args; /* Arguments to be parsed as words */ + int rest_arg; /* Parse remainder as one arg? */ + const char** headers; /* Headers needed/allowed */ } httpauth_command_t; /* The various valid headers for the auth command */ const char* kAuthHeaders[] = { - "Authorization", - NULL + "Authorization", + NULL }; /* The command definitions */ const httpauth_command_t kCommands[] = { - { "auth", REQTYPE_AUTH, 3, 0, kAuthHeaders }, - { "set", REQTYPE_SET, 1, 1, NULL }, - { "quit", REQTYPE_QUIT, 0, 0, NULL }, - { NULL, -1, 0, 0, NULL } + { "auth", REQTYPE_AUTH, 3, 0, kAuthHeaders }, + { "set", REQTYPE_SET, 1, 1, NULL }, + { "quit", REQTYPE_QUIT, 0, 0, NULL }, + { NULL, -1, 0, 0, NULL } }; typedef struct httpauth_thread { - pthread_t tid; - int fd; + pthread_t tid; + int fd; } httpauth_thread_t; @@ -126,9 +126,8 @@ static int usage(); static void writepid(const char* pid); static void* httpauth_thread(void* arg); static int httpauth_processor(int ifd, int ofd); -static int httpauth_respond(int ofd, int scode, int ccode, const char* msg); -static int process_auth(ha_request_t* req, ha_response_t* resp, - ha_buffer_t* outb); +static int httpauth_respond(ha_request_t* rq, int ofd, int scode, int ccode, const char* msg); +static int process_auth(ha_request_t* rq); static int config_parse(const char* file, ha_buffer_t* buf); static void on_quit(int signal); @@ -138,990 +137,984 @@ static void on_quit(int signal); int main(int argc, char* argv[]) { - const char* conf = DEFAULT_CONFIG; - const char* pidfile = NULL; - httpauth_thread_t* threads = NULL; - httpauth_loaded_t* h; - char peername[MAXPATHLEN]; - struct sockaddr_any sany; - int daemonize = 1; - ha_buffer_t cbuf; - int r, i, sock; - int ch = 0; - - /* Keep note of the main thread */ - g_mainthread = pthread_self(); - - /* Create the main mutex */ - if(pthread_mutexattr_init(&g_mutexattr) != 0 || - pthread_mutexattr_settype(&g_mutexattr, HA_MUTEX_TYPE) || - pthread_mutex_init(&g_mutex, &g_mutexattr) != 0) - errx(1, "threading problem. can't create mutex"); - - /* Parse the arguments nicely */ + const char* conf = DEFAULT_CONFIG; + const char* pidfile = NULL; + httpauth_thread_t* threads = NULL; + httpauth_loaded_t* h; + char peername[MAXPATHLEN]; + struct sockaddr_any sany; + int daemonize = 1; + ha_buffer_t cbuf; + int r, i, sock; + int ch = 0; + + /* Keep note of the main thread */ + g_mainthread = pthread_self(); + + /* Create the main mutex */ + if(pthread_mutexattr_init(&g_mutexattr) != 0 || + pthread_mutexattr_settype(&g_mutexattr, HA_MUTEX_TYPE) || + pthread_mutex_init(&g_mutex, &g_mutexattr) != 0) + errx(1, "threading problem. can't create mutex"); + + /* Parse the arguments nicely */ while((ch = getopt(argc, argv, "d:f:p:X")) != -1) { switch(ch) { /* Don't daemonize */ - case 'd': - { - char* t; - - daemonize = 0; - g_debuglevel = strtol(optarg, &t, 10); - if(*t || g_debuglevel > 4) - errx(1, "invalid debug log level"); - g_debuglevel += LOG_ERR; - } - break; - - /* The configuration file */ - case 'f': - conf = optarg; - break; - - /* Write out a pid file */ - case 'p': - pidfile = optarg; - break; - - /* Process console input instead */ + case 'd': + { + char* t; + daemonize = 0; + g_debuglevel = strtol(optarg, &t, 10); + if(*t || g_debuglevel > 4) + errx(1, "invalid debug log level"); + g_debuglevel += LOG_ERR; + } + break; + + /* The configuration file */ + case 'f': + conf = optarg; + break; + + /* Write out a pid file */ + case 'p': + pidfile = optarg; + break; + + /* Process console input instead */ case 'X': - g_console = 1; - daemonize = 0; - break; + g_console = 1; + daemonize = 0; + break; - /* Usage information */ - case '?': - default: - return usage(); - break; - } - } + /* Usage information */ + case '?': + default: + return usage(); + break; + } + } - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; - if(argc != 0) - return usage(); + if(argc != 0) + return usage(); - ha_messagex(LOG_DEBUG, "starting up..."); + ha_messagex(NULL, LOG_DEBUG, "starting up..."); - /* From here on out we need to quit in an orderly fashion */ + /* From here on out we need to quit in an orderly fashion */ - /* Run global initialization on all handlers */ - for(i = 0; i < countof(g_handlerlist); i++) - { - if(g_handlerlist[i]->f_init) + /* Run global initialization on all handlers */ + for(i = 0; i < countof(g_handlerlist); i++) { - if((r = (g_handlerlist[i]->f_init)(NULL)) == -1) - goto finally; + if(g_handlerlist[i]->f_init) + { + if((r = (g_handlerlist[i]->f_init)(NULL)) == -1) + goto finally; + } } - } - /* Initialize our configuration buffer */ - ha_bufinit(&cbuf); + /* Initialize our configuration buffer */ + ha_bufinit(&cbuf); - /* Parse the configuration */ - config_parse(conf, &cbuf); + /* Parse the configuration */ + config_parse(conf, &cbuf); - if(!g_console) - { - /* Create the thread buffers */ - threads = (httpauth_thread_t*)calloc(g_maxthreads, sizeof(httpauth_thread_t)); - if(!threads) - errx(1, "out of memory"); + if(!g_console) + { + /* Create the thread buffers */ + threads = (httpauth_thread_t*)calloc(g_maxthreads, sizeof(httpauth_thread_t)); + if(!threads) + errx(1, "out of memory"); - /* Get the socket type */ - if(sock_any_pton(g_socket, &sany, DEFAULT_PORT) == -1) - errx(1, "invalid socket name or ip: %s", g_socket); + /* TODO: Import the new sock_any from clamsmtp */ + /* Get the socket type */ + if(sock_any_pton(g_socket, &sany, DEFAULT_PORT) == -1) + errx(1, "invalid socket name or ip: %s", g_socket); - /* Create the socket */ - sock = socket(SANY_TYPE(sany), SOCK_STREAM, 0); - if(sock < 0) - err(1, "couldn't open socket"); + /* Create the socket */ + sock = socket(SANY_TYPE(sany), SOCK_STREAM, 0); + if(sock < 0) + err(1, "couldn't open socket"); - /* Unlink the socket file if it exists */ - /* TODO: Is this safe? */ - unlink(g_socket); + /* Unlink the socket file if it exists */ + /* TODO: Is this safe? */ + unlink(g_socket); - if(bind(sock, &SANY_ADDR(sany), SANY_LEN(sany)) != 0) - err(1, "couldn't bind to address: %s", g_socket); + if(bind(sock, &SANY_ADDR(sany), SANY_LEN(sany)) != 0) + err(1, "couldn't bind to address: %s", g_socket); - /* Let 5 connections queue up */ - if(listen(sock, 5) != 0) - err(1, "couldn't listen on socket"); + /* Let 5 connections queue up */ + if(listen(sock, 5) != 0) + err(1, "couldn't listen on socket"); - ha_messagex(LOG_DEBUG, "created socket: %s", g_socket); - } + ha_messagex(NULL, LOG_DEBUG, "created socket: %s", g_socket); + } - /* Initialize all the handlers */ - for(h = g_handlers; h; h = h->next) - { - if(h->ctx.handler->f_init) + /* Initialize all the handlers */ + for(h = g_handlers; h; h = h->next) { - if((r = (h->ctx.handler->f_init)(&(h->ctx))) == -1) - goto finally; + if(h->ctx.handler->f_init) + { + if((r = (h->ctx.handler->f_init)(&(h->ctx))) == -1) + goto finally; + } } - } - - - /* This is for debugging the internal processes */ - if(g_console) - { - ha_messagex(LOG_DEBUG, "processing from console"); - r = httpauth_processor(0, 1); - goto finally; - } - /* This is the daemon section of the code */ - else - { - if(daemonize) + /* This is for debugging the internal processes */ + if(g_console) { - /* Fork a daemon nicely here */ - if(daemon(0, 0) == -1) - { - ha_message(LOG_ERR, "couldn't run httpauth as daemon"); - exit(1); - } - - ha_messagex(LOG_DEBUG, "running as a daemon"); - g_daemonized = 1; + ha_messagex(NULL, LOG_DEBUG, "processing from console"); + r = httpauth_processor(0, 1); + goto finally; } - writepid(pidfile); - /* Handle some signals */ - signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGINT, on_quit); - signal(SIGTERM, on_quit); + /* This is the daemon section of the code */ + else + { + if(daemonize) + { + /* Fork a daemon nicely here */ + if(daemon(0, 0) == -1) + { + ha_message(NULL, LOG_ERR, "couldn't run httpauth as daemon"); + exit(1); + } - siginterrupt(SIGINT, 1); - siginterrupt(SIGTERM, 1); + ha_messagex(NULL, LOG_DEBUG, "running as a daemon"); + g_daemonized = 1; + } - /* Open the system log */ - openlog("httpauthd", 0, LOG_AUTHPRIV); + writepid(pidfile); - ha_messagex(LOG_DEBUG, "accepting connections"); + /* Handle some signals */ + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, on_quit); + signal(SIGTERM, on_quit); - /* Now loop and accept the connections */ - while(!g_quit) - { - int fd; + siginterrupt(SIGINT, 1); + siginterrupt(SIGTERM, 1); - fd = accept(sock, NULL, NULL); - if(fd == -1) - { - switch(errno) - { - case EINTR: - case EAGAIN: - break; + /* Open the system log */ + openlog("httpauthd", 0, LOG_AUTHPRIV); - case ECONNABORTED: - ha_message(LOG_ERR, "couldn't accept a connection"); - break; + ha_messagex(NULL, LOG_DEBUG, "accepting connections"); - default: - ha_message(LOG_ERR, "couldn't accept a connection"); - g_quit = 1; - break; - }; + /* Now loop and accept the connections */ + while(!g_quit) + { + int fd; - if(g_quit) - break; + fd = accept(sock, NULL, NULL); + if(fd == -1) + { + switch(errno) + { + case EINTR: + case EAGAIN: + break; + + case ECONNABORTED: + ha_message(NULL, LOG_ERR, "couldn't accept a connection"); + break; + + default: + ha_message(NULL, LOG_ERR, "couldn't accept a connection"); + g_quit = 1; + break; + }; + + if(g_quit) + break; + + continue; + } - continue; - } + memset(&sany, 0, sizeof(sany)); + SANY_LEN(sany) = sizeof(sany); - memset(&sany, 0, sizeof(sany)); - SANY_LEN(sany) = sizeof(sany); + /* TODO: Move this code into the thread */ + /* Get the peer name */ + if(getpeername(fd, &SANY_ADDR(sany), &SANY_LEN(sany)) == -1 || + sock_any_ntop(&sany, peername, MAXPATHLEN, SANY_OPT_NOPORT) == -1) + ha_messagex(NULL, LOG_WARNING, "%d: couldn't get peer address", fd); + else + ha_messagex(NULL, LOG_INFO, "%d: accepted connection from: %s", fd, peername); - /* Get the peer name */ - if(getpeername(fd, &SANY_ADDR(sany), &SANY_LEN(sany)) == -1 || - sock_any_ntop(&sany, peername, MAXPATHLEN, SANY_OPT_NOPORT) == -1) - ha_messagex(LOG_WARNING, "%d: couldn't get peer address", fd); - else - ha_messagex(LOG_INFO, "%d: accepted connection from: %s", fd, peername); + /* Look for thread and also clean up others */ + for(i = 0; i < g_maxthreads; i++) + { + /* Clean up quit threads */ + if(threads[i].tid != 0) + { + if(threads[i].fd == -1) + { + ha_messagex(NULL, LOG_DEBUG, "cleaning up completed thread"); + pthread_join(threads[i].tid, NULL); + threads[i].tid = 0; + } + } + + /* Start a new thread if neccessary */ + if(fd != -1 && threads[i].tid == 0) + { + threads[i].fd = fd; + r = pthread_create(&(threads[i].tid), NULL, httpauth_thread, + (void*)(threads + i)); + if(r != 0) + { + errno = r; + ha_message(NULL, LOG_ERR, "couldn't create thread"); + g_quit = 1; + break; + } + + ha_messagex(NULL, LOG_DEBUG, "%d: created thread for connection", fd); + fd = -1; + break; + } + } - /* Look for thread and also clean up others */ - for(i = 0; i < g_maxthreads; i++) - { - /* Clean up quit threads */ - if(threads[i].tid != 0) - { - if(threads[i].fd == -1) - { - ha_messagex(LOG_DEBUG, "cleaning up completed thread"); - pthread_join(threads[i].tid, NULL); - threads[i].tid = 0; - } + /* Check to make sure we have a thread */ + if(fd != -1) + { + ha_messagex(NULL, LOG_ERR, "too many connections open (max %d)", g_maxthreads); + httpauth_respond(NULL, fd, HA_SERVER_ERROR, 0, "too many connections"); + shutdown(fd, SHUT_RDWR); + } } - /* Start a new thread if neccessary */ - if(fd != -1 && threads[i].tid == 0) + ha_messagex(NULL, LOG_INFO, "waiting for threads to quit"); + + /* Quit all threads here */ + for(i = 0; i < g_maxthreads; i++) { - threads[i].fd = fd; - r = pthread_create(&(threads[i].tid), NULL, httpauth_thread, - (void*)(threads + i)); - if(r != 0) - { - errno = r; - ha_message(LOG_ERR, "couldn't create thread"); - g_quit = 1; - break; - } + /* Clean up quit threads */ + if(threads[i].tid != 0) + { + if(threads[i].fd != -1) + shutdown(threads[i].fd, SHUT_RDWR); - ha_messagex(LOG_DEBUG, "%d: created thread for connection", fd); - fd = -1; - break; + pthread_join(threads[i].tid, NULL); + } } - } - - /* Check to make sure we have a thread */ - if(fd != -1) - { - ha_messagex(LOG_ERR, "too many connections open (max %d)", g_maxthreads); - httpauth_respond(fd, HA_SERVER_ERROR, 0, "too many connections"); - shutdown(fd, SHUT_RDWR); - } - } - - ha_messagex(LOG_INFO, "waiting for threads to quit"); - /* Quit all threads here */ - for(i = 0; i < g_maxthreads; i++) - { - /* Clean up quit threads */ - if(threads[i].tid != 0) - { - if(threads[i].fd != -1) - shutdown(threads[i].fd, SHUT_RDWR); - - pthread_join(threads[i].tid, NULL); - } + r = 0; } - r = 0; - } - finally: - ha_messagex(LOG_DEBUG, "performing cleanup..."); + ha_messagex(NULL, LOG_DEBUG, "performing cleanup..."); - /* Uninitialize all the handlers */ - for(h = g_handlers; h; h = h->next) - { - if(h->ctx.handler->f_destroy) - (h->ctx.handler->f_destroy)(&(h->ctx)); - } - - /* Run global destroy for all handlers */ - for(i = 0; i < countof(g_handlerlist); i++) - { - if(g_handlerlist[i]->f_destroy) - (g_handlerlist[i]->f_destroy)(NULL); - } + /* Uninitialize all the handlers */ + for(h = g_handlers; h; h = h->next) + { + if(h->ctx.handler->f_destroy) + (h->ctx.handler->f_destroy)(&(h->ctx)); + } - /* Clean up memory and stuff */ - ha_buffree(&cbuf); + /* Run global destroy for all handlers */ + for(i = 0; i < countof(g_handlerlist); i++) + { + if(g_handlerlist[i]->f_destroy) + (g_handlerlist[i]->f_destroy)(NULL); + } - /* Close the mutex */ - pthread_mutex_destroy(&g_mutex); - pthread_mutexattr_destroy(&g_mutexattr); + /* Clean up memory and stuff */ + ha_buffree(&cbuf); - ha_messagex(LOG_DEBUG, "stopped"); + /* Close the mutex */ + pthread_mutex_destroy(&g_mutex); + pthread_mutexattr_destroy(&g_mutexattr); - return r == -1 ? 1 : 0; + ha_messagex(NULL, LOG_DEBUG, "stopped"); + return r == -1 ? 1 : 0; } static void on_quit(int signal) { - g_quit = 1; - fprintf(stderr, "httpauthd: got signal to quit\n"); + g_quit = 1; + fprintf(stderr, "httpauthd: got signal to quit\n"); } static int usage() { - fprintf(stderr, "usage: httpauthd [-d level] [-X] [-p pidfile] [-f conffile]\n"); - return 2; + fprintf(stderr, "usage: httpauthd [-d level] [-X] [-p pidfile] [-f conffile]\n"); + return 2; } static void writepid(const char* pidfile) { - FILE* f = fopen(pidfile, "w"); - if(f == NULL) - { - warnx("couldn't open pid file: %s", pidfile); - } - else - { - fprintf(f, "%d\n", (int)getpid()); - - if(ferror(f)) - warnx("couldn't write to pid file: %s", pidfile); - - fclose(f); - } + FILE* f = fopen(pidfile, "w"); + if(f == NULL) + { + warnx("couldn't open pid file: %s", pidfile); + } + else + { + fprintf(f, "%d\n", (int)getpid()); + + if(ferror(f)) + warnx("couldn't write to pid file: %s", pidfile); + + fclose(f); + } } static void* httpauth_thread(void* arg) { - httpauth_thread_t* thread = (httpauth_thread_t*)arg; - int r; + httpauth_thread_t* thread = (httpauth_thread_t*)arg; + int r; - siginterrupt(SIGINT, 1); - siginterrupt(SIGTERM, 1); - - ASSERT(thread); - ASSERT(thread->fd != -1); + siginterrupt(SIGINT, 1); + siginterrupt(SIGTERM, 1); - /* call the processor */ - r = httpauth_processor(thread->fd, thread->fd); + ASSERT(thread); + ASSERT(thread->fd != -1); - ha_messagex(LOG_INFO, "%d: closed connection", thread->fd); + /* call the processor */ + r = httpauth_processor(thread->fd, thread->fd); - /* mark this as done */ - thread->fd = -1; + /* TODO: Move this to more appropriate place (where we have a req) */ + ha_messagex(NULL, LOG_INFO, "%d: closed connection", thread->fd); - return (void*)r; + /* mark this as done */ + thread->fd = -1; + return (void*)r; } /* ----------------------------------------------------------------------- * Logging */ -void log_request(ha_request_t* req, ha_buffer_t* buf, int fd) +void log_request(ha_request_t* rq) { - const httpauth_command_t* cmd; - const char* t; - const char* t2; - int i; + const httpauth_command_t* cmd; + const char* t; + const char* t2; + int i; - if(g_debuglevel < LOG_DEBUG) - return; + if(g_debuglevel < LOG_DEBUG) + return; - if(req->type == REQTYPE_IGNORE || req->type == -1) - return; + if(rq->req_type == REQTYPE_IGNORE || rq->req_type == -1) + return; - ha_bufcpy(buf, ""); + ha_bufcpy(rq->buf, ""); - for(i = 0; i < HA_MAX_ARGS; i++) - { - if(req->args[i]) + for(i = 0; i < HA_MAX_ARGS; i++) { - ha_bufjoin(buf); - ha_bufmcat(buf, ha_buflen(buf) > 0 ? ", " : "", req->args[i], NULL); + if(rq->req_args[i]) + { + ha_bufjoin(rq->buf); + ha_bufmcat(rq->buf, ha_buflen(rq->buf) > 0 ? ", " : "", rq->req_args[i], NULL); + } } - } - t = ha_bufdata(buf); + t = ha_bufdata(rq->buf); + t2 = NULL; - t2 = NULL; - - /* Figure out which command it is */ - for(cmd = kCommands; cmd->name; cmd++) - { - if(cmd->code == req->type) + /* Figure out which command it is */ + for(cmd = kCommands; cmd->name; cmd++) { - t2 = cmd->name; - break; + if(cmd->code == rq->req_type) + { + t2 = cmd->name; + break; + } } - } - ASSERT(t2); + ASSERT(t2); - ha_messagex(LOG_DEBUG, "%d: received request: " - "[ type: %s / args: %s ]", fd, t2, t); + ha_messagex(rq, LOG_DEBUG, "received request: [ type: %s / args: %s ]", t2, t); - for(i = 0; i < HA_MAX_HEADERS; i++) - { - if(req->headers[i].name) + for(i = 0; i < HA_MAX_HEADERS; i++) { - ASSERT(req->headers[i].data); - ha_messagex(LOG_DEBUG, "%d: received header: [ %s: %s ]", fd, - req->headers[i].name, req->headers[i].data); + if(rq->req_headers[i].name) + { + ASSERT(rq->req_headers[i].data); + ha_messagex(rq, LOG_DEBUG, "received header: [ %s: %s ]", + rq->req_headers[i].name, rq->req_headers[i].data); + } } - } } -void log_response(ha_response_t* resp, int fd) +void log_response(ha_request_t* rq) { - int i; + int i; - if(g_debuglevel < LOG_DEBUG) - return; + if(g_debuglevel < LOG_DEBUG) + return; - ha_messagex(LOG_DEBUG, "%d: sending response: " - "[ code: 200 / ccode: %d / detail: %s ]", fd, - resp->code, resp->detail ? resp->detail : ""); + ha_messagex(rq, LOG_DEBUG, "sending response: [ code: 200 / ccode: %d / detail: %s ]", + rq->resp_code, rq->resp_detail ? rq->resp_detail : ""); - for(i = 0; i < HA_MAX_HEADERS; i++) - { - if(resp->headers[i].name) + for(i = 0; i < HA_MAX_HEADERS; i++) { - ASSERT(resp->headers[i].data); - ha_messagex(LOG_DEBUG, "%d: sending header: [ %s: %s ]", fd, - resp->headers[i].name, resp->headers[i].data); + if(rq->resp_headers[i].name) + { + ASSERT(rq->resp_headers[i].data); + ha_messagex(rq, LOG_DEBUG, "sending header: [ %s: %s ]", + rq->resp_headers[i].name, rq->resp_headers[i].data); + } } - } } -void log_respcode(int code, const char* msg, int fd) +void log_respcode(ha_request_t* rq, int code, const char* msg) { - if(g_debuglevel < LOG_DEBUG) - return; + if(g_debuglevel < LOG_DEBUG) + return; - ha_messagex(LOG_DEBUG, "%d: sending response: " - "[ code: %d / detail: %s ]", fd, code, msg ? msg : ""); + ha_messagex(rq, LOG_DEBUG, "sending response: [ code: %d / detail: %s ]", + code, msg ? msg : ""); } /* ----------------------------------------------------------------------- * Command Parsing and Handling */ -static int httpauth_read(int ifd, ha_request_t* req, - ha_buffer_t* buf) +static int httpauth_read(ha_request_t* rq, int ifd) { - const httpauth_command_t* cmd; - char* t; - int i, r; - int more = 1; + const httpauth_command_t* cmd; + char* t; + int i, r; + int more = 1; - ASSERT(req && buf); - ASSERT(ifd != -1); + ASSERT(r); + ASSERT(ifd != -1); - /* Clean up the request header */ - req->type = -1; - memset(req->args, 0, sizeof(req->args)); - memset(req->headers, 0, sizeof(req->headers)); + /* Clean up the request header */ + rq->req_type = -1; + memset(rq->req_args, 0, sizeof(rq->req_args)); + memset(rq->req_headers, 0, sizeof(rq->req_headers)); - /* This guarantees a bit of memory allocated, and resets buffer */ - ha_bufreset(buf); + /* This guarantees a bit of memory allocated, and resets buffer */ + ha_bufreset(rq->buf); - r = ha_bufreadline(ifd, buf); - if(r == -1) - return -1; + r = ha_bufreadline(ifd, rq->buf); + if(r == -1) + return -1; - /* Check if this is the last line */ - if(r == 0) - more = 0; + /* Check if this is the last line */ + if(r == 0) + more = 0; - /* Check to see if we got anything */ - if(ha_buflen(buf) == 0) - { - req->type = REQTYPE_IGNORE; - return more; - } + /* Check to see if we got anything */ + if(ha_buflen(rq->buf) == 0) + { + rq->req_type = REQTYPE_IGNORE; + return more; + } - /* Find the first space in the line */ - t = ha_bufparseword(buf, " \t"); + /* Find the first space in the line */ + t = ha_bufparseword(rq->buf, " \t"); - if(t) - { - /* Figure out which command it is */ - for(cmd = kCommands; cmd->name; cmd++) + if(t) { - if(strcasecmp(t, cmd->name) == 0) - { - req->type = cmd->code; - break; - } + /* Figure out which command it is */ + for(cmd = kCommands; cmd->name; cmd++) + { + if(strcasecmp(t, cmd->name) == 0) + { + rq->req_type = cmd->code; + break; + } + } } - } - - else - { - req->type = REQTYPE_IGNORE; - return more; - } - /* Check for invalid command */ - if(req->type == -1) - return more; + else + { + rq->req_type = REQTYPE_IGNORE; + return more; + } - /* Now parse the arguments if any */ - for(i = 0; i < cmd->word_args; i++) - req->args[i] = ha_bufparseword(buf, " \t"); + /* Check for invalid command */ + if(rq->req_type == -1) + return more; - /* Does it want the rest as one argument? */ - if(cmd->rest_arg) - req->args[i] = ha_bufparseline(buf, 1); + /* Now parse the arguments if any */ + for(i = 0; i < cmd->word_args; i++) + rq->req_args[i] = ha_bufparseword(rq->buf, " \t"); + /* Does it want the rest as one argument? */ + if(cmd->rest_arg) + rq->req_args[i] = ha_bufparseline(rq->buf, 1); - /* Now skip anything else we have in the buffer */ - ha_bufskip(buf); + /* Now skip anything else we have in the buffer */ + ha_bufskip(rq->buf); - /* If we need headers, then read them now */ - if(cmd->headers) - { - const char** head; /* For iterating through valid headers */ - int valid = 0; /* The last header was valid */ - i = 0; /* The header we're working with */ - for(;;) + /* If we need headers, then read them now */ + if(cmd->headers) { - /* Make sure we have more data */ - if(!more) - break; - - r = ha_bufreadline(ifd, buf); - if(r == -1) - return -1; - - /* Check if this is the last line */ - if(r == 0) - more = 0; - - /* An empty line is the end of the headers */ - if(ha_buflen(buf) == 0) - break; + const char** head; /* For iterating through valid headers */ + int valid = 0; /* The last header was valid */ + i = 0; /* The header we're working with */ - /* Check if the header starts with a space */ - if(isspace(ha_bufchar(buf))) - { - /* Skip all the spaces */ - while(ha_buflen(buf) > 0 && isspace(ha_bufchar(buf))) - ha_bufeat(buf); + for(;;) + { + /* Make sure we have more data */ + if(!more) + break; - /* An empty line is the end of the headers - even if that line has spaces on it */ - if(ha_buflen(buf) == 0) - break; + r = ha_bufreadline(ifd, rq->buf); + if(r == -1) + return -1; - /* A header that has data on it but started - with a space continues the previous header */ - if(valid && i > 0) - { - t = ha_bufparseline(buf, 0); - if(t) - { - char* t2 = (char*)req->headers[i - 1].data + strlen(req->headers[i - 1].data); - - /* Fill the area between the end of the last - valid header and this with spaces */ - memset(t2, ' ', t - t2); - } - } - } - else - { - if(i < HA_MAX_HEADERS) - { - t = ha_bufparseword(buf, ":"); + /* Check if this is the last line */ + if(r == 0) + more = 0; - if(t) - { - for(head = cmd->headers; ; head++) - { - if(!(*head)) - { - t = NULL; + /* An empty line is the end of the headers */ + if(ha_buflen(rq->buf) == 0) break; - } - if(strcasecmp(t, *head) == 0) - break; + /* Check if the header starts with a space */ + if(isspace(ha_bufchar(rq->buf))) + { + /* Skip all the spaces */ + while(ha_buflen(rq->buf) > 0 && isspace(ha_bufchar(rq->buf))) + ha_bufeat(rq->buf); + + /* An empty line is the end of the headers + even if that line has spaces on it */ + if(ha_buflen(rq->buf) == 0) + break; + + /* A header that has data on it but started + with a space continues the previous header */ + if(valid && i > 0) + { + t = ha_bufparseline(rq->buf, 0); + if(t) + { + char* t2 = (char*)rq->req_headers[i - 1].data + strlen(rq->req_headers[i - 1].data); + + /* Fill the area between the end of the last + valid header and this with spaces */ + memset(t2, ' ', t - t2); + } + } + } + else + { + if(i < HA_MAX_HEADERS) + { + t = ha_bufparseword(rq->buf, ":"); + + if(t) + { + for(head = cmd->headers; ; head++) + { + if(!(*head)) + { + t = NULL; + break; + } + + if(strcasecmp(t, *head) == 0) + break; + } + } + + if(t) + { + rq->req_headers[i].name = t; + rq->req_headers[i].data = ha_bufparseline(rq->buf, 1); + i++; + } + + valid = (t != NULL) ? 1 : 0; + } } - } - - if(t) - { - req->headers[i].name = t; - req->headers[i].data = ha_bufparseline(buf, 1); - i++; - } - valid = (t != NULL) ? 1 : 0; + ha_bufskip(rq->buf); } - } - - ha_bufskip(buf); } - } - return more; + return more; } -static int write_data(int ofd, const char* data) +static int write_data(ha_request_t* rq, int ofd, const char* data) { - int r; + int r; - ASSERT(data); - ASSERT(ofd != -1); + ASSERT(data); + ASSERT(ofd != -1); - while(*data != 0) - { - r = write(ofd, data, strlen(data)); + while(*data != 0) + { + r = write(ofd, data, strlen(data)); - if(r > 0) - data += r; + if(r > 0) + data += r; - else if(r == -1) - { - if(errno == EAGAIN) - continue; + else if(r == -1) + { + if(errno == EAGAIN) + continue; - /* The other end closed. no message */ - if(errno != EPIPE) - ha_message(LOG_ERR, "couldn't write data"); + /* The other end closed. no message */ + if(errno != EPIPE) + ha_message(rq, LOG_ERR, "couldn't write data"); - return HA_CRITERROR; + return HA_CRITERROR; + } } - } - return 0; + return 0; } -static int httpauth_respond(int ofd, int scode, int ccode, const char* msg) +static int httpauth_respond(ha_request_t* rq, int ofd, int scode, int ccode, const char* msg) { - char num[16]; + char num[16]; - ASSERT(ofd != -1); - ASSERT(scode > 99 && scode < 1000); - ASSERT(ccode == 0 || (ccode > 99 && ccode < 1000)); + ASSERT(ofd != -1); + ASSERT(scode > 99 && scode < 1000); + ASSERT(ccode == 0 || (ccode > 99 && ccode < 1000)); - /* Can only have a client code when server code is 200 */ - ASSERT(ccode == 0 || scode == HA_SERVER_OK); + /* Can only have a client code when server code is 200 */ + ASSERT(ccode == 0 || scode == HA_SERVER_OK); - sprintf(num, "%d ", scode); + sprintf(num, "%d ", scode); - if(write_data(ofd, num) < 0) - return HA_CRITERROR; + if(write_data(rq, ofd, num) < 0) + return HA_CRITERROR; - if(ccode != 0) - { - sprintf(num, "%d ", ccode); + if(ccode != 0) + { + sprintf(num, "%d ", ccode); - if(write_data(ofd, num) < 0) - return HA_CRITERROR; - } + if(write_data(rq, ofd, num) < 0) + return HA_CRITERROR; + } - if(!msg) - { - switch(scode) + if(!msg) { - case HA_SERVER_ACCEPTED: - msg = "Accepted"; - break; - case HA_SERVER_ERROR: - msg = "Internal Error "; - break; - case HA_SERVER_BADREQ: - msg = "Bad Request "; - break; - case HA_SERVER_DECLINE: - msg = "Unauthorized "; - break; - default: - msg = NULL; - break; - }; - } + switch(scode) + { + case HA_SERVER_ACCEPTED: + msg = "Accepted"; + break; + case HA_SERVER_ERROR: + msg = "Internal Error "; + break; + case HA_SERVER_BADREQ: + msg = "Bad Request "; + break; + case HA_SERVER_DECLINE: + msg = "Unauthorized "; + break; + default: + msg = NULL; + break; + }; + } - if(msg && write_data(ofd, msg) < 0) - return HA_CRITERROR; + if(msg && write_data(rq, ofd, msg) < 0) + return HA_CRITERROR; - /* When the client code is 0, then caller should log */ - if(ccode == 0) - log_respcode(scode, msg, ofd); + /* When the client code is 0, then caller should log */ + if(ccode == 0) + log_respcode(rq, scode, msg); - return write_data(ofd, "\n"); + return write_data(rq, ofd, "\n"); } const char kHeaderDelimiter[] = ": "; -static int httpauth_write(int ofd, ha_response_t* resp) +static int httpauth_write(ha_request_t* rq, int ofd) { - int i; - int wrote = 0; + int i; + int wrote = 0; - ASSERT(ofd != -1); - ASSERT(resp); + ASSERT(ofd != -1); + ASSERT(rq); - if(httpauth_respond(ofd, HA_SERVER_OK, resp->code, resp->detail) < 0) - return HA_CRITERROR; + if(httpauth_respond(rq, ofd, HA_SERVER_OK, rq->resp_code, rq->resp_detail) < 0) + return HA_CRITERROR; - for(i = 0; i < HA_MAX_HEADERS; i++) - { - if(resp->headers[i].name) + for(i = 0; i < HA_MAX_HEADERS; i++) { - if(write_data(ofd, resp->headers[i].name) == -1 || - write_data(ofd, kHeaderDelimiter) == -1 || - write_data(ofd, resp->headers[i].data) == -1 || - write_data(ofd, "\n") == -1) - return -1; + if(rq->resp_headers[i].name) + { + if(write_data(rq, ofd, rq->resp_headers[i].name) == -1 || + write_data(rq, ofd, kHeaderDelimiter) == -1 || + write_data(rq, ofd, rq->resp_headers[i].data) == -1 || + write_data(rq, ofd, "\n") == -1) + return -1; - wrote = 1; + wrote = 1; + } } - } - if(write_data(ofd, "\n") == -1) - return -1; + if(write_data(rq, ofd, "\n") == -1) + return -1; - log_response(resp, ofd); + log_response(rq); - return 0; + return 0; } -static int httpauth_error(int ofd, int r) +static int httpauth_error(ha_request_t* rq, int ofd, int r) { - int scode = 0; - const char* msg = NULL; + int scode = 0; + const char* msg = NULL; - ASSERT(r < 0); + ASSERT(r < 0); - switch(r) - { - case HA_BADREQ: - scode = HA_SERVER_BADREQ; - break; + switch(r) + { + case HA_BADREQ: + scode = HA_SERVER_BADREQ; + break; - case HA_CRITERROR: - msg = "Critical Error"; - /* fall through */ + case HA_CRITERROR: + msg = "Critical Error"; + /* fall through */ - case HA_FAILED: - scode = HA_SERVER_ERROR; - break; + case HA_FAILED: + scode = HA_SERVER_ERROR; + break; - default: - ASSERT(0 && "invalid error code"); - break; - } + default: + ASSERT(0 && "invalid error code"); + break; + }; - return httpauth_respond(ofd, scode, 0, msg); + return httpauth_respond(rq, ofd, scode, 0, msg); } -static int httpauth_ready(int ofd, ha_buffer_t* buf) +static int httpauth_ready(ha_request_t* rq, int ofd) { - const char* t; - httpauth_loaded_t* h; + const char* t; + httpauth_loaded_t* h; - ASSERT(ofd != -1); - ASSERT(buf); + ASSERT(ofd != -1); + ASSERT(rq); - /* We send a ready banner to our client */ + /* We send a ready banner to our client */ - if(ha_buferr(buf)) - return httpauth_error(ofd, HA_CRITERROR); - - else - return httpauth_respond(ofd, HA_SERVER_READY, 0, "HTTPAUTH/1.0"); + if(ha_buferr(rq->buf)) + return httpauth_error(rq, ofd, HA_CRITERROR); + else + return httpauth_respond(rq, ofd, HA_SERVER_READY, 0, "HTTPAUTH/1.0"); } -static int httpauth_auth(int ofd, ha_request_t* req, ha_response_t* resp) +static int httpauth_auth(ha_request_t* rq, int ofd) { - int r; - - ASSERT(req && resp); - - if(!req->context) - { - ha_messagex(LOG_ERR, "no auth handler set"); - return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "No Auth Handler Set"); - } - - /* Clear out our response */ - resp->code = -1; - resp->detail = NULL; - memset(resp->headers, 0, sizeof(resp->headers)); - ASSERT(resp->buf != NULL); - - /* Check our connection argument */ - if(!req->args[AUTH_ARG_CONN] || !(req->args[AUTH_ARG_CONN][0])) - { - ha_messagex(LOG_ERR, "missing connection ID in request"); - return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing Connection ID"); - } - - /* Check our uri argument */ - if(!req->args[AUTH_ARG_URI] || !(req->args[AUTH_ARG_URI][0])) - { - ha_messagex(LOG_ERR, "missing URI in request"); - return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing URI"); - } - - /* Check our connection arguments */ - if(!req->args[AUTH_ARG_METHOD] || !(req->args[AUTH_ARG_METHOD][0])) - { - ha_messagex(LOG_ERR, "missing HTTP method in request"); - return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing HTTP Method"); - } - - ASSERT(req->context->handler && req->context->handler->f_process); - r = (req->context->handler->f_process)(req, resp); - if(r < 0) - return r; - - if(httpauth_write(ofd, resp) < 0) - return HA_CRITERROR; - - return HA_OK; + int r; + + ASSERT(rq); + + if(!rq->context) + { + ha_messagex(rq, LOG_ERR, "no auth handler set"); + return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "No Auth Handler Set"); + } + + /* Clear out our response */ + rq->resp_code = -1; + rq->resp_detail = NULL; + memset(rq->resp_headers, 0, sizeof(rq->resp_headers)); + + /* Check our connection argument */ + if(!rq->req_args[AUTH_ARG_CONN] || !(rq->req_args[AUTH_ARG_CONN][0])) + { + ha_messagex(rq, LOG_ERR, "missing connection ID in request"); + return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing Connection ID"); + } + + /* Check our uri argument */ + if(!rq->req_args[AUTH_ARG_URI] || !(rq->req_args[AUTH_ARG_URI][0])) + { + ha_messagex(rq, LOG_ERR, "missing URI in request"); + return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing URI"); + } + + /* Check our connection arguments */ + if(!rq->req_args[AUTH_ARG_METHOD] || !(rq->req_args[AUTH_ARG_METHOD][0])) + { + ha_messagex(rq, LOG_ERR, "missing HTTP method in request"); + return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing HTTP Method"); + } + + ASSERT(rq->context->handler && rq->context->handler->f_process); + r = (rq->context->handler->f_process)(rq); + if(r < 0) + return r; + + if(httpauth_write(rq, ofd) < 0) + return HA_CRITERROR; + + return HA_OK; } -static int httpauth_set(int ofd, ha_request_t* req) +static int httpauth_set(ha_request_t* rq, int ofd) { - httpauth_loaded_t* h; - const char* name = req->args[0]; - const char* value = req->args[1]; - - ASSERT(req); - - /* Check our name argument */ - if(!name || !*name) - { - ha_messagex(LOG_ERR, "missing name in SET request"); - return HA_BADREQ; - } - - if(strcasecmp(name, "Domain") == 0) - { - req->digest_domain = value ? value : ""; - } - - else if(strcasecmp(name, "Handler") == 0) - { - if(!value || !*value) + httpauth_loaded_t* h; + const char* name = rq->req_args[0]; + const char* value = rq->req_args[1]; + + /* Check our name argument */ + if(!name || !*name) { - ha_messagex(LOG_ERR, "no auth handler specified in SET request."); - return HA_BADREQ; + ha_messagex(rq, LOG_ERR, "missing name in SET request"); + return HA_BADREQ; } - /* Find a handler for this type */ - for(h = g_handlers; h; h = h->next) + if(strcasecmp(name, "Domain") == 0) { - if(strcasecmp(h->ctx.name, value) == 0) - { - req->context = &(h->ctx); - value = NULL; - break; - } + rq->digest_domain = value ? value : ""; } - if(value != NULL) + else if(strcasecmp(name, "Handler") == 0) { - ha_messagex(LOG_ERR, "unknown authentication type: %s", req->args[0]); - return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Handler"); + if(!value || !*value) + { + ha_messagex(rq, LOG_ERR, "no auth handler specified in SET request."); + return HA_BADREQ; + } + + /* Find a handler for this type */ + for(h = g_handlers; h; h = h->next) + { + if(strcasecmp(h->ctx.name, value) == 0) + { + rq->context = &(h->ctx); + value = NULL; + break; + } + } + + if(value != NULL) + { + ha_messagex(rq, LOG_ERR, "unknown authentication type: %s", rq->req_args[0]); + return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Handler"); + } } - } - else - { - ha_messagex(LOG_ERR, "bad option in SET request"); - return HA_BADREQ; - } + else + { + ha_messagex(rq, LOG_ERR, "bad option in SET request"); + return HA_BADREQ; + } - return httpauth_respond(ofd, HA_SERVER_ACCEPTED, 0, NULL); + return httpauth_respond(rq, ofd, HA_SERVER_ACCEPTED, 0, NULL); } static int httpauth_processor(int ifd, int ofd) { - ha_buffer_t buf; - ha_request_t req; - ha_response_t resp; - int result = -1; - int r; + ha_buffer_t buf; + ha_request_t rq; + int result = -1; + int r; - ASSERT(ifd != -1); - ASSERT(ofd != -1); + ASSERT(ifd != -1); + ASSERT(ofd != -1); - /* Initialize the memory buffers */ - ha_bufinit(&buf); + /* Initialize the memory buffers */ + ha_bufinit(&buf); - memset(&req, 0, sizeof(req)); - memset(&resp, 0, sizeof(resp)); + memset(&rq, 0, sizeof(rq)); - /* Set up some context stuff */ - req.digest_domain = ""; - req.buf = &buf; - resp.buf = &buf; + /* Set up some context stuff */ + rq.digest_domain = ""; + rq.buf = &buf; - if(httpauth_ready(ofd, &buf) == -1) - { - result = 1; - goto finally; - } + if(httpauth_ready(&rq, ofd) == -1) + { + result = 1; + goto finally; + } - /* Now loop and handle the commands */ - while(result == -1) - { - ha_bufreset(&buf); + /* Now loop and handle the commands */ + while(result == -1) + { + ha_bufreset(&buf); - r = httpauth_read(ifd, &req, &buf); + r = httpauth_read(&rq, ifd); - if(ha_buferr(&buf)) - r = HA_CRITERROR; + if(ha_buferr(&buf)) + r = HA_CRITERROR; - if(r < 0) - { - httpauth_error(ofd, r); - result = 1; - break; - } + if(r < 0) + { + httpauth_error(&rq, ofd, r); + result = 1; + break; + } - log_request(&req, &buf, ifd); + log_request(&rq); - if(r == 0) - result = 0; + if(r == 0) + result = 0; - switch(req.type) - { - case REQTYPE_AUTH: - r = httpauth_auth(ofd, &req, &resp); - break; + switch(rq.req_type) + { + case REQTYPE_AUTH: + r = httpauth_auth(&rq, ofd); + break; - case REQTYPE_SET: - r = httpauth_set(ofd, &req); - break; + case REQTYPE_SET: + r = httpauth_set(&rq, ofd); + break; - case REQTYPE_QUIT: - r = HA_OK; - result = 0; - break; + case REQTYPE_QUIT: + r = HA_OK; + result = 0; + break; - case REQTYPE_IGNORE: - r = HA_FALSE; - break; + case REQTYPE_IGNORE: + r = HA_FALSE; + break; - default: - ha_messagex(LOG_WARNING, "%d: received unknown command from client", ifd); - r = httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Unknown command"); - break; - }; + default: + ha_messagex(&rq, LOG_WARNING, "received unknown command from client"); + r = httpauth_respond(&rq, ofd, HA_SERVER_BADREQ, 0, "Unknown command"); + break; + }; - if(ha_buferr(&buf)) - r = HA_CRITERROR; + if(ha_buferr(&buf)) + r = HA_CRITERROR; - if(r < 0) - { - httpauth_error(ofd, r); + if(r < 0) + { + httpauth_error(&rq, ofd, r); - if(r == HA_CRITERROR) - result = 1; + if(r == HA_CRITERROR) + result = 1; + } } - } - if(ifd == ofd) - shutdown(ofd, SHUT_RDWR); - else - close(ofd); + if(ifd == ofd) + { + shutdown(ofd, SHUT_RDWR); + close(ofd); + } + else + { + close(ifd); + close(ofd); + } finally: - ha_buffree(&buf); - - return result; + ha_buffree(&buf); + return result; } /* ----------------------------------------------------------------------- @@ -1129,335 +1122,335 @@ finally: */ static ha_context_t* config_addhandler(ha_buffer_t* buf, const char* alias, - ha_handler_t* handler, const ha_context_t* defaults) + ha_handler_t* handler, const ha_context_t* defaults) { - httpauth_loaded_t* loaded; - int len; + httpauth_loaded_t* loaded; + int len; - ASSERT(buf && alias && handler && defaults); + ASSERT(buf && alias && handler && defaults); - len = sizeof(httpauth_loaded_t) + handler->context_size; + len = sizeof(httpauth_loaded_t) + handler->context_size; - loaded = (httpauth_loaded_t*)ha_bufmalloc(buf, len); - if(!loaded) - errx(1, "out of memory"); + loaded = (httpauth_loaded_t*)ha_bufmalloc(buf, len); + if(!loaded) + errx(1, "out of memory"); - memset(loaded, 0, len); + memset(loaded, 0, len); - /* Setup the options from the defaults */ - memcpy(&(loaded->ctx), defaults, sizeof(ha_context_t)); + /* Setup the options from the defaults */ + memcpy(&(loaded->ctx), defaults, sizeof(ha_context_t)); - if(handler->context_size) - { - void* mem = ((unsigned char*)(loaded)) + sizeof(httpauth_loaded_t); - - /* Initialize the defaults properly */ - if(handler->context_default) - memcpy(mem, handler->context_default, handler->context_size); + if(handler->context_size) + { + void* mem = ((unsigned char*)(loaded)) + sizeof(httpauth_loaded_t); - loaded->ctx.ctx_data = mem; - } + /* Initialize the defaults properly */ + if(handler->context_default) + memcpy(mem, handler->context_default, handler->context_size); - else - { - loaded->ctx.ctx_data = NULL; - } + loaded->ctx.ctx_data = mem; + } - loaded->ctx.name = (char*)alias; - loaded->ctx.handler = handler; + else + { + loaded->ctx.ctx_data = NULL; + } - if(!g_handlers) - { - g_handlers = loaded; - } - else - { - httpauth_loaded_t* l = g_handlers; + loaded->ctx.name = (char*)alias; + loaded->ctx.handler = handler; - for(;;) + if(!g_handlers) + { + g_handlers = loaded; + } + else { - if(strcasecmp(alias, l->ctx.name) == 0) - errx(1, "duplicate handler section for '%s'", alias); + httpauth_loaded_t* l = g_handlers; - if(!(l->next)) - break; + for(;;) + { + if(strcasecmp(alias, l->ctx.name) == 0) + errx(1, "duplicate handler section for '%s'", alias); - l = l->next; - } + if(!(l->next)) + break; - l->next = loaded; - } + l = l->next; + } - ha_messagex(LOG_DEBUG, "configuration: handler: %s (%s)", alias, handler->type); - return &(loaded->ctx); + l->next = loaded; + } + + ha_messagex(NULL, LOG_DEBUG, "configuration: handler: %s (%s)", alias, handler->type); + return &(loaded->ctx); } #define VALID_ALIAS_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_-." static int config_parse(const char* file, ha_buffer_t* buf) { - ha_context_t defaults; - ha_context_t* ctx = NULL; - int line = 0; - int fd; - char* t; - char* name; - char* value; - int more = 1; - int recog; - int r, i; - - ASSERT(file && buf); - - /* Open the configuration file */ - fd = open(file, O_RDONLY); - if(fd == -1) - err(1, "couldn't open configuration file: %s", file); - - /* These are the default options for the contexts */ - memset(&defaults, 0, sizeof(defaults)); - defaults.allowed_types = 0xFFFFFFFF; /* All types by default */ - defaults.cache_timeout = DEFAULT_TIMEOUT; /* Timeout for cache */ - defaults.cache_max = DEFAULT_CACHEMAX; - defaults.realm = ""; - - /* Read each line and process */ - while(more) - { - ha_bufskip(buf); - - if((more = ha_bufreadline(fd, buf)) == -1) - return -1; - - line++; - - /* Eat all white space at beginning of line */ - while(ha_buflen(buf) && isspace(ha_bufchar(buf))) - ha_bufeat(buf); - - /* Skip blank lines */ - if(ha_buflen(buf) == 0) - continue; - - /* Skip comment lines */ - if(ha_bufchar(buf) == '#') - continue; - - /* Check for a handler */ - if(ha_bufchar(buf) == '[') + ha_context_t defaults; + ha_context_t* ctx = NULL; + int line = 0; + int fd; + char* t; + char* name; + char* value; + int more = 1; + int recog; + int r, i; + + ASSERT(file && buf); + + /* Open the configuration file */ + fd = open(file, O_RDONLY); + if(fd == -1) + err(1, "couldn't open configuration file: %s", file); + + /* These are the default options for the contexts */ + memset(&defaults, 0, sizeof(defaults)); + defaults.allowed_types = 0xFFFFFFFF; /* All types by default */ + defaults.cache_timeout = DEFAULT_TIMEOUT; /* Timeout for cache */ + defaults.cache_max = DEFAULT_CACHEMAX; + defaults.realm = ""; + + /* Read each line and process */ + while(more) { - ha_handler_t* handler = NULL; - const char* x; + ha_bufskip(buf); - ha_bufeat(buf); - name = ha_bufparseline(buf, 1); + if((more = ha_bufreadline(fd, buf)) == -1) + return -1; - if(!name || name[strlen(name) - 1] != ']') - errx(1, "handler section invalid (line %d)", line); + line++; + /* Eat all white space at beginning of line */ + while(ha_buflen(buf) && isspace(ha_bufchar(buf))) + ha_bufeat(buf); - /* remove the bracket */ - name[strlen(name) - 1] = 0; + /* Skip blank lines */ + if(ha_buflen(buf) == 0) + continue; - /* - * Take out any colon found, past which would - * be an aliased name - */ - t = strchr(name, ':'); - if(t != NULL) - { - *t = 0; - t++; + /* Skip comment lines */ + if(ha_bufchar(buf) == '#') + continue; - /* Rid of whitespace on ends */ - t = trim_space(t); + /* Check for a handler */ + if(ha_bufchar(buf) == '[') + { + ha_handler_t* handler = NULL; + const char* x; - /* Validate the alias name */ - if(!*t || strspn(t, VALID_ALIAS_CHARS) != strlen(t)) - errx(1, "invalid name for handler: %s", t); - } + ha_bufeat(buf); + name = ha_bufparseline(buf, 1); - /* Rid of whitespace */ - name = trim_space(name); + if(!name || name[strlen(name) - 1] != ']') + errx(1, "handler section invalid (line %d)", line); - /* Look for a handler with this type */ - for(i = 0; i < countof(g_handlerlist); i++) - { - if(g_handlerlist[i] && g_handlerlist[i]->type && - strcasecmp(name, g_handlerlist[i]->type) == 0) - { - handler = g_handlerlist[i]; - break; - } - } - if(handler == NULL) - errx(1, "unknown handler type '%s' (line %d)", name, line); + /* remove the bracket */ + name[strlen(name) - 1] = 0; - /* If we had a last handler then add it to handlers */ - ctx = config_addhandler(buf, t ? t : name, handler, &defaults); + /* + * Take out any colon found, past which would + * be an aliased name + */ + t = strchr(name, ':'); + if(t != NULL) + { + *t = 0; + t++; - /* Rest doesn't apply to handler headers */ - continue; - } + /* Rid of whitespace on ends */ + t = trim_space(t); + /* Validate the alias name */ + if(!*t || strspn(t, VALID_ALIAS_CHARS) != strlen(t)) + errx(1, "invalid name for handler: %s", t); + } - /* Parse out the name */ - name = ha_bufparseword(buf, ":"); - if(!name || !name[0]) - errx(1, "configuration file invalid (line %d)", line); + /* Rid of whitespace */ + name = trim_space(name); - strlwr(name); + /* Look for a handler with this type */ + for(i = 0; i < countof(g_handlerlist); i++) + { + if(g_handlerlist[i] && g_handlerlist[i]->type && + strcasecmp(name, g_handlerlist[i]->type) == 0) + { + handler = g_handlerlist[i]; + break; + } + } - /* And get the rest of the line */ - value = ha_bufparseline(buf, 1); - if(value == NULL) - errx(1, "configuration missing value at (line %d)", line); + if(handler == NULL) + errx(1, "unknown handler type '%s' (line %d)", name, line); + /* If we had a last handler then add it to handlers */ + ctx = config_addhandler(buf, t ? t : name, handler, &defaults); - recog = 0; + /* Rest doesn't apply to handler headers */ + continue; + } - /* Is this the global section? */ - if(!ctx) - { - /* Look and see if that's a name we want */ - if(strcmp("socket", name) == 0) - { - g_socket = value; - recog = 1; - } - - else if(strcmp("maxthreads", name) == 0) - { - if(ha_confint(name, value, 1, 256, &g_maxthreads) == -1) - exit(1); - recog = 1; - } - } - /* Otherwise we're in a handler */ - else - { - if(ctx->handler->f_config) - { - r = (ctx->handler->f_config)(ctx, name, value); - if(r < 0) - return r; + /* Parse out the name */ + name = ha_bufparseword(buf, ":"); + if(!name || !name[0]) + errx(1, "configuration file invalid (line %d)", line); - if(!recog && r == HA_OK) - recog = 1; - } - } + strlwr(name); - /* Options that are legal in both global and internal sections */ - if(!recog) - { - ha_context_t* opts = ctx ? ctx : &defaults; - ASSERT(opts); - - if(strcmp(name, "cachetimeout") == 0) - { - int v; - if(ha_confint(name, value, 0, 86400, &v) < 0) - exit(1); /* Message already printed */ - - opts->cache_timeout = v; - recog = 1; - } - - else if(strcmp(name, "cachemax") == 0) - { - int v; - if(ha_confint(name, value, 0, 0x7FFFFFFF, &v) < 0) - exit(1); /* Message already printed */ - - opts->cache_max = v; - recog = 1; - } - - else if(strcmp(name, "authtypes") == 0) - { - int types = 0; - char* t; - - strlwr(value); - - /* Split the line into tokens at the spaces */ - while(*value) - { - value = trim_space(value); - t = value; + /* And get the rest of the line */ + value = ha_bufparseline(buf, 1); + if(value == NULL) + errx(1, "configuration missing value at (line %d)", line); - while(*t && !isspace(*t)) - t++; - if(strncmp(value, "basic", 5) == 0) - types |= HA_TYPE_BASIC; + recog = 0; - else if(strncmp(value, "digest", 6) == 0) - types |= HA_TYPE_DIGEST; + /* Is this the global section? */ + if(!ctx) + { + /* Look and see if that's a name we want */ + if(strcmp("socket", name) == 0) + { + g_socket = value; + recog = 1; + } - else if(strncmp(value, "ntlm", 4) == 0) - types |= HA_TYPE_NTLM; + else if(strcmp("maxthreads", name) == 0) + { + if(ha_confint(name, value, 1, 256, &g_maxthreads) == -1) + exit(1); + recog = 1; + } + } - else - errx(1, "invalid type for '%s': %s (line %d)", name, value, line); + /* Otherwise we're in a handler */ + else + { + if(ctx->handler->f_config) + { + r = (ctx->handler->f_config)(ctx, name, value); + if(r < 0) + return r; - value = t; + if(!recog && r == HA_OK) + recog = 1; + } } - if(types == 0) - errx(1, "no authentication types for '%s' (line %d)", name, line); + /* Options that are legal in both global and internal sections */ + if(!recog) + { + ha_context_t* opts = ctx ? ctx : &defaults; + ASSERT(opts); - opts->allowed_types = types; - recog = 1; - } + if(strcmp(name, "cachetimeout") == 0) + { + int v; + if(ha_confint(name, value, 0, 86400, &v) < 0) + exit(1); /* Message already printed */ - else if(strcmp(name, "realm") == 0) - { - opts->realm = value; - recog = 1; - } + opts->cache_timeout = v; + recog = 1; + } - else if(strcmp(name, "digestignoreuri") == 0) - { - int v; - if(ha_confbool(name, value, &v) < 0) - exit(1); /* Message already printed */ + else if(strcmp(name, "cachemax") == 0) + { + int v; + if(ha_confint(name, value, 0, 0x7FFFFFFF, &v) < 0) + exit(1); /* Message already printed */ - opts->digest_ignoreuri = v; - recog = 1; - } + opts->cache_max = v; + recog = 1; + } - else if(strcmp(name, "digestignorenc") == 0) - { - int v; - if(ha_confbool(name, value, &v) < 0) - exit(1); /* Message already printed */ + else if(strcmp(name, "authtypes") == 0) + { + int types = 0; + char* t; - opts->digest_ignorenc = v; - recog = 1; - } + strlwr(value); + + /* Split the line into tokens at the spaces */ + while(*value) + { + value = trim_space(value); + t = value; + + while(*t && !isspace(*t)) + t++; + + if(strncmp(value, "basic", 5) == 0) + types |= HA_TYPE_BASIC; + + else if(strncmp(value, "digest", 6) == 0) + types |= HA_TYPE_DIGEST; + + else if(strncmp(value, "ntlm", 4) == 0) + types |= HA_TYPE_NTLM; + + else + errx(1, "invalid type for '%s': %s (line %d)", name, value, line); + + value = t; + } + + if(types == 0) + errx(1, "no authentication types for '%s' (line %d)", name, line); + + opts->allowed_types = types; + recog = 1; + } + + else if(strcmp(name, "realm") == 0) + { + opts->realm = value; + recog = 1; + } + + else if(strcmp(name, "digestignoreuri") == 0) + { + int v; + if(ha_confbool(name, value, &v) < 0) + exit(1); /* Message already printed */ + + opts->digest_ignoreuri = v; + recog = 1; + } + + else if(strcmp(name, "digestignorenc") == 0) + { + int v; + if(ha_confbool(name, value, &v) < 0) + exit(1); /* Message already printed */ + + opts->digest_ignorenc = v; + recog = 1; + } #ifdef _DEBUG - else if(strcmp(name, "digestdebugnonce") == 0) - { - opts->digest_debugnonce = value; - recog = 1; - } + else if(strcmp(name, "digestdebugnonce") == 0) + { + opts->digest_debugnonce = value; + recog = 1; + } #endif - } + } - if(!recog) - errx(1, "unrecognized configuration setting '%s' (line %d)", name, line); - else - ha_messagex(LOG_DEBUG, "configuration: setting: [ %s: %s ]", name, value); - } + if(!recog) + errx(1, "unrecognized configuration setting '%s' (line %d)", name, line); + else + ha_messagex(NULL, LOG_DEBUG, "configuration: setting: [ %s: %s ]", name, value); + } - if(!g_handlers) - ha_messagex(LOG_WARNING, "configuration: no handlers found in configuration file"); + if(!g_handlers) + ha_messagex(NULL, LOG_WARNING, "configuration: no handlers found in configuration file"); - return 0; + return 0; } |