From fea460a66ad21b1de75b3872e5c66c381a69d743 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 24 Jun 2006 10:06:24 +0000 Subject: [PATCH] - Harden authentication failure in FD by single threading errors and forcing a 6 second wait. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3068 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kes-1.39 | 2 + bacula/src/filed/authenticate.c | 80 +++++++++++++++++++-------------- bacula/src/version.h | 4 +- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/bacula/kes-1.39 b/bacula/kes-1.39 index 750b5d8616..cdde06eaaf 100644 --- a/bacula/kes-1.39 +++ b/bacula/kes-1.39 @@ -3,6 +3,8 @@ General: 24Jun06 +- Harden authentication failure in FD by single threading errors + and forcing a 6 second wait. - ========= Remove Accept Any Volume ========= directive. - Major cleanup and simplification of regress using shell functions (more tests to be converted to new format) diff --git a/bacula/src/filed/authenticate.c b/bacula/src/filed/authenticate.c index c1165a3d1b..ddd12b02d7 100644 --- a/bacula/src/filed/authenticate.c +++ b/bacula/src/filed/authenticate.c @@ -26,47 +26,46 @@ static char OK_hello[] = "2000 OK Hello\n"; static char Dir_sorry[] = "2999 No go\n"; - +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /********************************************************************* * */ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) { - POOLMEM *dirname; - DIRRES *director; + POOLMEM *dirname = get_pool_memory(PM_MESSAGE); + DIRRES *director = NULL; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool auth_success = false; alist *verify_list = NULL; + btimer_t *tid = NULL; if (rcode != R_DIRECTOR) { Dmsg1(50, "I only authenticate directors, not %d\n", rcode); Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode); - return 0; + goto auth_fatal; } if (bs->msglen < 25 || bs->msglen > 200) { Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n", bs->who, bs->msglen); - char addr[64]; - char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; + char addr[64]; + char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"), - who, bs->msglen); - return 0; + who, bs->msglen); + goto auth_fatal; } - dirname = get_pool_memory(PM_MESSAGE); dirname = check_pool_memory_size(dirname, bs->msglen); if (sscanf(bs->msg, "Hello Director %s calling\n", dirname) != 1) { char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; - free_pool_memory(dirname); bs->msg[100] = 0; Dmsg2(50, "Bad Hello command from Director at %s: %s\n", bs->who, bs->msg); Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), - who, bs->msg); - return 0; + who, bs->msg); + goto auth_fatal; } unbash_spaces(dirname); LockRes(); @@ -79,9 +78,8 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), - dirname, who); - free_pool_memory(dirname); - return 0; + dirname, who); + goto auth_fatal; } if (have_tls) { @@ -99,14 +97,14 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) } } - btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT); + tid = start_bsock_timer(bs, AUTH_TIMEOUT); auth_success = cram_md5_auth(bs, director->password, tls_local_need); if (auth_success) { auth_success = cram_md5_get_auth(bs, director->password, &tls_remote_need); if (!auth_success) { - char addr[64]; - char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; - Dmsg1(50, "cram_get_auth failed for %s\n", who); + char addr[64]; + char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr; + Dmsg1(50, "cram_get_auth failed for %s\n", who); } } else { char addr[64]; @@ -115,23 +113,22 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) } if (!auth_success) { Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"), - bs->who); - director = NULL; + bs->who); goto auth_fatal; } /* Verify that the remote host is willing to meet our TLS requirements */ if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" - " advertise required TLS support.\n")); - director = NULL; + " advertize required TLS support.\n")); + auth_success = false; goto auth_fatal; } /* Verify that we are willing to meet the remote host's requirements */ if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); - director = NULL; + auth_success = false; goto auth_fatal; } @@ -140,16 +137,25 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) { Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n")); - director = NULL; + auth_success = false; goto auth_fatal; } } } auth_fatal: - stop_bsock_timer(tid); + if (tid) { + stop_bsock_timer(tid); + tid = NULL; + } free_pool_memory(dirname); jcr->director = director; + /* Single thread all failures to avoid DOS */ + if (auth_success) { + P(mutex); + bmicrosleep(6, 0); + V(mutex); + } return (director != NULL); } @@ -166,9 +172,12 @@ int authenticate_director(JCR *jcr) BSOCK *dir = jcr->dir_bsock; if (!authenticate(R_DIRECTOR, dir, jcr)) { + /* Single thread all failures to avoid DOS */ + P(mutex); + bmicrosleep(6, 0); + V(mutex); bnet_fsend(dir, "%s", Dir_sorry); Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n")); - bmicrosleep(5, 0); return 0; } return bnet_fsend(dir, "%s", OK_hello); @@ -185,18 +194,17 @@ int authenticate_storagedaemon(JCR *jcr) int tls_remote_need = BNET_TLS_NONE; bool auth_success = false; -#ifdef HAVE_TLS + btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT); + /* TLS Requirement */ - if (me->tls_enable) { + if (have_tls && me->tls_enable) { if (me->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } -#endif /* HAVE_TLS */ - btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT); auth_success = cram_md5_get_auth(sd, jcr->sd_auth_key, &tls_remote_need); if (!auth_success) { Dmsg1(50, "cram_get_auth failed for %s\n", sd->who); @@ -231,8 +239,7 @@ int authenticate_storagedaemon(JCR *jcr) goto auth_fatal; } -#ifdef HAVE_TLS - if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { + if (have_tls && tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(me->tls_ctx, sd)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); @@ -240,9 +247,14 @@ int authenticate_storagedaemon(JCR *jcr) goto auth_fatal; } } -#endif /* HAVE_TLS */ auth_fatal: stop_bsock_timer(tid); + /* Single thread all failures to avoid DOS */ + if (!auth_success) { + P(mutex); + bmicrosleep(6, 0); + V(mutex); + } return auth_success; } diff --git a/bacula/src/version.h b/bacula/src/version.h index 8a5db7555e..13fb7a8d85 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "1.39.14" -#define BDATE "22 June 2006" -#define LSMDATE "22Jun06" +#define BDATE "24 June 2006" +#define LSMDATE "24Jun06" /* Debug flags */ #undef DEBUG -- 2.39.5