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