/* * Authenticate Director */ static int authenticate_director(JCR *jcr) { const MONITORRES *monitor = MonitorItemThread::instance()->getMonitor(); BSOCK *dir = jcr->dir_bsock; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool compatible = true; char bashed_name[MAX_NAME_LENGTH]; char *password; bstrncpy(bashed_name, monitor->hdr.name, sizeof(bashed_name)); bash_spaces(bashed_name); password = monitor->password; /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(dir, 60 * 5); dir->fsend(DIRhello, bashed_name); if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) || !cram_md5_challenge(dir, password, tls_local_need, compatible)) { stop_bsock_timer(tid); Jmsg1(jcr, M_FATAL, 0, _("Director authorization problem.\n" "Most likely the passwords do not agree.\n" "Please see %s for help.\n"), MANUAL_AUTH_URL); return 0; } Dmsg1(6, ">dird: %s", dir->msg); if (dir->recv() <= 0) { stop_bsock_timer(tid); Jmsg1(jcr, M_FATAL, 0, _("Bad response to Hello command: ERR=%s\n"), dir->bstrerror()); return 0; } Dmsg1(10, "<dird: %s", dir->msg); stop_bsock_timer(tid); if (strncmp(dir->msg, DIROKhello, sizeof(DIROKhello)-1) != 0) { Jmsg0(jcr, M_FATAL, 0, _("Director rejected Hello command\n")); return 0; } else { Jmsg0(jcr, M_INFO, 0, dir->msg); } return 1; }
/* * Authenticate File daemon connection */ static int authenticate_file_daemon(JCR *jcr, CLIENTRES* client) { const MONITORRES *monitor = MonitorItemThread::instance()->getMonitor(); BSOCK *fd = jcr->file_bsock; char dirname[MAX_NAME_LENGTH]; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool compatible = true; /* * Send my name to the File daemon then do authentication */ bstrncpy(dirname, monitor->hdr.name, sizeof(dirname)); bash_spaces(dirname); /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(fd, 60 * 5); if (!fd->fsend(SDFDhello, dirname)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd)); return 0; } if (!cram_md5_respond(fd, client->password, &tls_remote_need, &compatible) || !cram_md5_challenge(fd, client->password, tls_local_need, compatible)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n" "Please see " MANUAL_AUTH_URL " for help.\n")); return 0; } Dmsg1(116, ">filed: %s", fd->msg); if (fd->recv() <= 0) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon to Hello command: ERR=%s\n"), fd->bstrerror()); return 0; } Dmsg1(110, "<stored: %s", fd->msg); stop_bsock_timer(tid); if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)-1) != 0) { Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Hello command\n")); return 0; } return 1; }
/* * Authenticate Storage daemon connection */ int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store) { BSOCK *sd = jcr->store_bsock; char dirname[MAX_NAME_LENGTH]; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; int compatible = true; /* * Send my name to the Storage daemon then do authentication */ bstrncpy(dirname, monitor->hdr.name, sizeof(dirname)); bash_spaces(dirname); /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(sd, 60 * 5); if (!sd->fsend(SDFDhello, dirname)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), sd->bstrerror()); return 0; } if (!cram_md5_respond(sd, store->password, &tls_remote_need, &compatible) || !cram_md5_challenge(sd, store->password, tls_local_need, compatible)) { stop_bsock_timer(tid); Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n" "Please see " MANUAL_AUTH_URL " for help.\n")); return 0; } Dmsg1(116, ">stored: %s", sd->msg); if (sd->recv() <= 0) { stop_bsock_timer(tid); Jmsg1(jcr, M_FATAL, 0, _("bdird<stored: bad response to Hello command: ERR=%s\n"), sd->bstrerror()); return 0; } Dmsg1(110, "<stored: %s", sd->msg); stop_bsock_timer(tid); if (strncmp(sd->msg, SDOKhello, sizeof(SDOKhello)) != 0) { Jmsg0(jcr, M_FATAL, 0, _("Storage daemon rejected Hello command\n")); return 0; } return 1; }
/* * See who is connecting and lookup the authentication information. * First make him prove his identity and then prove our identity to the Remote daemon. */ static inline bool two_way_authenticate(int rcode, BSOCK *bs, JCR* jcr) { 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 compatible = true; /* Want md5 compatible DIR */ bool auth_success = false; alist *verify_list = NULL; btimer_t *tid = NULL; if (rcode != R_DIRECTOR) { Dmsg1(dbglvl, "I only authenticate directors, not %d\n", rcode); Jmsg1(jcr, M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode); goto auth_fatal; } if (bs->msglen < 25 || bs->msglen > 500) { Dmsg2(dbglvl, "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; Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"), who, bs->msglen); goto auth_fatal; } dirname = check_pool_memory_size(dirname, bs->msglen); if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) { char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr; bs->msg[100] = 0; Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n", bs->who(), bs->msg); Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), who, bs->msg); goto auth_fatal; } unbash_spaces(dirname); foreach_res(director, R_DIRECTOR) { if (bstrcmp(director->hdr.name, dirname)) break; } if (!director) { char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr; Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), dirname, who); goto auth_fatal; } if (have_tls) { /* * TLS Requirement */ if (director->tls_enable) { if (director->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (director->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (director->tls_verify_peer) { verify_list = director->tls_allowed_cns; } } /* * Timeout Hello after 10 min */ tid = start_bsock_timer(bs, AUTH_TIMEOUT); /* * Sanity check. */ ASSERT(director->password.encoding == p_encoding_md5); /* * Challenge the director */ auth_success = cram_md5_challenge(bs, director->password.value, tls_local_need, compatible); if (job_canceled(jcr)) { auth_success = false; goto auth_fatal; /* quick exit */ } if (auth_success) { auth_success = cram_md5_respond(bs, director->password.value, &tls_remote_need, &compatible); if (!auth_success) { char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr; Dmsg1(dbglvl, "cram_get_auth failed for %s\n", who); } } else { char addr[64]; char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr; Dmsg1(dbglvl, "cram_auth failed for %s\n", who); } if (!auth_success) { Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"), 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) { Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* * Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) { Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); auth_success = false; goto auth_fatal; } if (director->tls_authenticate) { /* authentication only? */ bs->free_tls(); /* shutodown tls */ } } auth_fatal: 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 auth_success; }
/* * First prove our identity to the Remote daemon and then make him prove his identity. */ static inline bool two_way_authenticate(BSOCK *bs, JCR *jcr, bool initiate, const char *what) { int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool compatible = true; bool auth_success = false; alist *verify_list = NULL; btimer_t *tid = NULL; /* * TLS Requirement */ if (have_tls && me->tls_enable) { if (me->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (me->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (job_canceled(jcr)) { auth_success = false; /* force quick exit */ goto auth_fatal; } /* * Timeout Hello after 10 min */ tid = start_bsock_timer(bs, AUTH_TIMEOUT); /* * See if we initiate the challenge or respond to a challenge. */ if (initiate) { /* * Challenge SD */ auth_success = cram_md5_challenge(bs, jcr->sd_auth_key, tls_local_need, compatible); if (auth_success) { /* * Respond to his challenge */ auth_success = cram_md5_respond(bs, jcr->sd_auth_key, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "Respond cram-get-auth failed with %s\n", bs->who()); } } else { Dmsg1(dbglvl, "Challenge cram-auth failed with %s\n", bs->who()); } } else { /* * Respond to challenge */ auth_success = cram_md5_respond(bs, jcr->sd_auth_key, &tls_remote_need, &compatible); if (job_canceled(jcr)) { auth_success = false; /* force quick exit */ goto auth_fatal; } if (!auth_success) { Dmsg1(dbglvl, "cram_respond failed for %s\n", bs->who()); } else { /* * Challenge SD. */ auth_success = cram_md5_challenge(bs, jcr->sd_auth_key, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_challenge failed for %s\n", bs->who()); } } } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by %s daemon.\n" "Please see %s for help.\n"), what, MANUAL_AUTH_URL); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* * See if we are handshaking a passive client connection. */ if (initiate) { verify_list = me->tls_allowed_cns; } /* * Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(me->tls_ctx, bs, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); auth_success = false; goto auth_fatal; } if (me->tls_authenticate) { /* tls authentication only? */ bs->free_tls(); /* yes, shutdown tls */ } } auth_fatal: /* * Destroy session key */ memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); stop_bsock_timer(tid); /* * Single thread all failures to avoid DOS */ if (!auth_success) { P(mutex); bmicrosleep(6, 0); V(mutex); } return auth_success; }
/* * Authenticate Storage daemon connection */ bool authenticate_storage_daemon(JCR *jcr, STORERES *store) { BSOCK *sd = jcr->store_bsock; char dirname[MAX_NAME_LENGTH]; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; int compatible = true; bool auth_success = false; /* * Send my name to the Storage daemon then do authentication */ bstrncpy(dirname, director->hdr.name, sizeof(dirname)); bash_spaces(dirname); /* Timeout Hello after 1 min */ btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT); if (!sd->fsend(hello, dirname)) { stop_bsock_timer(tid); Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd)); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd)); return 0; } /* TLS Requirement */ if (store->tls_enable) { if (store->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (store->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible); if (auth_success) { auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who()); } } else { Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who()); } if (!auth_success) { stop_bsock_timer(tid); Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n")); Jmsg2(jcr, M_FATAL, 0, _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n" "Passwords or names not the same or\n" "Maximum Concurrent Jobs exceeded on the SD or\n" "SD networking messed up (restart daemon).\n" "Please see " MANUAL_AUTH_URL " for help.\n"), sd->host(), sd->port()); return 0; } /* 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) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n")); return 0; } /* 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) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); return 0; } /* Is TLS Enabled? */ if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(store->tls_ctx, sd, NULL)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"), sd->host(), sd->port()); return 0; } if (store->tls_authenticate) { /* authentication only? */ sd->free_tls(); /* yes, stop tls */ } } Dmsg1(116, ">stored: %s", sd->msg); if (sd->recv() <= 0) { stop_bsock_timer(tid); Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"), sd->who(), sd->host(), sd->bstrerror()); return 0; } Dmsg1(110, "<stored: %s", sd->msg); stop_bsock_timer(tid); if (!bstrncmp(sd->msg, OKhello, sizeof(OKhello))) { Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n")); Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"), sd->host(), sd->port()); return 0; } return 1; }
int authenticate_user_agent(UAContext *uac) { char name[MAX_NAME_LENGTH]; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool tls_authenticate; int compatible = true; CONRES *cons = NULL; BSOCK *ua = uac->UA_sock; bool auth_success = false; TLS_CONTEXT *tls_ctx = NULL; alist *verify_list = NULL; if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) { Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(), ua->host(), ua->port(), ua->msglen); return 0; } if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) { ua->msg[100] = 0; /* terminate string */ Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(), ua->host(), ua->port(), ua->msg); return 0; } name[sizeof(name)-1] = 0; /* terminate name */ if (bstrcmp(name, "*UserAgent*")) { /* default console */ /* TLS Requirement */ if (director->tls_enable) { if (director->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } tls_authenticate = director->tls_authenticate; if (tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (director->tls_verify_peer) { verify_list = director->tls_allowed_cns; } auth_success = cram_md5_challenge(ua, director->password, tls_local_need, compatible) && cram_md5_respond(ua, director->password, &tls_remote_need, &compatible); } else { unbash_spaces(name); cons = (CONRES *)GetResWithName(R_CONSOLE, name); if (cons) { /* TLS Requirement */ if (cons->tls_enable) { if (cons->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } tls_authenticate = cons->tls_authenticate; if (tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (cons->tls_verify_peer) { verify_list = cons->tls_allowed_cns; } auth_success = cram_md5_challenge(ua, cons->password, tls_local_need, compatible) && cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible); if (auth_success) { uac->cons = cons; /* save console resource pointer */ } } else { auth_success = false; goto auth_done; } } /* Verify that the remote peer 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 client did not advertise required TLS support.\n")); auth_success = false; goto auth_done; } /* Verify that we are willing to meet the peer'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 client requires TLS.\n")); auth_success = false; goto auth_done; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { if (cons) { tls_ctx = cons->tls_ctx; } else { tls_ctx = director->tls_ctx; } /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(tls_ctx, ua, verify_list)) { Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n")); auth_success = false; goto auth_done; } if (tls_authenticate) { /* authentication only? */ ua->free_tls(); /* stop tls */ } } /* Authorization Completed */ auth_done: if (!auth_success) { ua->fsend("%s", _(Dir_sorry)); Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"), name, ua->who(), ua->host(), ua->port()); sleep(5); return 0; } ua->fsend(_("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE); return 1; }
/* * Authenticate File daemon connection */ int authenticate_file_daemon(JCR *jcr) { BSOCK *fd = jcr->file_bsock; CLIENTRES *client = jcr->res.client; char dirname[MAX_NAME_LENGTH]; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; int compatible = true; bool auth_success = false; /* * Send my name to the File daemon then do authentication */ bstrncpy(dirname, director->name(), sizeof(dirname)); bash_spaces(dirname); /* Timeout Hello after 1 min */ btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT); if (!fd->fsend(hello, dirname)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"), fd->host(), fd->port(), fd->bstrerror()); return 0; } Dmsg1(dbglvl, "Sent: %s", fd->msg); /* TLS Requirement */ if (client->tls_enable) { if (client->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (client->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible); if (auth_success) { auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who()); } } else { Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who()); } if (!auth_success) { stop_bsock_timer(tid); Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n")); Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n" "Passwords or names not the same or\n" "Maximum Concurrent Jobs exceeded on the FD or\n" "FD networking messed up (restart daemon).\n" "Please see " MANUAL_AUTH_URL " for help.\n"), fd->host(), fd->port()); return 0; } /* 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) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"), fd->who(), fd->host()); return 0; } /* 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) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"), fd->host(), fd->port()); return 0; } /* Is TLS Enabled? */ if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"), fd->host(), fd->port()); return 0; } if (client->tls_authenticate) { /* tls authentication only? */ fd->free_tls(); /* yes, shutdown tls */ } } Dmsg1(116, ">filed: %s", fd->msg); if (fd->recv() <= 0) { stop_bsock_timer(tid); Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"), bnet_strerror(fd)); Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"), fd->host(), fd->port(), fd->bstrerror()); return 0; } Dmsg1(110, "<filed: %s", fd->msg); stop_bsock_timer(tid); jcr->FDVersion = 0; if (!bstrncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) && sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) { Dmsg0(dbglvl, _("File daemon rejected Hello command\n")); Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"), fd->host(), fd->port()); return 0; } return 1; }
/* * First prove our identity to the Storage daemon, then * make him prove his identity. */ int authenticate_storagedaemon(JCR *jcr) { BSOCK *sd = jcr->store_bsock; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; int compatible = true; bool auth_success = false; btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT); /* TLS Requirement */ if (have_tls && me->tls_enable) { if (me->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (me->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (job_canceled(jcr)) { auth_success = false; /* force quick exit */ goto auth_fatal; } /* Respond to SD challenge */ auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible); if (job_canceled(jcr)) { auth_success = false; /* force quick exit */ goto auth_fatal; } if (!auth_success) { Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who()); } else { /* Now challenge him */ auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who()); } } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n" "Please see " MANUAL_AUTH_URL " for help.\n")); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (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, NULL)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); auth_success = false; goto auth_fatal; } if (me->tls_authenticate) { /* tls authentication only? */ sd->free_tls(); /* yes, shutdown tls */ } } auth_fatal: /* Destroy session key */ memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); stop_bsock_timer(tid); /* Single thread all failures to avoid DOS */ if (!auth_success) { P(mutex); bmicrosleep(6, 0); V(mutex); } return auth_success; }
/* * See who is connecting and lookup the authentication information. * First make him prove his identity and then prove our identity to the Remote daemon. */ static inline bool two_way_authenticate(int rcode, BSOCK *bs, JCR* jcr) { POOLMEM *dirname; DIRRES *director = NULL; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool compatible = true; /* require md5 compatible DIR */ bool auth_success = false; alist *verify_list = NULL; if (rcode != R_DIRECTOR) { Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode); Jmsg1(jcr, M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); return 0; } /* * Sanity check. */ if (bs->msglen < 25 || bs->msglen > 500) { Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n", bs->who(), bs->msglen); Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"), bs->who(), bs->msglen); return 0; } dirname = get_pool_memory(PM_MESSAGE); dirname = check_pool_memory_size(dirname, bs->msglen); if (sscanf(bs->msg, "Hello Director %127s calling", dirname) != 1) { bs->msg[100] = 0; Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n", bs->who(), bs->msg); Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), bs->who(), bs->msg); return 0; } director = NULL; unbash_spaces(dirname); foreach_res(director, rcode) { if (bstrcmp(director->hdr.name, dirname)) { break; } } if (!director) { Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n", dirname, bs->who()); Jmsg(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n" "Please see %s for help.\n"), dirname, bs->who(), MANUAL_AUTH_URL); free_pool_memory(dirname); return 0; } /* * TLS Requirement */ if (director->tls_enable) { if (director->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (director->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (director->tls_verify_peer) { verify_list = director->tls_allowed_cns; } ASSERT(director->password.encoding == p_encoding_md5); /* * Timeout Hello after 10 mins */ btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT); auth_success = cram_md5_challenge(bs, director->password.value, tls_local_need, compatible); if (auth_success) { auth_success = cram_md5_respond(bs, director->password.value, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_get_auth failed with %s\n", bs->who()); } } else { Dmsg1(dbglvl, "cram_auth failed with %s\n", bs->who()); } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n" "Please see %s for help.\n"), MANUAL_AUTH_URL); auth_success = false; 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) { Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* * Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"), bs->host(), bs->port()); auth_success = false; goto auth_fatal; } if (director->tls_authenticate) { /* authenticate with tls only? */ bs->free_tls(); /* yes, shut it down */ } } auth_fatal: stop_bsock_timer(tid); free_pool_memory(dirname); jcr->director = director; return auth_success; }
/* * Depending on the initiate parameter perform one of the following: * * - First make him prove his identity and then prove our identity to the Remote daemon. * - First prove our identity to the Remote daemon and then make him prove his identity. */ static inline bool two_way_authenticate(BSOCK *bs, JCR *jcr, bool initiate, const char *what) { int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool compatible = true; /* require md5 compatible FD/SD */ bool auth_success = false; alist *verify_list = NULL; btimer_t *tid = NULL; /* * TLS Requirement */ if (me->tls_enable) { if (me->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (me->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (me->tls_verify_peer) { verify_list = me->tls_allowed_cns; } /* * Timeout Hello after 5 mins */ tid = start_bsock_timer(bs, AUTH_TIMEOUT); /* * See if we initiate the challenge or respond to a challenge. */ if (initiate) { /* * Challenge FD/SD */ auth_success = cram_md5_challenge(bs, jcr->sd_auth_key, tls_local_need, compatible); if (auth_success) { /* * Respond to his challenge */ auth_success = cram_md5_respond(bs, jcr->sd_auth_key, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "Respond cram-get-auth failed with %s\n", bs->who()); } } else { Dmsg1(dbglvl, "Challenge cram-auth failed with %s\n", bs->who()); } } else { /* * Respond to his challenge */ auth_success = cram_md5_respond(bs, jcr->sd_auth_key, &tls_remote_need, &compatible); if (auth_success) { /* * Challenge FD/SD */ auth_success = cram_md5_challenge(bs, jcr->sd_auth_key, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "Challenge cram-auth failed with %s\n", bs->who()); } } else { Dmsg1(dbglvl, "Respond cram-get-auth failed with %s\n", bs->who()); } } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from %s daemon at %s rejected.\n" "Please see %s for help.\n"), what, bs->who(), MANUAL_AUTH_URL); auth_success = false; 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* * Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(me->tls_ctx, bs, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with %s daemon at \"%s:%d\"\n"), what, bs->host(), bs->port()); auth_success = false; goto auth_fatal; } if (me->tls_authenticate) { /* tls authenticate only? */ bs->free_tls(); /* yes, shut it down */ } } auth_fatal: stop_bsock_timer(tid); jcr->authenticated = auth_success; return auth_success; }
/* * Authenticate Director */ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons) { BSOCK *dir = jcr->dir_bsock; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool tls_authenticate; int compatible = true; char bashed_name[MAX_NAME_LENGTH]; char *password; TLS_CONTEXT *tls_ctx = NULL; /* * Send my name to the Director then do authentication */ if (cons) { bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name)); bash_spaces(bashed_name); password = cons->password; /* TLS Requirement */ if (cons->tls_enable) { if (cons->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (cons->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } tls_authenticate = cons->tls_authenticate; tls_ctx = cons->tls_ctx; } else { bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name)); password = director->password; /* TLS Requirement */ if (director->tls_enable) { if (director->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (director->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } tls_authenticate = director->tls_authenticate; tls_ctx = director->tls_ctx; } /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(dir, 60 * 5); dir->fsend(hello, bashed_name); if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) || !cram_md5_challenge(dir, password, tls_local_need, compatible)) { goto bail_out; } /* 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) { sendit(_("Authorization problem:" " Remote server did not advertise required TLS support.\n")); goto bail_out; } /* 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) { sendit(_("Authorization problem:" " Remote server requires TLS.\n")); goto bail_out; } /* Is TLS Enabled? */ if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(tls_ctx, dir, NULL)) { sendit(_("TLS negotiation failed\n")); goto bail_out; } if (tls_authenticate) { /* Authenticate only? */ dir->free_tls(); /* yes, shutdown tls */ } } /* * It's possible that the TLS connection will * be dropped here if an invalid client certificate was presented */ Dmsg1(6, ">dird: %s", dir->msg); if (dir->recv() <= 0) { senditf(_("Bad response to Hello command: ERR=%s\n"), dir->bstrerror()); goto bail_out; } Dmsg1(10, "<dird: %s", dir->msg); if (strncmp(dir->msg, OKhello, sizeof(OKhello)-1) != 0) { sendit(_("Director rejected Hello command\n")); goto bail_out; } else { sendit(dir->msg); } stop_bsock_timer(tid); return 1; bail_out: stop_bsock_timer(tid); sendit( _("Director authorization problem.\n" "Most likely the passwords do not agree.\n" "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n" "Please see " MANUAL_AUTH_URL " for help.\n")); return 0; }
/* * Authenticate Director */ bool DirComm::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons, char *errmsg, int errmsg_len) { BSOCK *dir = jcr->dir_bsock; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; bool tls_authenticate; int compatible = true; char bashed_name[MAX_NAME_LENGTH]; char *password; TLS_CONTEXT *tls_ctx = NULL; errmsg[0] = 0; /* * Send my name to the Director then do authentication */ if (cons) { bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name)); bash_spaces(bashed_name); password = cons->password; /* TLS Requirement */ if (cons->tls_enable) { if (cons->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } tls_authenticate = cons->tls_authenticate; tls_ctx = cons->tls_ctx; } else { bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name)); password = director->password; /* TLS Requirement */ if (director->tls_enable) { if (director->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } tls_authenticate = director->tls_authenticate; tls_ctx = director->tls_ctx; } if (tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } /* Timeout Hello after 15 secs */ dir->start_timer(15); dir->fsend(hello, bashed_name); /* respond to Dir challenge */ if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) || /* Now challenge dir */ !cram_md5_challenge(dir, password, tls_local_need, compatible)) { bsnprintf(errmsg, errmsg_len, _("Director authorization problem at \"%s:%d\"\n"), dir->host(), dir->port()); goto bail_out; } /* 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) { bsnprintf(errmsg, errmsg_len, _("Authorization problem:" " Remote server at \"%s:%d\" did not advertise required TLS support.\n"), dir->host(), dir->port()); goto bail_out; } /* 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) { bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\":" " Remote server requires TLS.\n"), dir->host(), dir->port()); goto bail_out; } /* Is TLS Enabled? */ if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_client(tls_ctx, dir, NULL)) { bsnprintf(errmsg, errmsg_len, _("TLS negotiation failed with Director at \"%s:%d\"\n"), dir->host(), dir->port()); goto bail_out; } if (tls_authenticate) { /* authenticate only? */ dir->free_tls(); /* Yes, shutdown tls */ } } Dmsg1(6, ">dird: %s", dir->msg); if (dir->recv() <= 0) { dir->stop_timer(); bsnprintf(errmsg, errmsg_len, _("Bad response to Hello command: ERR=%s\n" "The Director at \"%s:%d\" is probably not running.\n"), dir->bstrerror(), dir->host(), dir->port()); return false; } dir->stop_timer(); Dmsg1(10, "<dird: %s", dir->msg); if (strncmp(dir->msg, OKhello, sizeof(OKhello)-1) != 0) { bsnprintf(errmsg, errmsg_len, _("Director at \"%s:%d\" rejected Hello command\n"), dir->host(), dir->port()); return false; } else { if (m_conn == 0) { bsnprintf(errmsg, errmsg_len, "%s", dir->msg); } } return true; bail_out: dir->stop_timer(); bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\"\n" "Most likely the passwords do not agree.\n" "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n" "Please see " MANUAL_AUTH_URL " for help.\n"), dir->host(), dir->port()); return false; }
int authenticate_filed(JCR *jcr) { BSOCK *fd = jcr->file_bsock; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; int compatible = true; /* require md5 compatible FD */ bool auth_success = false; alist *verify_list = NULL; /* TLS Requirement */ if (me->tls_enable) { if (me->tls_require) { tls_local_need = BNET_TLS_REQUIRED; } else { tls_local_need = BNET_TLS_OK; } } if (me->tls_authenticate) { tls_local_need = BNET_TLS_REQUIRED; } if (me->tls_verify_peer) { verify_list = me->tls_allowed_cns; } /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT); /* Challenge FD */ auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible); if (auth_success) { /* Respond to his challenge */ auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "cram-get-auth failed with %s\n", fd->who()); } } else { Dmsg1(dbglvl, "cram-auth failed with %s\n", fd->who()); } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n" "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"), fd->who()); auth_success = false; 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"), fd->host(), fd->port()); auth_success = false; goto auth_fatal; } if (me->tls_authenticate) { /* tls authenticate only? */ fd->free_tls(); /* yes, shut it down */ } } auth_fatal: stop_bsock_timer(tid); if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n" "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"), fd->who()); } jcr->authenticated = auth_success; return auth_success; }
/* * Depending on the initiate parameter perform one of the following: * * - First make him prove his identity and then prove our identity to the Remote. * - First prove our identity to the Remote and then make him prove his identity. */ bool BSOCK::two_way_authenticate(JCR *jcr, const char *what, const char *name, s_password &password, tls_t &tls, bool initiated_by_remote) { btimer_t *tid = NULL; const int dbglvl = 50; bool compatible = true; bool auth_success = false; int tls_local_need = BNET_TLS_NONE; int tls_remote_need = BNET_TLS_NONE; ASSERT(password.encoding == p_encoding_md5); /* * TLS Requirement */ if (get_tls_enable(tls.ctx)) { tls_local_need = get_tls_require(tls.ctx) ? BNET_TLS_REQUIRED : BNET_TLS_OK; } if (jcr && job_canceled(jcr)) { Dmsg0(dbglvl, "Failed, because job is canceled.\n"); auth_success = false; /* force quick exit */ goto auth_fatal; } /* * Timeout Hello after 10 min */ tid = start_bsock_timer(this, AUTH_TIMEOUT); /* * See if we initiate the challenge or respond to a challenge. */ if (initiated_by_remote) { /* * Challenge Remote. */ auth_success = cram_md5_challenge(this, password.value, tls_local_need, compatible); if (auth_success) { /* * Respond to remote challenge */ auth_success = cram_md5_respond(this, password.value, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "Respond cram-get-auth failed with %s\n", who()); } } else { Dmsg1(dbglvl, "Challenge cram-auth failed with %s\n", who()); } } else { /* * Respond to remote challenge */ auth_success = cram_md5_respond(this, password.value, &tls_remote_need, &compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_respond failed for %s\n", who()); } else { /* * Challenge Remote. */ auth_success = cram_md5_challenge(this, password.value, tls_local_need, compatible); if (!auth_success) { Dmsg1(dbglvl, "cram_challenge failed for %s\n", who()); } } } if (!auth_success) { Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by %s %s.\n" "Please see %s for help.\n"), what, name, MANUAL_AUTH_URL); goto auth_fatal; } if (jcr && job_canceled(jcr)) { Dmsg0(dbglvl, "Failed, because job is canceled.\n"); auth_success = false; /* force quick exit */ 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertize required TLS support.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); 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) { Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); auth_success = false; goto auth_fatal; } if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { alist *verify_list = NULL; if (tls.verify_peer) { verify_list = tls.allowed_cns; } /* * See if we are handshaking a passive client connection. */ if (initiated_by_remote) { if (!bnet_tls_server(tls.ctx, this, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); Dmsg0(dbglvl, "TLS negotiation failed.\n"); auth_success = false; goto auth_fatal; } } else { if (!bnet_tls_client(tls.ctx, this, tls.verify_peer, verify_list)) { Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); Dmsg0(dbglvl, "TLS negotiation failed.\n"); auth_success = false; goto auth_fatal; } } if (tls.authenticate) { /* tls authentication only? */ free_tls(); /* yes, shutdown tls */ } } auth_fatal: if (tid) { stop_bsock_timer(tid); tid = NULL; } if (jcr) { jcr->authenticated = auth_success; } return auth_success; }