static bool select_director(const char *director, DIRRES **ret_dir, CONRES **ret_cons) { int numcon=0, numdir=0; int i=0, item=0; BSOCK *UA_sock; DIRRES *dir = NULL; CONRES *cons = NULL; *ret_cons = NULL; *ret_dir = NULL; LockRes(); numdir = 0; foreach_res(dir, R_DIRECTOR) { numdir++; } numcon = 0; foreach_res(cons, R_CONSOLE) { numcon++; } UnlockRes(); if (numdir == 1) { /* No choose */ dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL); } if (director) { /* Command line choice overwrite the no choose option */ LockRes(); foreach_res(dir, R_DIRECTOR) { if (bstrcmp(dir->name(), director)) { break; } } UnlockRes(); if (!dir) { /* Can't find Director used as argument */ senditf(_("Can't find %s in Director list\n"), director); return 0; } } if (!dir) { /* prompt for director */ UA_sock = New(BSOCK_TCP); try_again: sendit(_("Available Directors:\n")); LockRes(); numdir = 0; foreach_res(dir, R_DIRECTOR) { senditf( _("%2d: %s at %s:%d\n"), 1+numdir++, dir->name(), dir->address, dir->DIRport); }
/* * Return 1 if OK * 0 if no input * -1 error (must stop) */ int get_cmd(FILE *input, const char *prompt, BSOCK *sock, int sec) { static char *line = NULL; static char *next = NULL; static int do_history = 0; char *command; if (line == NULL) { do_history = 0; rl_catch_signals = 0; /* do it ourselves */ /* Here, readline does ***real*** malloc * so, be we have to use the real free */ line = readline((char *)prompt); /* cast needed for old readlines */ if (!line) { return -1; /* error return and exit */ } strip_trailing_junk(line); command = line; } else if (next) { command = next + 1; } else { sendit(_("Command logic problem\n")); sock->msglen = 0; sock->msg[0] = 0; return 0; /* No input */ } /* * Split "line" into multiple commands separated by the eol character. * Each part is pointed to by "next" until finally it becomes null. */ if (eol == '\0') { next = NULL; } else { next = strchr(command, eol); if (next) { *next = '\0'; } } if (command != line && isatty(fileno(input))) { senditf("%s%s\n", prompt, command); } sock->msglen = pm_strcpy(&sock->msg, command); if (sock->msglen) { do_history++; } if (!next) { if (do_history) { add_history(line); } actuallyfree(line); /* allocated by readline() malloc */ line = NULL; } return 1; /* OK */ }
/* * 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; }