1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2018 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, October MM
25 */
26 /**
27 * @file
28 * This file handles accepting Director Commands
29 */
30
31 #include "include/bareos.h"
32 #include "filed/filed.h"
33 #include "filed/filed_globals.h"
34 #include "include/ch.h"
35 #include "filed/authenticate.h"
36 #include "filed/dir_cmd.h"
37 #include "filed/estimate.h"
38 #include "filed/evaluate_job_command.h"
39 #include "filed/heartbeat.h"
40 #include "filed/fileset.h"
41 #include "filed/socket_server.h"
42 #include "filed/restore.h"
43 #include "filed/verify.h"
44 #include "findlib/enable_priv.h"
45 #include "findlib/shadowing.h"
46 #include "lib/bget_msg.h"
47 #include "lib/bnet.h"
48 #include "lib/edit.h"
49 #include "lib/path_list.h"
50 #include "lib/qualified_resource_name_type_converter.h"
51 #include "lib/tls_conf.h"
52
53 #if defined(WIN32_VSS)
54 #include "win32/findlib/win32.h"
55 #include "vss.h"
56 #endif
57
58 namespace filedaemon {
59
60 extern bool backup_only_mode;
61 extern bool restore_only_mode;
62
63 /**
64 * As Windows saves ACLs as part of the standard backup stream
65 * we just pretend here that is has implicit acl support.
66 */
67 #if defined(HAVE_ACL) || defined(HAVE_WIN32)
68 const bool have_acl = true;
69 #else
70 const bool have_acl = false;
71 #endif
72
73 #if defined(HAVE_XATTR)
74 const bool have_xattr = true;
75 #else
76 const bool have_xattr = false;
77 #endif
78
79 #ifdef DATA_ENCRYPTION
80 const bool have_encryption = true;
81 #else
82 const bool have_encryption = false;
83 #endif
84
85 /* Global variables to handle Client Initiated Connections */
86 static bool quit_client_initiate_connection = false;
87 static alist *client_initiated_connection_threads = nullptr;
88
89 /* Imported functions */
90 extern bool AccurateCmd(JobControlRecord *jcr);
91 extern bool StatusCmd(JobControlRecord *jcr);
92 extern bool QstatusCmd(JobControlRecord *jcr);
93 extern "C" char *job_code_callback_filed(JobControlRecord *jcr, const char* param);
94
95 /* Forward referenced functions */
96 static bool BackupCmd(JobControlRecord *jcr);
97 static bool BootstrapCmd(JobControlRecord *jcr);
98 static bool CancelCmd(JobControlRecord *jcr);
99 static bool EndRestoreCmd(JobControlRecord *jcr);
100 static bool EstimateCmd(JobControlRecord *jcr);
101 #ifdef DEVELOPER
102 static bool exit_cmd(JobControlRecord *jcr);
103 #endif
104 static bool FilesetCmd(JobControlRecord *jcr);
105 static bool job_cmd(JobControlRecord *jcr);
106 static bool LevelCmd(JobControlRecord *jcr);
107 static bool PluginoptionsCmd(JobControlRecord *jcr);
108 static bool RunafterCmd(JobControlRecord *jcr);
109 static bool RunbeforenowCmd(JobControlRecord *jcr);
110 static bool RunbeforeCmd(JobControlRecord *jcr);
111 static bool RunscriptCmd(JobControlRecord *jcr);
112 static bool ResolveCmd(JobControlRecord *jcr);
113 static bool RestoreObjectCmd(JobControlRecord *jcr);
114 static bool RestoreCmd(JobControlRecord *jcr);
115 static bool SessionCmd(JobControlRecord *jcr);
116 static bool SecureerasereqCmd(JobControlRecord *jcr);
117 static bool SetauthorizationCmd(JobControlRecord *jcr);
118 static bool SetbandwidthCmd(JobControlRecord *jcr);
119 static bool SetdebugCmd(JobControlRecord *jcr);
120 static bool StorageCmd(JobControlRecord *jcr);
121 static bool SmDumpCmd(JobControlRecord *jcr);
122 static bool VerifyCmd(JobControlRecord *jcr);
123
124 static BareosSocket *connect_to_director(JobControlRecord *jcr, DirectorResource *dir_res, bool verbose);
125 static bool response(JobControlRecord *jcr, BareosSocket *sd, char *resp, const char *cmd);
126 static void FiledFreeJcr(JobControlRecord *jcr);
127 static bool OpenSdReadSession(JobControlRecord *jcr);
128 static void SetStorageAuthKeyAndTlsPolicy(JobControlRecord *jcr, char *key, TlsPolicy policy);
129
130 /* Exported functions */
131
132 struct s_cmds {
133 const char *cmd;
134 bool (*func)(JobControlRecord *);
135 bool monitoraccess; /* specify if monitors have access to this function */
136 };
137
138 /**
139 * The following are the recognized commands from the Director.
140 *
141 * Keywords are sorted first longest match when the keywords start with the same string.
142 */
143 static struct s_cmds cmds[] = {
144 { "accurate", AccurateCmd, false },
145 { "backup", BackupCmd, false },
146 { "bootstrap", BootstrapCmd, false },
147 { "cancel", CancelCmd, false },
148 { "endrestore", EndRestoreCmd, false },
149 { "estimate", EstimateCmd, false },
150 #ifdef DEVELOPER
151 { "exit", exit_cmd, false },
152 #endif
153 { "fileset", FilesetCmd, false },
154 { "JobId=", job_cmd, false },
155 { "level = ", LevelCmd, false },
156 { "pluginoptions", PluginoptionsCmd, false },
157 { "RunAfterJob", RunafterCmd, false },
158 { "RunBeforeNow", RunbeforenowCmd, false },
159 { "RunBeforeJob", RunbeforeCmd, false },
160 { "Run", RunscriptCmd, false },
161 { "restoreobject", RestoreObjectCmd, false },
162 { "restore ", RestoreCmd, false },
163 { "resolve ", ResolveCmd, false },
164 { "getSecureEraseCmd", SecureerasereqCmd, false},
165 { "session", SessionCmd, false },
166 { "setauthorization", SetauthorizationCmd, false },
167 { "setbandwidth=", SetbandwidthCmd, false },
168 { "setdebug=", SetdebugCmd, false },
169 { "status", StatusCmd, true },
170 { ".status", QstatusCmd, true },
171 { "storage ", StorageCmd, false },
172 { "sm_dump", SmDumpCmd, false },
173 { "verify", VerifyCmd, false },
174 {nullptr, nullptr, false} /* list terminator */
175 };
176
177 /**
178 * Commands send to director
179 */
180 static char hello_client[] = "Hello Client %s FdProtocolVersion=%d calling\n";
181
182 /**
183 * Responses received from the director
184 */
185 static const char OKversion[] = "1000 OK: %s Version: %s (%u %s %u)";
186
187 /**
188 * Commands received from director that need scanning
189 */
190 static char setauthorizationcmd[] = "setauthorization Authorization=%100s";
191 static char setbandwidthcmd[] = "setbandwidth=%lld Job=%127s";
192 static char setdebugv0cmd[] = "setdebug=%d trace=%d";
193 static char setdebugv1cmd[] = "setdebug=%d trace=%d hangup=%d";
194 static char setdebugv2cmd[] = "setdebug=%d trace=%d hangup=%d timestamp=%d";
195 static char storaddrv0cmd[] = "storage address=%s port=%d ssl=%d";
196 static char storaddrv1cmd[] = "storage address=%s port=%d ssl=%d Authorization=%100s";
197 static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n";
198 static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
199 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
200 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
201 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
202 static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
203 static char endrestoreobjectcmd[] = "restoreobject end\n";
204 static char pluginoptionscmd[] = "pluginoptions %s";
205 static char verifycmd[] = "verify level=%30s";
206 static char Estimatecmd[] = "estimate listing=%d";
207 static char runbeforecmd[] = "RunBeforeJob %s";
208 static char runaftercmd[] = "RunAfterJob %s";
209 static char runscriptcmd[] = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
210 static char resolvecmd[] = "resolve %s";
211
212 /**
213 * Responses sent to Director
214 */
215 static char errmsg[] = "2999 Invalid command\n";
216 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
217 static char OkAuthorization[] = "2000 OK Authorization\n";
218 static char OKBandwidth[] = "2000 OK Bandwidth\n";
219 static char OKinc[] = "2000 OK include\n";
220 static char OKest[] = "2000 OK estimate files=%s bytes=%s\n";
221 static char OKlevel[] = "2000 OK level\n";
222 static char OKbackup[] = "2000 OK backup\n";
223 static char OKbootstrap[] = "2000 OK bootstrap\n";
224 static char OKverify[] = "2000 OK verify\n";
225 static char OKrestore[] = "2000 OK restore\n";
226 static char OKsecureerase[] = "2000 OK FDSecureEraseCmd %s\n";
227 static char OKsession[] = "2000 OK session\n";
228 static char OKstore[] = "2000 OK storage\n";
229 static char OKstoreend[] = "2000 OK storage end\n";
230 static char OKjob[] = "2000 OK Job %s (%s) %s,%s,%s";
231 static char OKsetdebugv0[] = "2000 OK setdebug=%d trace=%d hangup=%d tracefile=%s\n";
232 static char OKsetdebugv1[] = "2000 OK setdebug=%d trace=%d hangup=%d timestamp=%d tracefile=%s\n";
233 static char BADjob[] = "2901 Bad Job\n";
234 static char EndJob[] =
235 "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
236 " JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
237 static char OKRunBefore[] = "2000 OK RunBefore\n";
238 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
239 static char OKRunAfter[] = "2000 OK RunAfter\n";
240 static char OKRunScript[] = "2000 OK RunScript\n";
241 static char BadRunBeforeJob[] = "2905 Bad RunBeforeJob command.\n";
242 static char FailedRunScript[] = "2905 Failed RunScript\n";
243 static char BadRunAfterJob[] = "2905 Bad RunAfterJob command.\n";
244 static char BADcmd[] = "2902 Bad %s\n";
245 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
246 static char OKPluginOptions[] = "2000 OK PluginOptions\n";
247 static char BadPluginOptions[] = "2905 Bad PluginOptions command.\n";
248
249 /**
250 * Responses received from Storage Daemon
251 */
252 static char OK_end[] = "3000 OK end\n";
253 static char OK_close[] = "3000 OK close Status = %d\n";
254 static char OK_open[] = "3000 OK open ticket = %d\n";
255 static char OK_data[] = "3000 OK data\n";
256 static char OK_append[] = "3000 OK append data\n";
257
258 /**
259 * Commands sent to Storage Daemon
260 */
261 static char append_open[] = "append open session\n";
262 static char append_data[] = "append data %d\n";
263 static char append_end[] = "append end session %d\n";
264 static char append_close[] = "append close session %d\n";
265 static char read_open[] = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
266 static char read_data[] = "read data %d\n";
267 static char read_close[] = "read close session %d\n";
268
269 /**
270 * See if we are allowed to execute the command issued.
271 */
ValidateCommand(JobControlRecord * jcr,const char * cmd,alist * allowed_job_cmds)272 static bool ValidateCommand(JobControlRecord *jcr, const char *cmd, alist *allowed_job_cmds)
273 {
274 char *allowed_job_cmd = nullptr;
275 bool allowed = false;
276
277 /*
278 * If there is no explicit list of allowed cmds allow all cmds.
279 */
280 if (!allowed_job_cmds) { return true; }
281
282 foreach_alist(allowed_job_cmd, allowed_job_cmds) {
283 if (Bstrcasecmp(cmd, allowed_job_cmd)) {
284 allowed = true;
285 break;
286 }
287 }
288
289 if (!allowed) {
290 Jmsg(jcr, M_FATAL, 0, _("Illegal \"%s\" command not allowed by Allowed Job Cmds setting of this filed.\n"),
291 cmd);
292 }
293
294 return allowed;
295 }
296
CleanupFileset(JobControlRecord * jcr)297 static inline void CleanupFileset(JobControlRecord *jcr)
298 {
299 findFILESET *fileset;
300 findIncludeExcludeItem *incexe;
301 findFOPTS *fo;
302
303 fileset = jcr->ff->fileset;
304 if (fileset) {
305 /*
306 * Delete FileSet Include lists
307 */
308 for (int i = 0; i < fileset->include_list.size(); i++) {
309 incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
310 for (int j = 0; j < incexe->opts_list.size(); j++) {
311 fo = (findFOPTS *)incexe->opts_list.get(j);
312 if (fo->plugin) { free(fo->plugin); }
313 for (int k = 0; k < fo->regex.size(); k++) { regfree((regex_t *)fo->regex.get(k)); }
314 for (int k = 0; k < fo->regexdir.size(); k++) { regfree((regex_t *)fo->regexdir.get(k)); }
315 for (int k = 0; k < fo->regexfile.size(); k++) { regfree((regex_t *)fo->regexfile.get(k)); }
316 if (fo->size_match) { free(fo->size_match); }
317 fo->regex.destroy();
318 fo->regexdir.destroy();
319 fo->regexfile.destroy();
320 fo->wild.destroy();
321 fo->wilddir.destroy();
322 fo->wildfile.destroy();
323 fo->wildbase.destroy();
324 fo->base.destroy();
325 fo->fstype.destroy();
326 fo->Drivetype.destroy();
327 }
328 incexe->opts_list.destroy();
329 incexe->name_list.destroy();
330 incexe->plugin_list.destroy();
331 incexe->ignoredir.destroy();
332 }
333 fileset->include_list.destroy();
334
335 /*
336 * Delete FileSet Exclude lists
337 */
338 for (int i = 0; i<fileset->exclude_list.size(); i++) {
339 incexe = (findIncludeExcludeItem *)fileset->exclude_list.get(i);
340 for (int j = 0; j<incexe->opts_list.size(); j++) {
341 fo = (findFOPTS *)incexe->opts_list.get(j);
342 if (fo->size_match) { free(fo->size_match); }
343 fo->regex.destroy();
344 fo->regexdir.destroy();
345 fo->regexfile.destroy();
346 fo->wild.destroy();
347 fo->wilddir.destroy();
348 fo->wildfile.destroy();
349 fo->wildbase.destroy();
350 fo->base.destroy();
351 fo->fstype.destroy();
352 fo->Drivetype.destroy();
353 }
354 incexe->opts_list.destroy();
355 incexe->name_list.destroy();
356 incexe->plugin_list.destroy();
357 incexe->ignoredir.destroy();
358 }
359 fileset->exclude_list.destroy();
360 free(fileset);
361 }
362 jcr->ff->fileset = nullptr;
363 }
364
AreMaxConcurrentJobsExceeded()365 static inline bool AreMaxConcurrentJobsExceeded()
366 {
367 JobControlRecord *jcr;
368 unsigned int cnt = 0;
369
370 foreach_jcr(jcr) {
371 cnt++;
372 }
373 endeach_jcr(jcr);
374
375 return (cnt >= me->MaxConcurrentJobs) ? true : false;
376 }
377
create_new_director_session(BareosSocket * dir)378 JobControlRecord *create_new_director_session(BareosSocket *dir)
379 {
380 JobControlRecord *jcr;
381 const char jobname[12] = "*Director*";
382
383 jcr = new_jcr(sizeof(JobControlRecord), FiledFreeJcr); /* create JobControlRecord */
384 jcr->dir_bsock = dir;
385 jcr->ff = init_find_files();
386 jcr->start_time = time(nullptr);
387 jcr->RunScripts = New(alist(10, not_owned_by_alist));
388 jcr->last_fname = GetPoolMemory(PM_FNAME);
389 jcr->last_fname[0] = 0;
390 jcr->client_name = GetMemory(strlen(my_name) + 1);
391 PmStrcpy(jcr->client_name, my_name);
392 bstrncpy(jcr->Job, jobname, sizeof(jobname)); /* dummy */
393 jcr->crypto.pki_sign = me->pki_sign;
394 jcr->crypto.pki_encrypt = me->pki_encrypt;
395 jcr->crypto.pki_keypair = me->pki_keypair;
396 jcr->crypto.pki_signers = me->pki_signers;
397 jcr->crypto.pki_recipients = me->pki_recipients;
398 if (dir) { dir->SetJcr(jcr); }
399 SetJcrInTsd(jcr);
400
401 EnableBackupPrivileges(nullptr, 1 /* ignore_errors */);
402
403 return jcr;
404 }
405
process_director_commands(void * p_jcr)406 void *process_director_commands(void *p_jcr)
407 {
408 JobControlRecord *jcr = (JobControlRecord *)p_jcr;
409 return process_director_commands(jcr, jcr->dir_bsock);
410 }
411
process_director_commands(JobControlRecord * jcr,BareosSocket * dir)412 void *process_director_commands(JobControlRecord *jcr, BareosSocket *dir)
413 {
414 bool found;
415 bool quit = false;
416
417 /**********FIXME******* add command handler error code */
418
419 while (jcr->authenticated && (!quit)) {
420 /*
421 * Read command
422 */
423 if (dir->recv() < 0) { break; /* connection terminated */ }
424
425 dir->msg[dir->message_length] = 0;
426 Dmsg1(100, "<dird: %s\n", dir->msg);
427 found = false;
428 for (int i = 0; cmds[i].cmd; i++) {
429 if (bstrncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd))) {
430 found = true; /* indicate command found */
431 if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
432 Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
433 dir->fsend(invalid_cmd);
434 dir->signal(BNET_EOD);
435 break;
436 }
437 Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
438 if (!cmds[i].func(jcr)) { /* do command */
439 quit = true; /* error or fully terminated, get out */
440 Dmsg1(100, "Quit command loop. Canceled=%d\n", JobCanceled(jcr));
441 }
442 break;
443 }
444 }
445 if (!found) { /* command not found */
446 dir->fsend(errmsg);
447 quit = true;
448 break;
449 }
450 }
451
452 /*
453 * Inform Storage daemon that we are done
454 */
455 if (jcr->store_bsock) { jcr->store_bsock->signal(BNET_TERMINATE); }
456
457 /*
458 * Run the after job
459 */
460 if (jcr->RunScripts) {
461 RunScripts(jcr, jcr->RunScripts, "ClientAfterJob",
462 (jcr->director && jcr->director->allowed_script_dirs) ? jcr->director->allowed_script_dirs
463 : me->allowed_script_dirs);
464 }
465
466 if (jcr->JobId) { /* send EndJob if running a job */
467 char ed1[50], ed2[50];
468 /*
469 * Send termination status back to Dir
470 */
471 dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->ReadBytes, ed1),
472 edit_uint64(jcr->JobBytes, ed2), jcr->JobErrors, jcr->enable_vss, jcr->crypto.pki_encrypt);
473 Dmsg1(110, "End FD msg: %s\n", dir->msg);
474 }
475
476 GeneratePluginEvent(jcr, bEventJobEnd);
477
478 DequeueMessages(jcr); /* send any queued messages */
479
480 /*
481 * Inform Director that we are done
482 */
483 dir->signal(BNET_TERMINATE);
484
485 FreePlugins(jcr); /* release instantiated plugins */
486 FreeAndNullPoolMemory(jcr->job_metadata);
487
488 /*
489 * Clean up fileset
490 */
491 CleanupFileset(jcr);
492
493 FreeJcr(jcr); /* destroy JobControlRecord record */
494 Dmsg0(100, "Done with FreeJcr\n");
495 Dsm_check(100);
496 GarbageCollectMemoryPool();
497
498 #ifdef HAVE_WIN32
499 AllowOsSuspensions();
500 #endif
501
502 return nullptr;
503 }
504
505 /**
506 * Create a new thread to handle director connection.
507 */
StartProcessDirectorCommands(JobControlRecord * jcr)508 static bool StartProcessDirectorCommands(JobControlRecord *jcr)
509 {
510 int result = 0;
511 pthread_t thread;
512
513 if ((result = pthread_create(&thread, nullptr, process_director_commands, (void *)jcr)) != 0) {
514 BErrNo be;
515 Emsg1(M_ABORT, 0, _("Cannot create Director connect thread: %s\n"), be.bstrerror(result));
516 }
517
518 return (result == 0);
519 }
520
521 /**
522 * Connection request from an director.
523 *
524 * Accept commands one at a time from the Director and execute them.
525 *
526 * Concerning ClientRunBefore/After, the sequence of events is rather critical.
527 * If they are not done in the right order one can easily get FD->SD timeouts
528 * if the script runs a long time.
529 *
530 * The current sequence of events is:
531 * 1. Dir starts job with FD
532 * 2. Dir connects to SD
533 * 3. Dir connects to FD
534 * 4. FD connects to SD
535 * 5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
536 * 6. Dir sends include/exclude
537 * 7. FD sends data to SD
538 * 8. SD/FD disconnects while SD despools data and attributes (optional)
539 * 9. FD runs ClientRunAfterJob
540 */
handle_director_connection(BareosSocket * dir)541 void *handle_director_connection(BareosSocket *dir)
542 {
543 JobControlRecord *jcr;
544
545 #ifdef HAVE_WIN32
546 PreventOsSuspensions();
547 #endif
548
549 if (AreMaxConcurrentJobsExceeded()) {
550 Emsg0(M_ERROR, 0, _("Number of Jobs exhausted, please increase MaximumConcurrentJobs\n"));
551 return nullptr;
552 }
553
554 jcr = create_new_director_session(dir);
555
556 Dmsg0(120, "Calling Authenticate\n");
557 if (AuthenticateDirector(jcr)) { Dmsg0(120, "OK Authenticate\n"); }
558
559 return process_director_commands(jcr, dir);
560 }
561
ParseOkVersion(const char * string)562 static bool ParseOkVersion(const char *string)
563 {
564 char name[MAX_NAME_LENGTH];
565 char version[MAX_NAME_LENGTH];
566 unsigned int day = 0;
567 char month[100];
568 unsigned int year = 0;
569 int number = 0;
570
571 number = sscanf(string, OKversion, &name, &version, &day, &month, &year);
572 Dmsg2(120, "OK message: %s, Version: %s\n", name, version);
573 return (number == 5);
574 }
575
handle_connection_to_director(void * director_resource)576 static void *handle_connection_to_director(void *director_resource)
577 {
578 DirectorResource *dir_res = (DirectorResource *)director_resource;
579 BareosSocket *dir_bsock = nullptr;
580 JobControlRecord *jcr = nullptr;
581 int data_available = 0;
582 int retry_period = 60;
583 const int timeout_data = 60;
584
585 while (!quit_client_initiate_connection) {
586 if (jcr) {
587 FreeJcr(jcr);
588 jcr = nullptr;
589 }
590
591 jcr = create_new_director_session(nullptr);
592 dir_bsock = connect_to_director(jcr, dir_res, true);
593 if (!dir_bsock) {
594 Emsg2(M_ERROR, 0, "Failed to connect to Director \"%s\". Retry in %ds.\n", dir_res->name(),
595 retry_period);
596 sleep(retry_period);
597 } else {
598 Dmsg1(120, "Connected to \"%s\".\n", dir_res->name());
599
600 /*
601 * Returns: 1 if data available, 0 if timeout, -1 if error
602 */
603 data_available = 0;
604 while ((data_available == 0) && (!quit_client_initiate_connection)) {
605 Dmsg2(120, "Waiting for data from Director \"%s\" (timeout: %ds)\n", dir_res->name(), timeout_data);
606 data_available = dir_bsock->WaitDataIntr(timeout_data);
607 }
608 if (!quit_client_initiate_connection) {
609 if (data_available < 0) {
610 Emsg1(M_ABORT, 0, _("Failed while waiting for data from Director \"%s\"\n"), dir_res->name());
611 } else {
612 /*
613 * data is available
614 */
615 dir_bsock->SetJcr(jcr);
616 jcr->dir_bsock = dir_bsock;
617 if (StartProcessDirectorCommands(jcr)) {
618 /*
619 * jcr (and dir_bsock) are now used by another thread.
620 */
621 dir_bsock = nullptr;
622 jcr = nullptr;
623 }
624 }
625 }
626 }
627 }
628
629 Dmsg1(100, "Exiting Client Initiated Connection thread for %s\n", dir_res->name());
630 if (jcr) {
631 /*
632 * cleanup old data structures
633 */
634 FreeJcr(jcr);
635 }
636
637 return nullptr;
638 }
639
StartConnectToDirectorThreads()640 bool StartConnectToDirectorThreads()
641 {
642 bool result = false;
643 DirectorResource *dir_res = nullptr;
644 int pthread_create_result = 0;
645 if (!client_initiated_connection_threads) { client_initiated_connection_threads = New(alist()); }
646 pthread_t *thread;
647
648 foreach_res(dir_res, R_DIRECTOR) {
649 if (dir_res->conn_from_fd_to_dir) {
650 if (!dir_res->address) {
651 Emsg1(M_ERROR, 0, "Failed to connect to Director \"%s\". The address config directive is missing.\n",
652 dir_res->name());
653 } else if (!dir_res->port) {
654 Emsg1(M_ERROR, 0, "Failed to connect to Director \"%s\". The port config directive is missing.\n",
655 dir_res->name());
656 } else {
657 Dmsg3(120, "Connecting to Director \"%s\", address %s:%d.\n", dir_res->name(), dir_res->address,
658 dir_res->port);
659 thread = (pthread_t *)bmalloc(sizeof(pthread_t));
660 if ((pthread_create_result =
661 pthread_create(thread, nullptr, handle_connection_to_director, (void *)dir_res)) == 0) {
662 client_initiated_connection_threads->append(thread);
663 } else {
664 BErrNo be;
665 Emsg1(M_ABORT, 0, _("Cannot create Director connect thread: %s\n"),
666 be.bstrerror(pthread_create_result));
667 }
668 }
669 }
670 }
671
672 return result;
673 }
674
StopConnectToDirectorThreads(bool wait)675 bool StopConnectToDirectorThreads(bool wait)
676 {
677 bool result = true;
678 pthread_t *thread = nullptr;
679 quit_client_initiate_connection = true;
680 if (client_initiated_connection_threads) {
681 while(!client_initiated_connection_threads->empty()) {
682 thread = (pthread_t *)client_initiated_connection_threads->remove(0);
683 if (thread) {
684 pthread_kill(*thread, TIMEOUT_SIGNAL);
685 if (wait) {
686 if (pthread_join(*thread, nullptr) != 0) { result = false; }
687 }
688 bfree(thread);
689 }
690 }
691 delete(client_initiated_connection_threads);
692 }
693 return result;
694 }
695
SmDumpCmd(JobControlRecord * jcr)696 static bool SmDumpCmd(JobControlRecord *jcr)
697 {
698 CloseMemoryPool();
699 sm_dump(false, true);
700 jcr->dir_bsock->fsend("2000 sm_dump OK\n");
701 return true;
702 }
703
704 /**
705 * Resolve a hostname
706 */
ResolveCmd(JobControlRecord * jcr)707 static bool ResolveCmd(JobControlRecord *jcr)
708 {
709 BareosSocket *dir = jcr->dir_bsock;
710 dlist *addr_list;
711 const char *errstr;
712 char addresses[2048];
713 char hostname[2048];
714
715 sscanf(dir->msg, resolvecmd, &hostname);
716
717 if ((addr_list = BnetHost2IpAddrs(hostname, 0, &errstr)) == nullptr) {
718 dir->fsend(_("%s: Failed to resolve %s\n"), my_name, hostname);
719 goto bail_out;
720 }
721
722 dir->fsend(_("%s resolves %s to %s\n"),my_name, hostname,
723 BuildAddressesString(addr_list, addresses, sizeof(addresses), false));
724 FreeAddresses(addr_list);
725
726 bail_out:
727 dir->signal(BNET_EOD);
728 return true;
729 }
730
SecureerasereqCmd(JobControlRecord * jcr)731 static bool SecureerasereqCmd(JobControlRecord *jcr)
732 {
733 const char *setting;
734 BareosSocket *dir = jcr->dir_bsock;
735
736 setting = me->secure_erase_cmdline ? me->secure_erase_cmdline : "*None*";
737 Dmsg1(200,"Secure Erase Cmd Request: %s\n", setting);
738 return dir->fsend(OKsecureerase, setting);
739 }
740
741 #ifdef DEVELOPER
exit_cmd(JobControlRecord * jcr)742 static bool exit_cmd(JobControlRecord *jcr)
743 {
744 jcr->dir_bsock->fsend("2000 exit OK\n");
745 //terminate_filed(0);
746 StopSocketServer();
747 return false;
748 }
749 #endif
750
751 /**
752 * Cancel a Job
753 */
CancelCmd(JobControlRecord * jcr)754 static bool CancelCmd(JobControlRecord *jcr)
755 {
756 BareosSocket *dir = jcr->dir_bsock;
757 char Job[MAX_NAME_LENGTH];
758 JobControlRecord *cjcr;
759
760 if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
761 if (!(cjcr=get_jcr_by_full_name(Job))) {
762 dir->fsend(_("2901 Job %s not found.\n"), Job);
763 } else {
764 GeneratePluginEvent(cjcr, bEventCancelCommand, nullptr);
765 cjcr->setJobStatus(JS_Canceled);
766 if (cjcr->store_bsock) {
767 cjcr->store_bsock->SetTimedOut();
768 cjcr->store_bsock->SetTerminated();
769 }
770 cjcr->MyThreadSendSignal(TIMEOUT_SIGNAL);
771 FreeJcr(cjcr);
772 dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
773 }
774 } else {
775 dir->fsend(_("2902 Error scanning cancel command.\n"));
776 }
777 dir->signal(BNET_EOD);
778 return true;
779 }
780
781 /**
782 * Set new authorization key as requested by the Director
783 */
SetauthorizationCmd(JobControlRecord * jcr)784 static bool SetauthorizationCmd(JobControlRecord *jcr)
785 {
786 BareosSocket *dir = jcr->dir_bsock;
787 PoolMem sd_auth_key(PM_MESSAGE);
788
789 sd_auth_key.check_size(dir->message_length);
790 if (sscanf(dir->msg, setauthorizationcmd, sd_auth_key.c_str()) != 1) {
791 dir->fsend(BADcmd, "setauthorization");
792 return false;
793 }
794
795 SetStorageAuthKeyAndTlsPolicy(jcr, sd_auth_key.c_str(), jcr->sd_tls_policy);
796 Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
797
798 return dir->fsend(OkAuthorization);
799 }
800
801 /**
802 * Set bandwidth limit as requested by the Director
803 */
SetbandwidthCmd(JobControlRecord * jcr)804 static bool SetbandwidthCmd(JobControlRecord *jcr)
805 {
806 BareosSocket *dir = jcr->dir_bsock;
807 int64_t bw = 0;
808 JobControlRecord *cjcr;
809 char Job[MAX_NAME_LENGTH];
810
811 *Job = 0;
812 if (sscanf(dir->msg, setbandwidthcmd, &bw, Job) != 2 || bw < 0) {
813 PmStrcpy(jcr->errmsg, dir->msg);
814 dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
815 return false;
816 }
817
818 if (*Job) {
819 if (!(cjcr = get_jcr_by_full_name(Job))) {
820 dir->fsend(_("2901 Job %s not found.\n"), Job);
821 } else {
822 cjcr->max_bandwidth = bw;
823 if (cjcr->store_bsock) {
824 cjcr->store_bsock->SetBwlimit(bw);
825 if (me->allow_bw_bursting) { cjcr->store_bsock->SetBwlimitBursting(); }
826 }
827 FreeJcr(cjcr);
828 }
829 } else { /* No job requested, apply globally */
830 me->max_bandwidth_per_job = bw; /* Overwrite directive */
831 }
832
833 return dir->fsend(OKBandwidth);
834 }
835
836 /**
837 * Set debug level as requested by the Director
838 */
SetdebugCmd(JobControlRecord * jcr)839 static bool SetdebugCmd(JobControlRecord *jcr)
840 {
841 BareosSocket *dir = jcr->dir_bsock;
842 int32_t level, trace_flag, hangup_flag, timestamp_flag;
843 int scan;
844
845 Dmsg1(50, "SetdebugCmd: %s", dir->msg);
846 scan = sscanf(dir->msg, setdebugv2cmd, &level, &trace_flag, &hangup_flag, ×tamp_flag);
847 if (scan != 4) { scan = sscanf(dir->msg, setdebugv1cmd, &level, &trace_flag, &hangup_flag); }
848 if (scan != 3 && scan != 4) {
849 scan = sscanf(dir->msg, setdebugv0cmd, &level, &trace_flag);
850 if (scan != 2) {
851 PmStrcpy(jcr->errmsg, dir->msg);
852 dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
853 return false;
854 } else {
855 hangup_flag = -1;
856 }
857 }
858
859 PoolMem tracefilename(PM_FNAME);
860 Mmsg(tracefilename, "%s/%s.trace", TRACEFILEDIRECTORY, my_name);
861
862 if (level >= 0) { debug_level = level; }
863
864 SetTrace(trace_flag);
865 SetHangup(hangup_flag);
866 if (scan == 4) {
867 SetTimestamp(timestamp_flag);
868 Dmsg5(50, "level=%d trace=%d hangup=%d timestamp=%d tracefilename=%s\n", level, GetTrace(), GetHangup(),
869 GetTimestamp(), tracefilename.c_str());
870 return dir->fsend(OKsetdebugv1, level, GetTrace(), GetHangup(), GetTimestamp(), tracefilename.c_str());
871 } else {
872 Dmsg4(50, "level=%d trace=%d hangup=%d tracefilename=%s\n", level, GetTrace(), GetHangup(),
873 tracefilename.c_str());
874 return dir->fsend(OKsetdebugv0, level, GetTrace(), GetHangup(), tracefilename.c_str());
875 }
876 }
877
EstimateCmd(JobControlRecord * jcr)878 static bool EstimateCmd(JobControlRecord *jcr)
879 {
880 BareosSocket *dir = jcr->dir_bsock;
881 char ed1[50], ed2[50];
882
883 /*
884 * See if we are allowed to run estimate cmds.
885 */
886 if (!ValidateCommand(jcr, "estimate",
887 (jcr->director && jcr->director->allowed_job_cmds) ? jcr->director->allowed_job_cmds
888 : me->allowed_job_cmds)) {
889 dir->fsend(_("2992 Bad estimate command.\n"));
890 return 0;
891 }
892
893 if (sscanf(dir->msg, Estimatecmd, &jcr->listing) != 1) {
894 PmStrcpy(jcr->errmsg, dir->msg);
895 Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
896 dir->fsend(_("2992 Bad estimate command.\n"));
897 return false;
898 }
899
900 MakeEstimate(jcr);
901
902 dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
903 edit_uint64_with_commas(jcr->JobBytes, ed2));
904 dir->signal(BNET_EOD);
905
906 return true;
907 }
908
909 /**
910 * Get JobId and Storage Daemon Authorization key from Director
911 */
job_cmd(JobControlRecord * jcr)912 static bool job_cmd(JobControlRecord *jcr)
913 {
914 BareosSocket *dir = jcr->dir_bsock;
915
916 JobCommand command(dir->msg);
917
918 if (!command.EvaluationSuccesful()) {
919 PmStrcpy(jcr->errmsg, dir->msg);
920 Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
921 dir->fsend(BADjob);
922 return false;
923 }
924
925 jcr->JobId = command.job_id_;
926 strncpy(jcr->Job, command.job_, sizeof(jcr->Job));
927 jcr->VolSessionId = command.vol_session_id_;
928 jcr->VolSessionTime = command.vol_session_time_;
929
930 TlsPolicy tls_policy = command.protocol_version_ == JobCommand::ProtocolVersion::KVersionBefore_18_2 ?
931 TlsPolicy::kBnetTlsNone : command.tls_policy_;
932
933 SetStorageAuthKeyAndTlsPolicy(jcr, command.sd_auth_key_, tls_policy);
934 Dmsg3(120, "JobId=%d Auth=%s TlsPolicy=%d\n", jcr->JobId, jcr->sd_auth_key, tls_policy);
935 Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
936 NewPlugins(jcr); /* instantiate plugins for this jcr */
937 GeneratePluginEvent(jcr, bEventJobStart, (void *)jcr->errmsg);
938
939 const char *os_version;
940 #ifdef HAVE_WIN32
941 os_version = win_os;
942 #else
943 os_version = HOST_OS;
944 #endif
945
946 return dir->fsend(OKjob, VERSION, LSMDATE, os_version, DISTNAME, DISTVER);
947 }
948
RunbeforeCmd(JobControlRecord * jcr)949 static bool RunbeforeCmd(JobControlRecord *jcr)
950 {
951 bool ok;
952 POOLMEM *cmd;
953 RunScript *script;
954 BareosSocket *dir = jcr->dir_bsock;
955
956 if (!me->compatible) {
957 dir->fsend(BadRunBeforeJob);
958 return false;
959 }
960
961 Dmsg1(100, "RunbeforeCmd: %s", dir->msg);
962 cmd = GetMemory(dir->message_length + 1);
963 if (sscanf(dir->msg, runbeforecmd, cmd) != 1) {
964 PmStrcpy(jcr->errmsg, dir->msg);
965 Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
966 dir->fsend(BadRunBeforeJob);
967 FreeMemory(cmd);
968 return false;
969 }
970 UnbashSpaces(cmd);
971
972 /*
973 * Run the command now
974 */
975 script = NewRunscript();
976 script->SetJobCodeCallback(job_code_callback_filed);
977 script->SetCommand(cmd);
978 script->when = SCRIPT_Before;
979 FreeMemory(cmd);
980
981 ok = script->run(jcr, "ClientRunBeforeJob");
982 FreeRunscript(script);
983
984 if (ok) {
985 dir->fsend(OKRunBefore);
986 return true;
987 } else {
988 dir->fsend(BadRunBeforeJob);
989 return false;
990 }
991 }
992
RunbeforenowCmd(JobControlRecord * jcr)993 static bool RunbeforenowCmd(JobControlRecord *jcr)
994 {
995 BareosSocket *dir = jcr->dir_bsock;
996
997 RunScripts(jcr, jcr->RunScripts, "ClientBeforeJob",
998 (jcr->director && jcr->director->allowed_script_dirs) ? jcr->director->allowed_script_dirs
999 : me->allowed_script_dirs);
1000
1001 if (JobCanceled(jcr)) {
1002 dir->fsend(FailedRunScript);
1003 Dmsg0(100, "Back from RunScripts ClientBeforeJob now: FAILED\n");
1004 return false;
1005 } else {
1006 dir->fsend(OKRunBeforeNow);
1007 Dmsg0(100, "Back from RunScripts ClientBeforeJob now: OK\n");
1008 return true;
1009 }
1010 }
1011
RunafterCmd(JobControlRecord * jcr)1012 static bool RunafterCmd(JobControlRecord *jcr)
1013 {
1014 BareosSocket *dir = jcr->dir_bsock;
1015 POOLMEM *cmd;
1016 RunScript *script;
1017
1018 if (!me->compatible) {
1019 dir->fsend(BadRunAfterJob);
1020 return false;
1021 }
1022
1023 Dmsg1(100, "RunafterCmd: %s", dir->msg);
1024 cmd = GetMemory(dir->message_length + 1);
1025 if (sscanf(dir->msg, runaftercmd, cmd) != 1) {
1026 PmStrcpy(jcr->errmsg, dir->msg);
1027 Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
1028 dir->fsend(BadRunAfterJob);
1029 FreeMemory(cmd);
1030 return false;
1031 }
1032 UnbashSpaces(cmd);
1033
1034 script = NewRunscript();
1035 script->SetJobCodeCallback(job_code_callback_filed);
1036 script->SetCommand(cmd);
1037 script->on_success = true;
1038 script->on_failure = false;
1039 script->when = SCRIPT_After;
1040 FreeMemory(cmd);
1041
1042 jcr->RunScripts->append(script);
1043
1044 return dir->fsend(OKRunAfter);
1045 }
1046
RunscriptCmd(JobControlRecord * jcr)1047 static bool RunscriptCmd(JobControlRecord *jcr)
1048 {
1049 POOLMEM *msg;
1050 RunScript *cmd;
1051 BareosSocket *dir = jcr->dir_bsock;
1052 int on_success, on_failure, fail_on_error;
1053
1054 /*
1055 * See if we are allowed to run runscript cmds.
1056 */
1057 if (!ValidateCommand(jcr, "runscript",
1058 (jcr->director && jcr->director->allowed_job_cmds) ? jcr->director->allowed_job_cmds
1059 : me->allowed_job_cmds)) {
1060 dir->fsend(FailedRunScript);
1061 return 0;
1062 }
1063
1064 msg = GetMemory(dir->message_length + 1);
1065 cmd = NewRunscript();
1066 cmd->SetJobCodeCallback(job_code_callback_filed);
1067
1068 Dmsg1(100, "RunscriptCmd: '%s'\n", dir->msg);
1069
1070 /*
1071 * Note, we cannot sscanf into bools
1072 */
1073 if (sscanf(dir->msg, runscriptcmd, &on_success, &on_failure, &fail_on_error, &cmd->when, msg) != 5) {
1074 PmStrcpy(jcr->errmsg, dir->msg);
1075 Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
1076 dir->fsend(FailedRunScript);
1077 FreeRunscript(cmd);
1078 FreeMemory(msg);
1079 return false;
1080 }
1081
1082 cmd->on_success = on_success;
1083 cmd->on_failure = on_failure;
1084 cmd->fail_on_error = fail_on_error;
1085 UnbashSpaces(msg);
1086
1087 cmd->SetCommand(msg);
1088 cmd->debug();
1089 jcr->RunScripts->append(cmd);
1090
1091 FreePoolMemory(msg);
1092
1093 return dir->fsend(OKRunScript);
1094 }
1095
1096 /**
1097 * This passes plugin specific options.
1098 */
PluginoptionsCmd(JobControlRecord * jcr)1099 static bool PluginoptionsCmd(JobControlRecord *jcr)
1100 {
1101 BareosSocket *dir = jcr->dir_bsock;
1102 POOLMEM *msg;
1103
1104 msg = GetMemory(dir->message_length + 1);
1105 if (sscanf(dir->msg, pluginoptionscmd, msg) != 1) {
1106 PmStrcpy(jcr->errmsg, dir->msg);
1107 Jmsg1(jcr, M_FATAL, 0, _("Bad Plugin Options command: %s\n"), jcr->errmsg);
1108 dir->fsend(BadPluginOptions);
1109 FreeMemory(msg);
1110 return false;
1111 }
1112
1113 UnbashSpaces(msg);
1114 GeneratePluginEvent(jcr, bEventNewPluginOptions, (void *)msg);
1115 FreeMemory(msg);
1116
1117 return dir->fsend(OKPluginOptions);
1118 }
1119
1120 /**
1121 * This reads data sent from the Director from the
1122 * RestoreObject table that allows us to get objects
1123 * that were backed up (VSS .xml data) and are needed
1124 * before starting the restore.
1125 */
RestoreObjectCmd(JobControlRecord * jcr)1126 static bool RestoreObjectCmd(JobControlRecord *jcr)
1127 {
1128 BareosSocket *dir = jcr->dir_bsock;
1129 int32_t FileIndex;
1130 restore_object_pkt rop;
1131
1132 memset(&rop, 0, sizeof(rop));
1133 rop.pkt_size = sizeof(rop);
1134 rop.pkt_end = sizeof(rop);
1135
1136 Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
1137 if (bstrcmp(dir->msg, endrestoreobjectcmd)) {
1138 GeneratePluginEvent(jcr, bEventRestoreObject, nullptr);
1139 return dir->fsend(OKRestoreObject);
1140 }
1141
1142 rop.plugin_name = (char *) malloc (dir->message_length);
1143 *rop.plugin_name = 0;
1144
1145 if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, &rop.object_full_len, &rop.object_index,
1146 &rop.object_type, &rop.object_compression, &FileIndex, rop.plugin_name) != 8) {
1147 /*
1148 * Old version, no plugin_name
1149 */
1150 if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len, &rop.object_full_len, &rop.object_index,
1151 &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
1152 Dmsg0(5, "Bad restore object command\n");
1153 PmStrcpy(jcr->errmsg, dir->msg);
1154 Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
1155 goto bail_out;
1156 }
1157 }
1158
1159 UnbashSpaces(rop.plugin_name);
1160
1161 Dmsg7(100,
1162 "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
1163 "FI=%d plugin_name=%s\n",
1164 rop.JobId, rop.object_len, rop.object_full_len, rop.object_index, rop.object_type, FileIndex,
1165 rop.plugin_name);
1166
1167 /*
1168 * Read Object name
1169 */
1170 if (dir->recv() < 0) { goto bail_out; }
1171 Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->message_length, dir->msg);
1172 rop.object_name = bstrdup(dir->msg);
1173
1174 /*
1175 * Read Object
1176 */
1177 if (dir->recv() < 0) { goto bail_out; }
1178
1179 /*
1180 * Transfer object from message buffer, and get new message buffer
1181 */
1182 rop.object = dir->msg;
1183 dir->msg = GetPoolMemory(PM_MESSAGE);
1184
1185 /*
1186 * If object is compressed, uncompress it
1187 */
1188 switch (rop.object_compression) {
1189 case 1: { /* zlib level 9 */
1190 int status;
1191 int out_len = rop.object_full_len + 100;
1192 POOLMEM *obj = GetMemory(out_len);
1193
1194 Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
1195 status = Zinflate(rop.object, rop.object_len, obj, out_len);
1196 Dmsg1(100, "Zinflate status=%d\n", status);
1197
1198 if (out_len != rop.object_full_len) {
1199 Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object_name=%s\n"),
1200 rop.object_full_len, out_len, rop.object_name);
1201 }
1202
1203 FreePoolMemory(rop.object); /* Release compressed object */
1204 rop.object = obj; /* New uncompressed object */
1205 rop.object_len = out_len;
1206 break;
1207 }
1208 default:
1209 break;
1210 }
1211
1212 if (debug_level >= 100) {
1213 PoolMem object_content(PM_MESSAGE);
1214
1215 /*
1216 * Convert the object into a null terminated string.
1217 */
1218 object_content.check_size(rop.object_len + 1);
1219 memset(object_content.c_str(), 0, rop.object_len + 1);
1220 memcpy(object_content.c_str(), rop.object, rop.object_len);
1221
1222 Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, object_content.c_str());
1223 }
1224
1225 /*
1226 * We still need to do this to detect a vss restore
1227 */
1228 if (bstrcmp(rop.object_name, "job_metadata.xml")) {
1229 Dmsg0(100, "got job metadata\n");
1230 jcr->got_metadata = true;
1231 }
1232
1233 GeneratePluginEvent(jcr, bEventRestoreObject, (void *)&rop);
1234
1235 if (rop.object_name) { free(rop.object_name); }
1236
1237 if (rop.object) { FreePoolMemory(rop.object); }
1238
1239 if (rop.plugin_name) { free(rop.plugin_name); }
1240
1241 Dmsg1(100, "Send: %s", OKRestoreObject);
1242 return true;
1243
1244 bail_out:
1245 dir->fsend(_("2909 Bad RestoreObject command.\n"));
1246 return false;
1247 }
1248
1249 #if defined(WIN32_VSS)
CountIncludeListFileEntries(JobControlRecord * jcr)1250 static inline int CountIncludeListFileEntries(JobControlRecord *jcr)
1251 {
1252 int cnt = 0;
1253 findFILESET *fileset;
1254 findIncludeExcludeItem *incexe;
1255
1256 fileset = jcr->ff->fileset;
1257 if (fileset) {
1258 for (int i = 0; i < fileset->include_list.size(); i++) {
1259 incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
1260 cnt += incexe->name_list.size();
1261 }
1262 }
1263
1264 return cnt;
1265 }
1266 #endif
1267
1268 /**
1269 * Director is passing his Fileset
1270 */
FilesetCmd(JobControlRecord * jcr)1271 static bool FilesetCmd(JobControlRecord *jcr)
1272 {
1273 BareosSocket *dir = jcr->dir_bsock;
1274 bool retval;
1275 #if defined(WIN32_VSS)
1276 int vss = 0;
1277
1278 sscanf(dir->msg, "fileset vss=%d", &vss);
1279 #endif
1280
1281 if (!InitFileset(jcr)) { return false; }
1282
1283 while (dir->recv() >= 0) {
1284 StripTrailingJunk(dir->msg);
1285 Dmsg1(500, "Fileset: %s\n", dir->msg);
1286 AddFileset(jcr, dir->msg);
1287 }
1288
1289 if (!TermFileset(jcr)) { return false; }
1290
1291 #if defined(WIN32_VSS)
1292 jcr->enable_vss = (vss && (CountIncludeListFileEntries(jcr) > 0)) ? true : false;
1293 #endif
1294
1295 retval = dir->fsend(OKinc);
1296 GeneratePluginEvent(jcr, bEventEndFileSet);
1297 CheckIncludeListShadowing(jcr, jcr->ff->fileset);
1298
1299 return retval;
1300 }
1301
FreeBootstrap(JobControlRecord * jcr)1302 static void FreeBootstrap(JobControlRecord *jcr)
1303 {
1304 if (jcr->RestoreBootstrap) {
1305 SecureErase(jcr, jcr->RestoreBootstrap);
1306 FreePoolMemory(jcr->RestoreBootstrap);
1307 jcr->RestoreBootstrap = nullptr;
1308 }
1309 }
1310
1311 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1312 static uint32_t bsr_uniq = 0;
1313
1314 /**
1315 * The Director sends us the bootstrap file, which
1316 * we will in turn pass to the SD.
1317 * Deprecated. The bsr is now sent directly from the
1318 * Director to the SD.
1319 */
BootstrapCmd(JobControlRecord * jcr)1320 static bool BootstrapCmd(JobControlRecord *jcr)
1321 {
1322 BareosSocket *dir = jcr->dir_bsock;
1323 POOLMEM *fname = GetPoolMemory(PM_FNAME);
1324 FILE *bs;
1325
1326 FreeBootstrap(jcr);
1327 P(bsr_mutex);
1328 bsr_uniq++;
1329 Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->name(), jcr->Job, bsr_uniq);
1330 V(bsr_mutex);
1331 Dmsg1(400, "bootstrap=%s\n", fname);
1332 jcr->RestoreBootstrap = fname;
1333 bs = fopen(fname, "a+b"); /* create file */
1334 if (!bs) {
1335 BErrNo be;
1336 Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"), jcr->RestoreBootstrap,
1337 be.bstrerror());
1338 /*
1339 * Suck up what he is sending to us so that he will then
1340 * read our error message.
1341 */
1342 while (dir->recv() >= 0) {}
1343 FreeBootstrap(jcr);
1344 jcr->setJobStatus(JS_ErrorTerminated);
1345 return false;
1346 }
1347
1348 while (dir->recv() >= 0) {
1349 Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
1350 fputs(dir->msg, bs);
1351 }
1352 fclose(bs);
1353 /*
1354 * Note, do not free the bootstrap yet -- it needs to be sent to the SD
1355 */
1356 return dir->fsend(OKbootstrap);
1357 }
1358
1359 /**
1360 * Get backup level from Director
1361 */
LevelCmd(JobControlRecord * jcr)1362 static bool LevelCmd(JobControlRecord *jcr)
1363 {
1364 BareosSocket *dir = jcr->dir_bsock;
1365 POOLMEM *level, *buf = nullptr;
1366 int mtime_only;
1367
1368 level = GetMemory(dir->message_length+1);
1369 Dmsg1(10, "LevelCmd: %s", dir->msg);
1370
1371 /*
1372 * Keep compatibility with older directors
1373 */
1374 if (strstr(dir->msg, "accurate")) { jcr->accurate = true; }
1375 if (strstr(dir->msg, "rerunning")) { jcr->rerunning = true; }
1376 if (sscanf(dir->msg, "level = %s ", level) != 1) { goto bail_out; }
1377
1378 if (bstrcmp(level, "base")) {
1379 /*
1380 * Base backup requested
1381 */
1382 jcr->setJobLevel(L_BASE);
1383 } else if (bstrcmp(level, "full")) {
1384 /*
1385 * Full backup requested
1386 */
1387 jcr->setJobLevel(L_FULL);
1388 } else if (strstr(level, "differential")) {
1389 jcr->setJobLevel(L_DIFFERENTIAL);
1390 FreeMemory(level);
1391 return true;
1392 } else if (strstr(level, "incremental")) {
1393 jcr->setJobLevel(L_INCREMENTAL);
1394 FreeMemory(level);
1395 return true;
1396 } else if (bstrcmp(level, "since_utime")) {
1397 char ed1[50], ed2[50];
1398
1399 /*
1400 * We get his UTC since time, then sync the clocks and correct it to agree with our clock.
1401 */
1402 buf = GetMemory(dir->message_length+1);
1403 utime_t since_time, adj;
1404 btime_t his_time, bt_start, rt=0, bt_adj=0;
1405 if (jcr->getJobLevel() == L_NONE) { jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */ }
1406
1407 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s", buf, &mtime_only,
1408 jcr->PrevJob) != 3) {
1409 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d", buf, &mtime_only) != 2) { goto bail_out; }
1410 }
1411
1412 since_time = str_to_uint64(buf); /* this is the since time */
1413 Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1414 /*
1415 * Sync clocks by polling him for the time. We take 10 samples of his time throwing out the first two.
1416 */
1417 for (int i = 0; i < 10; i++) {
1418 bt_start = GetCurrentBtime();
1419 dir->signal(BNET_BTIME); /* poll for time */
1420 if (dir->recv() <= 0) { /* get response */
1421 goto bail_out;
1422 }
1423 if (sscanf(dir->msg, "btime %s", buf) != 1) { goto bail_out; }
1424 if (i < 2) { /* toss first two results */
1425 continue;
1426 }
1427 his_time = str_to_uint64(buf);
1428 rt = GetCurrentBtime() - bt_start; /* compute round trip time */
1429 Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1), edit_uint64(bt_start, ed2));
1430 bt_adj += bt_start - his_time - rt/2;
1431 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1432 }
1433
1434 bt_adj = bt_adj / 8; /* compute average time */
1435 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1436 adj = BtimeToUtime(bt_adj);
1437 since_time += adj; /* adjust for clock difference */
1438
1439 /*
1440 * Don't notify if time within 3 seconds
1441 */
1442 if (adj > 3 || adj < -3) {
1443 int type;
1444 if (adj > 600 || adj < -600) {
1445 type = M_WARNING;
1446 } else {
1447 type = M_INFO;
1448 }
1449 Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1450 }
1451 dir->signal(BNET_EOD);
1452
1453 Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1454 jcr->incremental = true; /* set incremental or decremental backup */
1455 jcr->mtime = since_time; /* set since time */
1456 GeneratePluginEvent(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1457 } else {
1458 Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1459 FreeMemory(level);
1460 return false;
1461 }
1462
1463 FreeMemory(level);
1464 if (buf) { FreeMemory(buf); }
1465
1466 GeneratePluginEvent(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1467
1468 return dir->fsend(OKlevel);
1469
1470 bail_out:
1471 PmStrcpy(jcr->errmsg, dir->msg);
1472 Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1473 FreeMemory(level);
1474 if (buf) { FreeMemory(buf); }
1475 return false;
1476 }
1477
1478 /**
1479 * Get session parameters from Director -- this is for a Restore command
1480 * This is deprecated. It is now passed via the bsr.
1481 */
SessionCmd(JobControlRecord * jcr)1482 static bool SessionCmd(JobControlRecord *jcr)
1483 {
1484 BareosSocket *dir = jcr->dir_bsock;
1485
1486 Dmsg1(100, "SessionCmd: %s", dir->msg);
1487 if (sscanf(dir->msg, sessioncmd, jcr->VolumeName, &jcr->VolSessionId, &jcr->VolSessionTime, &jcr->StartFile,
1488 &jcr->EndFile, &jcr->StartBlock, &jcr->EndBlock) != 7) {
1489 PmStrcpy(jcr->errmsg, dir->msg);
1490 Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1491 return false;
1492 }
1493
1494 return dir->fsend(OKsession);
1495 }
1496
SetStorageAuthKeyAndTlsPolicy(JobControlRecord * jcr,char * key,TlsPolicy policy)1497 static void SetStorageAuthKeyAndTlsPolicy(JobControlRecord *jcr, char *key, TlsPolicy policy)
1498 {
1499 /* if no key don't update anything */
1500 if (!*key) { return; }
1501
1502 /**
1503 * We can be contacting multiple storage daemons.
1504 * So, make sure that any old jcr->store_bsock is cleaned up.
1505 */
1506 if (jcr->store_bsock) {
1507 delete jcr->store_bsock;
1508 jcr->store_bsock = nullptr;
1509 }
1510
1511 /**
1512 * We can be contacting multiple storage daemons.
1513 * So, make sure that any old jcr->sd_auth_key is cleaned up.
1514 */
1515 if (jcr->sd_auth_key) {
1516 /*
1517 * If we already have a Authorization key, director can do multi storage restore
1518 */
1519 Dmsg0(5, "set multi_restore=true\n");
1520 jcr->multi_restore = true;
1521 bfree(jcr->sd_auth_key);
1522 }
1523
1524 jcr->sd_auth_key = bstrdup(key);
1525 Dmsg0(5, "set sd auth key\n");
1526
1527 jcr->sd_tls_policy = policy;
1528 Dmsg1(5, "set sd ssl_policy to %d\n", policy);
1529
1530 }
1531
1532 /**
1533 * Get address of storage daemon from Director
1534 */
StorageCmd(JobControlRecord * jcr)1535 static bool StorageCmd(JobControlRecord *jcr)
1536 {
1537 int stored_port; /* storage daemon port */
1538 TlsPolicy tls_policy; /* enable ssl to sd */
1539 char stored_addr[MAX_NAME_LENGTH];
1540 PoolMem sd_auth_key(PM_MESSAGE);
1541 BareosSocket *dir = jcr->dir_bsock;
1542 BareosSocket *storage_daemon_socket = New(BareosSocketTCP);
1543
1544 if (me->nokeepalive) { storage_daemon_socket->ClearKeepalive(); }
1545 Dmsg1(100, "StorageCmd: %s", dir->msg);
1546 sd_auth_key.check_size(dir->message_length);
1547 if (sscanf(dir->msg, storaddrv1cmd, stored_addr, &stored_port, &tls_policy, sd_auth_key.c_str()) != 4) {
1548 if (sscanf(dir->msg, storaddrv0cmd, stored_addr, &stored_port, &tls_policy) != 3) {
1549 PmStrcpy(jcr->errmsg, dir->msg);
1550 Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1551 goto bail_out;
1552 }
1553 }
1554
1555 SetStorageAuthKeyAndTlsPolicy(jcr, sd_auth_key.c_str(), tls_policy);
1556
1557 Dmsg3(110, "Open storage: %s:%d ssl=%d\n", stored_addr, stored_port, tls_policy);
1558
1559 storage_daemon_socket->SetSourceAddress(me->FDsrc_addr);
1560
1561 /*
1562 * TODO: see if we put limit on restore and backup...
1563 */
1564 if (!jcr->max_bandwidth) {
1565 if (jcr->director->max_bandwidth_per_job) {
1566 jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
1567 } else if (me->max_bandwidth_per_job) {
1568 jcr->max_bandwidth = me->max_bandwidth_per_job;
1569 }
1570 }
1571
1572 storage_daemon_socket->SetBwlimit(jcr->max_bandwidth);
1573 if (me->allow_bw_bursting) { storage_daemon_socket->SetBwlimitBursting(); }
1574
1575 /*
1576 * Open command communications with Storage daemon
1577 */
1578 if (!storage_daemon_socket->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval, _("Storage daemon"),
1579 stored_addr, nullptr, stored_port, 1)) {
1580 Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"), stored_addr, stored_port);
1581 Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n", stored_addr, stored_port);
1582 goto bail_out;
1583 }
1584 Dmsg0(110, "Connection OK to SD.\n");
1585
1586 jcr->store_bsock = storage_daemon_socket;
1587
1588 if (tls_policy == TlsPolicy::kBnetTlsAuto) {
1589 std::string qualified_resource_name;
1590 if (!my_config->GetQualifiedResourceNameTypeConverter()->ResourceToString(
1591 jcr->Job, R_JOB, qualified_resource_name)) {
1592 goto bail_out;
1593 }
1594
1595 if (!storage_daemon_socket->DoTlsHandshake(TlsPolicy::kBnetTlsAuto, me, false,
1596 qualified_resource_name.c_str(), jcr->sd_auth_key, jcr)) {
1597 jcr->store_bsock = nullptr;
1598 goto bail_out;
1599 }
1600 }
1601
1602 storage_daemon_socket->fsend("Hello Start Job %s\n", jcr->Job);
1603 if (!AuthenticateWithStoragedaemon(jcr)) {
1604 Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1605 goto bail_out;
1606 }
1607 Dmsg0(110, "Authenticated with SD.\n");
1608
1609 /*
1610 * Send OK to Director
1611 */
1612 return dir->fsend(OKstore);
1613
1614 bail_out:
1615 delete storage_daemon_socket;
1616 jcr->store_bsock = nullptr;
1617 dir->fsend(BADcmd, "storage");
1618 return false;
1619 }
1620
LogFlagStatus(JobControlRecord * jcr,int flag,const char * flag_text)1621 static void LogFlagStatus(JobControlRecord *jcr, int flag, const char *flag_text)
1622 {
1623 findFILESET *fileset = jcr->ff->fileset;
1624 bool found = false;
1625 if (fileset) {
1626 for (int i = 0; i < fileset->include_list.size() && !found; i++) {
1627 findIncludeExcludeItem *incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
1628
1629 for (int j = 0; j < incexe->opts_list.size() && !found; j++) {
1630 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1631
1632 if (BitIsSet(flag, fo->flags)) {
1633 found = true;
1634 }
1635 }
1636 }
1637 }
1638
1639 std::string m = flag_text;
1640 m += found ? "is enabled\n" : "is disabled\n";
1641 Jmsg(jcr, M_INFO, 0, m.c_str());
1642 }
1643
1644
1645 /**
1646 * Clear a flag in the find options.
1647 *
1648 * We walk the list of include blocks and for each option block
1649 * check if a certain flag is set and clear that.
1650 */
ClearFlagInFileset(JobControlRecord * jcr,int flag,const char * warning)1651 static inline void ClearFlagInFileset(JobControlRecord *jcr, int flag, const char *warning)
1652 {
1653 findFILESET *fileset;
1654 bool cleared_flag = false;
1655
1656 fileset = jcr->ff->fileset;
1657 if (fileset) {
1658 for (int i = 0; i < fileset->include_list.size(); i++) {
1659 findIncludeExcludeItem *incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
1660
1661 for (int j = 0; j < incexe->opts_list.size(); j++) {
1662 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1663
1664 if (BitIsSet(flag, fo->flags)) {
1665 ClearBit(flag, fo->flags);
1666 cleared_flag = true;
1667 }
1668 }
1669 }
1670 }
1671
1672 if (cleared_flag) { Jmsg(jcr, M_WARNING, 0, warning); }
1673 }
1674
1675 /**
1676 * Clear a compression flag in the find options.
1677 *
1678 * We walk the list of include blocks and for each option block
1679 * check if a certain compression flag is set and clear that.
1680 */
ClearCompressionFlagInFileset(JobControlRecord * jcr)1681 static inline void ClearCompressionFlagInFileset(JobControlRecord *jcr)
1682 {
1683 findFILESET *fileset;
1684
1685 fileset = jcr->ff->fileset;
1686 if (fileset) {
1687 for (int i = 0; i < fileset->include_list.size(); i++) {
1688 findIncludeExcludeItem *incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
1689
1690 for (int j = 0; j < incexe->opts_list.size(); j++) {
1691 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1692
1693 /*
1694 * See if a compression flag is set in this option block.
1695 */
1696 if (BitIsSet(FO_COMPRESS, fo->flags)) {
1697 switch (fo->Compress_algo) {
1698 #if defined(HAVE_LIBZ)
1699 case COMPRESS_GZIP:
1700 break;
1701 #endif
1702 #if defined(HAVE_LZO)
1703 case COMPRESS_LZO1X:
1704 break;
1705 #endif
1706 #if defined(HAVE_FASTLZ)
1707 case COMPRESS_FZFZ:
1708 case COMPRESS_FZ4L:
1709 case COMPRESS_FZ4H:
1710 break;
1711 #endif
1712 default:
1713 /*
1714 * When we get here its because the wanted compression protocol is not
1715 * supported with the current compile options.
1716 */
1717 Jmsg(jcr, M_WARNING, 0,
1718 "%s compression support requested in fileset but not available on this platform. Disabling "
1719 "...\n",
1720 cmprs_algo_to_text(fo->Compress_algo));
1721 ClearBit(FO_COMPRESS, fo->flags);
1722 fo->Compress_algo = 0;
1723 break;
1724 }
1725 }
1726 }
1727 }
1728 }
1729 }
1730
1731 /**
1732 * Find out what encryption cipher to use.
1733 */
GetWantedCryptoCipher(JobControlRecord * jcr,crypto_cipher_t * cipher)1734 static inline bool GetWantedCryptoCipher(JobControlRecord *jcr, crypto_cipher_t *cipher)
1735 {
1736 findFILESET *fileset;
1737 bool force_encrypt = false;
1738 crypto_cipher_t wanted_cipher = CRYPTO_CIPHER_NONE;
1739
1740 /*
1741 * Walk the fileset and check for the FO_FORCE_ENCRYPT flag and any forced crypto cipher.
1742 */
1743 fileset = jcr->ff->fileset;
1744 if (fileset) {
1745 for (int i = 0; i < fileset->include_list.size(); i++) {
1746 findIncludeExcludeItem *incexe = (findIncludeExcludeItem *)fileset->include_list.get(i);
1747
1748 for (int j = 0; j < incexe->opts_list.size(); j++) {
1749 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1750
1751 if (BitIsSet(FO_FORCE_ENCRYPT, fo->flags)) { force_encrypt = true; }
1752
1753 if (fo->Encryption_cipher != CRYPTO_CIPHER_NONE) {
1754 /*
1755 * Make sure we have not found a cipher definition before.
1756 */
1757 if (wanted_cipher != CRYPTO_CIPHER_NONE) {
1758 Jmsg(jcr, M_FATAL, 0, _("Fileset contains multiple cipher settings\n"));
1759 return false;
1760 }
1761
1762 /*
1763 * See if pki_encrypt is already set for this Job.
1764 */
1765 if (!jcr->crypto.pki_encrypt) {
1766 if (!me->pki_keypair_file) {
1767 Jmsg(jcr, M_FATAL, 0,
1768 _("Fileset contains cipher settings but PKI Key Pair is not configured\n"));
1769 return false;
1770 }
1771
1772 /*
1773 * Enable encryption and signing for this Job.
1774 */
1775 jcr->crypto.pki_sign = true;
1776 jcr->crypto.pki_encrypt = true;
1777 }
1778
1779 wanted_cipher = (crypto_cipher_t)fo->Encryption_cipher;
1780 }
1781 }
1782 }
1783 }
1784
1785 /*
1786 * See if fileset forced a certain cipher.
1787 */
1788 if (wanted_cipher == CRYPTO_CIPHER_NONE) { wanted_cipher = me->pki_cipher; }
1789
1790 /*
1791 * See if we are in compatible mode then we are hardcoded to CRYPTO_CIPHER_AES_128_CBC.
1792 */
1793 if (me->compatible) { wanted_cipher = CRYPTO_CIPHER_AES_128_CBC; }
1794
1795 /*
1796 * See if FO_FORCE_ENCRYPT is set and encryption is not configured for the filed.
1797 */
1798 if (force_encrypt && !jcr->crypto.pki_encrypt) {
1799 Jmsg(jcr, M_FATAL, 0, _("Fileset forces encryption but encryption is not configured\n"));
1800 return false;
1801 }
1802
1803 *cipher = wanted_cipher;
1804
1805 return true;
1806 }
1807
1808 /**
1809 * Do a backup.
1810 */
BackupCmd(JobControlRecord * jcr)1811 static bool BackupCmd(JobControlRecord *jcr)
1812 {
1813 int ok = 0;
1814 int SDJobStatus;
1815 int32_t FileIndex;
1816 BareosSocket *dir = jcr->dir_bsock;
1817 BareosSocket *sd = jcr->store_bsock;
1818 crypto_cipher_t cipher = CRYPTO_CIPHER_NONE;
1819
1820 /*
1821 * See if we are in restore only mode then we don't allow a backup to be initiated.
1822 */
1823 if (restore_only_mode) {
1824 Jmsg(jcr, M_FATAL, 0, _("Filed in restore only mode, backups are not allowed, aborting...\n"));
1825 goto cleanup;
1826 }
1827
1828 /*
1829 * See if we are allowed to run backup cmds.
1830 */
1831 if (!ValidateCommand(jcr, "backup",
1832 (jcr->director && jcr->director->allowed_job_cmds) ? jcr->director->allowed_job_cmds
1833 : me->allowed_job_cmds)) {
1834 goto cleanup;
1835 }
1836
1837 #if defined(WIN32_VSS)
1838 if (jcr->enable_vss) { VSSInit(jcr); }
1839 #endif
1840
1841 if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1842 jcr->JobFiles = FileIndex;
1843 Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1844 }
1845
1846 /**
1847 * Validate some options given to the backup make sense for the compiled in options of this filed.
1848 */
1849 #ifndef HAVE_WIN32
1850 if (!have_acl) {
1851 ClearFlagInFileset(
1852 jcr, FO_ACL,
1853 _("ACL support requested in fileset but not available on this platform. Disabling ...\n"));
1854 }
1855
1856 if (!have_xattr) {
1857 ClearFlagInFileset(
1858 jcr, FO_XATTR,
1859 _("XATTR support requested in fileset but not available on this platform. Disabling ...\n"));
1860 }
1861 #endif
1862 if (!have_encryption) {
1863 ClearFlagInFileset(
1864 jcr, FO_ENCRYPT,
1865 _("Encryption support requested in fileset but not available on this platform. Disabling ...\n"));
1866 }
1867
1868 ClearCompressionFlagInFileset(jcr);
1869
1870 #ifndef HAVE_WIN32
1871 LogFlagStatus(jcr, FO_XATTR, "Extended attribute support ");
1872 LogFlagStatus(jcr, FO_ACL, "ACL support ");
1873 #endif
1874 if (!GetWantedCryptoCipher(jcr, &cipher)) {
1875 dir->fsend(BADcmd, "backup");
1876 goto cleanup;
1877 }
1878
1879 jcr->setJobStatus(JS_Blocked);
1880 jcr->setJobType(JT_BACKUP);
1881 Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1882
1883 if (sd == nullptr) {
1884 Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1885 dir->fsend(BADcmd, "backup");
1886 goto cleanup;
1887 }
1888
1889 dir->fsend(OKbackup);
1890 Dmsg1(110, "filed>dird: %s", dir->msg);
1891
1892 /**
1893 * Send Append Open Session to Storage daemon
1894 */
1895 sd->fsend(append_open);
1896 Dmsg1(110, ">stored: %s", sd->msg);
1897
1898 /**
1899 * Expect to receive back the Ticket number
1900 */
1901 if (BgetMsg(sd) >= 0) {
1902 Dmsg1(110, "<stored: %s", sd->msg);
1903 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1904 Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1905 goto cleanup;
1906 }
1907 Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1908 } else {
1909 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1910 goto cleanup;
1911 }
1912
1913 /**
1914 * Send Append data command to Storage daemon
1915 */
1916 sd->fsend(append_data, jcr->Ticket);
1917 Dmsg1(110, ">stored: %s", sd->msg);
1918
1919 /**
1920 * Expect to get OK data
1921 */
1922 if (!response(jcr, sd, OK_data, "Append Data")) {
1923 Dmsg1(110, "<stored: %s", sd->msg);
1924 goto cleanup;
1925 }
1926 Dmsg1(110, "<stored: %s", sd->msg);
1927
1928 GeneratePluginEvent(jcr, bEventStartBackupJob);
1929
1930 #if defined(WIN32_VSS)
1931 /*
1932 * START VSS ON WIN32
1933 */
1934 if (jcr->pVSSClient) {
1935 if (jcr->pVSSClient->InitializeForBackup(jcr)) {
1936 int drive_count;
1937 char szWinDriveLetters[27];
1938 bool onefs_disabled;
1939
1940 GeneratePluginEvent(jcr, bEventVssBackupAddComponents);
1941
1942 /*
1943 * Tell vss which drives to snapshot
1944 */
1945 *szWinDriveLetters = 0;
1946
1947 /*
1948 * Plugin driver can return drive letters
1949 */
1950 GeneratePluginEvent(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1951
1952 drive_count = get_win32_driveletters(jcr->ff->fileset, szWinDriveLetters);
1953
1954 onefs_disabled = win32_onefs_is_disabled(jcr->ff->fileset);
1955
1956 if (drive_count > 0) {
1957 Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"),
1958 jcr->pVSSClient->GetDriverName(), (drive_count) ? szWinDriveLetters : "None");
1959
1960 if (!jcr->pVSSClient->CreateSnapshots(szWinDriveLetters, onefs_disabled)) {
1961 BErrNo be;
1962 Jmsg(jcr, M_FATAL, 0, _("CreateSGenerate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1963 } else {
1964 GeneratePluginEvent(jcr, bEventVssCreateSnapshots);
1965
1966 /*
1967 * Inform about VMPs if we have them
1968 */
1969 jcr->pVSSClient->ShowVolumeMountPointStats(jcr);
1970
1971 /*
1972 * Tell user if snapshot creation of a specific drive failed
1973 */
1974 for (int i = 0; i < (int)strlen(szWinDriveLetters); i++) {
1975 if (islower(szWinDriveLetters[i])) {
1976 Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"),
1977 szWinDriveLetters[i]);
1978 }
1979 }
1980
1981 /*
1982 * Inform user about writer states
1983 */
1984 for (int i = 0; i < (int)jcr->pVSSClient->GetWriterCount(); i++) {
1985 if (jcr->pVSSClient->GetWriterState(i) < 1) {
1986 Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"),
1987 jcr->pVSSClient->GetWriterInfo(i));
1988 }
1989 }
1990 }
1991
1992 } else {
1993 Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1994 }
1995 } else {
1996 BErrNo be;
1997
1998 Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1999 }
2000
2001 RunScripts(jcr, jcr->RunScripts, "ClientAfterVSS",
2002 (jcr->director && jcr->director->allowed_script_dirs) ? jcr->director->allowed_script_dirs
2003 : me->allowed_script_dirs);
2004 }
2005 #endif
2006
2007 /**
2008 * Send Files to Storage daemon
2009 */
2010 Dmsg1(110, "begin blast ff=%p\n", (FindFilesPacket *)jcr->ff);
2011 if (!BlastDataToStorageDaemon(jcr, nullptr, cipher)) {
2012 jcr->setJobStatus(JS_ErrorTerminated);
2013 BnetSuppressErrorMessages(sd, 1);
2014 Dmsg0(110, "Error in blast_data.\n");
2015 } else {
2016 jcr->setJobStatus(JS_Terminated);
2017 /* Note, the above set status will not override an error */
2018 if (!jcr->IsTerminatedOk()) {
2019 BnetSuppressErrorMessages(sd, 1);
2020 goto cleanup; /* bail out now */
2021 }
2022 /**
2023 * Expect to get response to append_data from Storage daemon
2024 */
2025 if (!response(jcr, sd, OK_append, "Append Data")) {
2026 jcr->setJobStatus(JS_ErrorTerminated);
2027 goto cleanup;
2028 }
2029
2030 /**
2031 * Send Append End Data to Storage daemon
2032 */
2033 sd->fsend(append_end, jcr->Ticket);
2034 /* Get end OK */
2035 if (!response(jcr, sd, OK_end, "Append End")) {
2036 jcr->setJobStatus(JS_ErrorTerminated);
2037 goto cleanup;
2038 }
2039
2040 /**
2041 * Send Append Close to Storage daemon
2042 */
2043 sd->fsend(append_close, jcr->Ticket);
2044 while (BgetMsg(sd) >= 0) { /* stop on signal or error */
2045 if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2046 ok = 1;
2047 Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2048 }
2049 }
2050 if (!ok) {
2051 Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2052 goto cleanup;
2053 }
2054 if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
2055 Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"), SDJobStatus);
2056 }
2057 }
2058
2059 cleanup:
2060 #if defined(WIN32_VSS)
2061 if (jcr->pVSSClient) { jcr->pVSSClient->DestroyWriterInfo(); }
2062 #endif
2063
2064 GeneratePluginEvent(jcr, bEventEndBackupJob);
2065 return false; /* return and stop command loop */
2066 }
2067
2068 /**
2069 * Do a Verify for Director
2070 *
2071 */
VerifyCmd(JobControlRecord * jcr)2072 static bool VerifyCmd(JobControlRecord *jcr)
2073 {
2074 char level[100];
2075 BareosSocket *dir = jcr->dir_bsock;
2076 BareosSocket *sd = jcr->store_bsock;
2077
2078 /*
2079 * See if we are allowed to run verify cmds.
2080 */
2081 if (!ValidateCommand(jcr, "verify",
2082 (jcr->director && jcr->director->allowed_job_cmds) ? jcr->director->allowed_job_cmds
2083 : me->allowed_job_cmds)) {
2084 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2085 return 0;
2086 }
2087
2088 jcr->setJobType(JT_VERIFY);
2089 if (sscanf(dir->msg, verifycmd, level) != 1) {
2090 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2091 return false;
2092 }
2093
2094 if (Bstrcasecmp(level, "init")) {
2095 jcr->setJobLevel(L_VERIFY_INIT);
2096 } else if (Bstrcasecmp(level, "catalog")){
2097 jcr->setJobLevel(L_VERIFY_CATALOG);
2098 } else if (Bstrcasecmp(level, "volume")){
2099 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2100 } else if (Bstrcasecmp(level, "data")){
2101 jcr->setJobLevel(L_VERIFY_DATA);
2102 } else if (Bstrcasecmp(level, "disk_to_catalog")) {
2103 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2104 } else {
2105 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2106 return false;
2107 }
2108
2109 dir->fsend(OKverify);
2110
2111 GeneratePluginEvent(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2112 GeneratePluginEvent(jcr, bEventStartVerifyJob);
2113
2114 Dmsg1(110, "filed>dird: %s", dir->msg);
2115
2116 switch (jcr->getJobLevel()) {
2117 case L_VERIFY_INIT:
2118 case L_VERIFY_CATALOG:
2119 DoVerify(jcr);
2120 break;
2121 case L_VERIFY_VOLUME_TO_CATALOG:
2122 if (!OpenSdReadSession(jcr)) { return false; }
2123 StartDirHeartbeat(jcr);
2124 DoVerifyVolume(jcr);
2125 StopDirHeartbeat(jcr);
2126 /*
2127 * Send Close session command to Storage daemon
2128 */
2129 sd->fsend(read_close, jcr->Ticket);
2130 Dmsg1(130, "filed>stored: %s", sd->msg);
2131
2132 /* ****FIXME**** check response */
2133 BgetMsg(sd); /* get OK */
2134
2135 /* Inform Storage daemon that we are done */
2136 sd->signal(BNET_TERMINATE);
2137
2138 break;
2139 case L_VERIFY_DISK_TO_CATALOG:
2140 DoVerify(jcr);
2141 break;
2142 default:
2143 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2144 return false;
2145 }
2146
2147 dir->signal(BNET_EOD);
2148 GeneratePluginEvent(jcr, bEventEndVerifyJob);
2149 return false; /* return and Terminate command loop */
2150 }
2151
2152 /**
2153 * Open connection to Director.
2154 */
connect_to_director(JobControlRecord * jcr,DirectorResource * dir_res,bool verbose)2155 static BareosSocket *connect_to_director(JobControlRecord *jcr, DirectorResource *dir_res, bool verbose)
2156 {
2157 ASSERT(dir_res != nullptr);
2158
2159 BareosSocketUniquePtr director_socket = MakeNewBareosSocketUniquePtr();
2160
2161 if (me->nokeepalive) { director_socket->ClearKeepalive(); }
2162
2163 director_socket->SetSourceAddress(me->FDsrc_addr);
2164
2165 int retry_interval = 0;
2166 int max_retry_time = 0;
2167 utime_t heart_beat = me->heartbeat_interval;
2168 if (!director_socket->connect(jcr, retry_interval, max_retry_time, heart_beat, dir_res->name(), dir_res->address,
2169 nullptr, dir_res->port, verbose)) {
2170 return nullptr;
2171 }
2172
2173 if (dir_res->IsTlsConfigured()) {
2174 std::string qualified_resource_name;
2175 if (!my_config->GetQualifiedResourceNameTypeConverter()->ResourceToString(me->hdr.name, my_config->r_own_,
2176 qualified_resource_name)) {
2177 Dmsg0(100, "Could not generate qualified resource name for a storage resource\n");
2178 return nullptr;
2179 }
2180
2181 if (!director_socket->DoTlsHandshake(TlsPolicy::kBnetTlsAuto, dir_res, false, qualified_resource_name.c_str(),
2182 dir_res->password_.value, jcr)) {
2183 Dmsg0(100, "Could not DoTlsHandshake() with director\n");
2184 return nullptr;
2185 }
2186 }
2187
2188 Dmsg1(10, "Opened connection with Director %s\n", dir_res->name());
2189 jcr->dir_bsock = director_socket.get();
2190
2191 director_socket->fsend(hello_client, my_name, FD_PROTOCOL_VERSION);
2192 if (!AuthenticateWithDirector(jcr, dir_res)) {
2193 jcr->dir_bsock = nullptr;
2194 return nullptr;
2195 }
2196
2197 director_socket->recv();
2198 ParseOkVersion(director_socket->msg);
2199
2200 jcr->director = dir_res;
2201
2202 return director_socket.release();
2203 }
2204
2205 /**
2206 * Do a Restore for Director
2207 */
RestoreCmd(JobControlRecord * jcr)2208 static bool RestoreCmd(JobControlRecord *jcr)
2209 {
2210 BareosSocket *dir = jcr->dir_bsock;
2211 BareosSocket *sd = jcr->store_bsock;
2212 POOLMEM *args;
2213 bool use_regexwhere = false;
2214 bool retval;
2215 int prefix_links;
2216 char replace;
2217
2218 /*
2219 * See if we are in backup only mode then we don't allow a restore to be initiated.
2220 */
2221 if (backup_only_mode) {
2222 Jmsg(jcr, M_FATAL, 0, _("Filed in backup only mode, restores are not allowed, aborting...\n"));
2223 return false;
2224 }
2225
2226 /*
2227 * See if we are allowed to run restore cmds.
2228 */
2229 if (!ValidateCommand(jcr, "restore",
2230 (jcr->director && jcr->director->allowed_job_cmds) ? jcr->director->allowed_job_cmds
2231 : me->allowed_job_cmds)) {
2232 return 0;
2233 }
2234
2235 jcr->setJobType(JT_RESTORE);
2236
2237 /**
2238 * Scan WHERE (base directory for restore) from command
2239 */
2240 Dmsg0(100, "restore command\n");
2241
2242 /*
2243 * Pickup where string
2244 */
2245 args = GetMemory(dir->message_length+1);
2246 *args = 0;
2247
2248 if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2249 if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2250 if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2251 PmStrcpy(jcr->errmsg, dir->msg);
2252 Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2253 return false;
2254 }
2255 *args = 0;
2256 }
2257 use_regexwhere = true;
2258 }
2259
2260 #if defined(WIN32_VSS)
2261 /**
2262 * No need to enable VSS for restore if we do not have plugin data to restore
2263 */
2264 jcr->enable_vss = jcr->got_metadata;
2265
2266 if (jcr->enable_vss) { VSSInit(jcr); }
2267 #endif
2268
2269 /*
2270 * Turn / into nothing
2271 */
2272 if (IsPathSeparator(args[0]) && args[1] == '\0') { args[0] = '\0'; }
2273
2274 Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2275 UnbashSpaces(args);
2276
2277 /*
2278 * Keep track of newly created directories to apply them correct attributes
2279 */
2280 if (replace == REPLACE_NEVER) { jcr->keep_path_list = true; }
2281
2282 if (use_regexwhere) {
2283 jcr->where_bregexp = get_bregexps(args);
2284 if (!jcr->where_bregexp) {
2285 Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2286 FreePoolMemory(args);
2287 return false;
2288 }
2289 } else {
2290 jcr->where = bstrdup(args);
2291 }
2292
2293 FreePoolMemory(args);
2294 jcr->replace = replace;
2295 jcr->prefix_links = prefix_links;
2296
2297 dir->fsend(OKrestore);
2298 Dmsg1(110, "filed>dird: %s", dir->msg);
2299
2300 jcr->setJobStatus(JS_Blocked);
2301
2302 if (!OpenSdReadSession(jcr)) {
2303 jcr->setJobStatus(JS_ErrorTerminated);
2304 goto bail_out;
2305 }
2306
2307 jcr->setJobStatus(JS_Running);
2308
2309 /**
2310 * Do restore of files and data
2311 */
2312 StartDirHeartbeat(jcr);
2313 GeneratePluginEvent(jcr, bEventStartRestoreJob);
2314
2315 #if defined(WIN32_VSS)
2316 /*
2317 * START VSS ON WIN32
2318 */
2319 if (jcr->pVSSClient) {
2320 if (!jcr->pVSSClient->InitializeForRestore(jcr)) {
2321 BErrNo be;
2322 Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"),
2323 be.bstrerror());
2324 }
2325
2326 GeneratePluginEvent(jcr, bEventVssRestoreLoadComponentMetadata);
2327
2328 RunScripts(jcr, jcr->RunScripts, "ClientAfterVSS",
2329 (jcr->director && jcr->director->allowed_script_dirs) ? jcr->director->allowed_script_dirs
2330 : me->allowed_script_dirs);
2331 }
2332 #endif
2333
2334 DoRestore(jcr);
2335 StopDirHeartbeat(jcr);
2336
2337 if (jcr->JobWarnings) {
2338 jcr->setJobStatus(JS_Warnings);
2339 } else {
2340 jcr->setJobStatus(JS_Terminated);
2341 }
2342
2343 /**
2344 * Send Close session command to Storage daemon
2345 */
2346 sd->fsend(read_close, jcr->Ticket);
2347 Dmsg1(100, "filed>stored: %s", sd->msg);
2348
2349 BgetMsg(sd); /* get OK */
2350
2351 /* Inform Storage daemon that we are done */
2352 sd->signal(BNET_TERMINATE);
2353
2354 #if defined(WIN32_VSS)
2355 /*
2356 * STOP VSS ON WIN32
2357 * Tell vss to close the restore session
2358 */
2359 if (jcr->pVSSClient) {
2360 Dmsg0(100, "About to call CloseRestore\n");
2361
2362 GeneratePluginEvent(jcr, bEventVssCloseRestore);
2363
2364 Dmsg0(100, "Really about to call CloseRestore\n");
2365 if (jcr->pVSSClient->CloseRestore()) {
2366 Dmsg0(100, "CloseRestore success\n");
2367 /*
2368 * Inform user about writer states
2369 */
2370 for (int i = 0; i < (int)jcr->pVSSClient->GetWriterCount(); i++) {
2371 int msg_type = M_INFO;
2372
2373 if (jcr->pVSSClient->GetWriterState(i) < 1) {
2374 msg_type = M_WARNING;
2375 jcr->JobErrors++;
2376 }
2377 Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), jcr->pVSSClient->GetWriterInfo(i));
2378 }
2379 } else {
2380 Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2381 }
2382 }
2383 #endif
2384
2385 bail_out:
2386 BfreeAndNull(jcr->where);
2387
2388 if (jcr->JobErrors) { jcr->setJobStatus(JS_ErrorTerminated); }
2389
2390 Dmsg0(100, "Done in job.c\n");
2391
2392 if (jcr->multi_restore) {
2393 Dmsg0(100, OKstoreend);
2394 dir->fsend(OKstoreend);
2395 retval = true; /* we continue the loop, waiting for next part */
2396 } else {
2397 retval = false; /* we stop here */
2398 }
2399
2400 if (JobCanceled(jcr)) { retval = false; /* we stop here */ }
2401
2402 if (!retval) { EndRestoreCmd(jcr); /* stopping so send bEventEndRestoreJob */ }
2403
2404 return retval;
2405 }
2406
EndRestoreCmd(JobControlRecord * jcr)2407 static bool EndRestoreCmd(JobControlRecord *jcr)
2408 {
2409 Dmsg0(5, "EndRestoreCmd\n");
2410 GeneratePluginEvent(jcr, bEventEndRestoreJob);
2411 return false; /* return and Terminate command loop */
2412 }
2413
OpenSdReadSession(JobControlRecord * jcr)2414 static bool OpenSdReadSession(JobControlRecord *jcr)
2415 {
2416 BareosSocket *sd = jcr->store_bsock;
2417
2418 if (!sd) {
2419 Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2420 return false;
2421 }
2422 Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n", jcr->VolSessionId, jcr->VolSessionTime,
2423 jcr->StartFile, jcr->EndFile);
2424 Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2425 /*
2426 * Open Read Session with Storage daemon
2427 */
2428 sd->fsend(read_open, "DummyVolume", jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2429 jcr->StartBlock, jcr->EndBlock);
2430 Dmsg1(110, ">stored: %s", sd->msg);
2431
2432 /*
2433 * Get ticket number
2434 */
2435 if (BgetMsg(sd) >= 0) {
2436 Dmsg1(110, "filed<stored: %s", sd->msg);
2437 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2438 Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2439 return false;
2440 }
2441 Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2442 } else {
2443 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2444 return false;
2445 }
2446
2447 /*
2448 * Start read of data with Storage daemon
2449 */
2450 sd->fsend(read_data, jcr->Ticket);
2451 Dmsg1(110, ">stored: %s", sd->msg);
2452
2453 /*
2454 * Get OK data
2455 */
2456 if (!response(jcr, sd, OK_data, "Read Data")) { return false; }
2457
2458 return true;
2459 }
2460
2461 /**
2462 * Destroy the Job Control Record and associated resources (sockets).
2463 */
FiledFreeJcr(JobControlRecord * jcr)2464 static void FiledFreeJcr(JobControlRecord *jcr)
2465 {
2466 #if defined(WIN32_VSS)
2467 if (jcr->pVSSClient) {
2468 delete jcr->pVSSClient;
2469 jcr->pVSSClient = nullptr;
2470 }
2471 #endif
2472
2473 if (jcr->store_bsock) {
2474 jcr->store_bsock->close();
2475 delete jcr->store_bsock;
2476 jcr->store_bsock = nullptr;
2477 }
2478
2479 if (jcr->dir_bsock) {
2480 jcr->dir_bsock->close();
2481 delete jcr->dir_bsock;
2482 jcr->dir_bsock = nullptr;
2483 }
2484
2485 if (jcr->last_fname) { FreePoolMemory(jcr->last_fname); }
2486
2487 FreeBootstrap(jcr);
2488 FreeRunscripts(jcr->RunScripts);
2489 delete jcr->RunScripts;
2490
2491 if (jcr->path_list) {
2492 FreePathList(jcr->path_list);
2493 jcr->path_list = nullptr;
2494 }
2495
2496 TermFindFiles(jcr->ff);
2497 jcr->ff = nullptr;
2498
2499 if (jcr->JobId != 0) {
2500 WriteStateFile(me->working_directory, "bareos-fd", GetFirstPortHostOrder(me->FDaddrs));
2501 }
2502
2503 return;
2504 }
2505
2506 /**
2507 * Get response from Storage daemon to a command we sent.
2508 * Check that the response is OK.
2509 *
2510 * Returns: false on failure
2511 * true on success
2512 */
response(JobControlRecord * jcr,BareosSocket * sd,char * resp,const char * cmd)2513 bool response(JobControlRecord *jcr, BareosSocket *sd, char *resp, const char *cmd)
2514 {
2515 if (sd->errors) { return false; }
2516 if (BgetMsg(sd) > 0) {
2517 Dmsg0(110, sd->msg);
2518 if (bstrcmp(sd->msg, resp)) { return true; }
2519 }
2520 if (JobCanceled(jcr)) { return false; /* if canceled avoid useless error messages */ }
2521 if (IsBnetError(sd)) {
2522 Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"), cmd, BnetStrerror(sd));
2523 } else {
2524 Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"), cmd, resp, sd->msg);
2525 }
2526 return false;
2527 }
2528 } /* namespace filedaemon */
2529