From: Radosław Korzeniewski Date: Mon, 24 May 2021 15:14:13 +0000 (+0200) Subject: metaplugin: Fix #7678 About issue with queryParameter with an invalid plugin X-Git-Tag: Release-11.3.2~530 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac328e799cebd02651fa60cf6b495ba7638f7911;p=thirdparty%2Fbacula.git metaplugin: Fix #7678 About issue with queryParameter with an invalid plugin --- diff --git a/bacula/src/plugins/fd/pluginlib/metaplugin.cpp b/bacula/src/plugins/fd/pluginlib/metaplugin.cpp index c39c55db4..59c963e36 100644 --- a/bacula/src/plugins/fd/pluginlib/metaplugin.cpp +++ b/bacula/src/plugins/fd/pluginlib/metaplugin.cpp @@ -157,7 +157,7 @@ METAPLUGIN::METAPLUGIN(bpContext *bpctx) : replace(0), robjsent(false), estimate(false), - listing(ListingNone), + listing(None), nodata(false), nextfile(false), openerror(false), @@ -382,7 +382,7 @@ bRC METAPLUGIN::parse_plugin_command(bpContext *ctx, const char *command, alist if (strcasecmp(parser.argk[i], "listing") == 0){ /* found, so check the value if provided */ if (parser.argv[i]){ - listing = ListingMode; + listing = Listing; DMSG0(ctx, DINFO, "listing procedure param found\n"); } } @@ -390,7 +390,7 @@ bRC METAPLUGIN::parse_plugin_command(bpContext *ctx, const char *command, alist if (strcasecmp(parser.argk[i], "query") == 0){ /* found, so check the value if provided */ if (parser.argv[i]){ - listing = ListingQueryParams; + listing = Query; DMSG0(ctx, DINFO, "query procedure param found\n"); } } @@ -927,6 +927,21 @@ bRC METAPLUGIN::send_startlisting(bpContext *ctx) return send_startjob(ctx, "ListingStart\n"); } +/* + * Send "QueryStart" protocol command. + * more info at PLUGIN::send_startjob + * + * in: + * bpContext - for Bacula debug and jobinfo messages + * out: + * bRC_OK - when send command was successful + * bRC_Error - on any error + */ +bRC METAPLUGIN::send_startquery(bpContext *ctx) +{ + return send_startjob(ctx, "QueryStart\n"); +} + /* * Send "RestoreStart" protocol command. * more info at METAPLUGIN::send_startjob @@ -1041,8 +1056,7 @@ bRC METAPLUGIN::prepare_backend(bpContext *ctx, char type, char *command) } // check for prohibitted command duplication - if (type != BACKEND_JOB_INFO_RESTORE && backend.check_command(command)) - { + if (type != BACKEND_JOB_INFO_RESTORE && backend.check_command(command)) { // already exist, report DMSG1(ctx, DERROR, "Plugin command=%s already defined, cannot proceed.\n", command); JMSG1(ctx, M_FATAL, "Plugin command already defined: \"%s\" Cannot proceed. You should correct FileSet configuration.\n", command); @@ -1062,58 +1076,80 @@ bRC METAPLUGIN::prepare_backend(bpContext *ctx, char type, char *command) } /* handshake (1) */ DMSG0(ctx, DINFO, "Backend handshake...\n"); - if (!backend.ctx->handshake(ctx, PLUGINNAME, PLUGINAPI)) - { + if (!backend.ctx->handshake(ctx, PLUGINNAME, PLUGINAPI)) { backend.ctx->terminate(ctx); return bRC_Error; } /* Job Info (2) */ DMSG0(ctx, DINFO, "Job Info (2) ...\n"); - if (send_jobinfo(ctx, type) != bRC_OK){ + if (send_jobinfo(ctx, type) != bRC_OK) { backend.ctx->terminate(ctx); return bRC_Error; } /* Plugin Params (3) */ DMSG0(ctx, DINFO, "Plugin Params (3) ...\n"); - if (send_parameters(ctx, command) != bRC_OK){ + if (send_parameters(ctx, command) != bRC_OK) { backend.ctx->terminate(ctx); return bRC_Error; } - switch (type){ - case BACKEND_JOB_INFO_BACKUP: - /* Start Backup (4) */ - DMSG0(ctx, DINFO, "Start Backup (4) ...\n"); - if (send_startbackup(ctx) != bRC_OK){ - backend.ctx->terminate(ctx); - return bRC_Error; - } - break; - case BACKEND_JOB_INFO_ESTIMATE: - /* Start Estimate or Listing (4) */ - if (listing != ListingNone){ + switch (type) + { + case BACKEND_JOB_INFO_BACKUP: + /* Start Backup (4) */ + DMSG0(ctx, DINFO, "Start Backup (4) ...\n"); + if (send_startbackup(ctx) != bRC_OK){ + backend.ctx->terminate(ctx); + return bRC_Error; + } + break; + case BACKEND_JOB_INFO_ESTIMATE: + { + /* Start Estimate or Listing/Query (4) */ + bRC rc = bRC_Error; + switch (listing) + { + case Listing: DMSG0(ctx, DINFO, "Start Listing (4) ...\n"); - if (send_startlisting(ctx) != bRC_OK){ - backend.ctx->terminate(ctx); - return bRC_Error; - } - } else { + rc = send_startlisting(ctx); + break; + case Query: + DMSG0(ctx, DINFO, "Start Query Params (4) ...\n"); + rc = send_startquery(ctx); + break; + default: DMSG0(ctx, DINFO, "Start Estimate (4) ...\n"); - if (send_startestimate(ctx) != bRC_OK){ - backend.ctx->terminate(ctx); - return bRC_Error; - } + rc = send_startestimate(ctx); + break; } - break; - case BACKEND_JOB_INFO_RESTORE: - /* Start Restore (4) */ - DMSG0(ctx, DINFO, "Start Restore (4) ...\n"); - if (send_startrestore(ctx) != bRC_OK){ + if (rc != bRC_OK) { backend.ctx->terminate(ctx); return bRC_Error; } - break; - default: + } + // if (listing != ListingNone){ + // DMSG0(ctx, DINFO, "Start Listing (4) ...\n"); + // if (send_startlisting(ctx) != bRC_OK){ + // backend.ctx->terminate(ctx); + // return bRC_Error; + // } + // } else { + // DMSG0(ctx, DINFO, "Start Estimate (4) ...\n"); + // if (send_startestimate(ctx) != bRC_OK){ + // backend.ctx->terminate(ctx); + // return bRC_Error; + // } + // } + break; + case BACKEND_JOB_INFO_RESTORE: + /* Start Restore (4) */ + DMSG0(ctx, DINFO, "Start Restore (4) ...\n"); + if (send_startrestore(ctx) != bRC_OK) { + backend.ctx->terminate(ctx); return bRC_Error; + } + break; + default: + return bRC_Error; } DMSG0(ctx, DINFO, "Prepare backend done.\n"); return bRC_OK; @@ -2383,8 +2419,14 @@ bRC METAPLUGIN::queryParameter(bpContext *ctx, struct query_pkt *qp) DMSG0(ctx, D1, "METAPLUGIN::queryParameter\n"); - if (listing == ListingNone){ - listing = ListingQueryParams; + // check if it is our Plugin command + if (!isourplugincommand(PLUGINPREFIX, qp->command) != 0){ + // it is not our plugin prefix + return bRC_OK; + } + + if (listing == None) { + listing = Query; Mmsg(cmd, "%s query=%s", qp->command, qp->parameter); if (prepare_backend(ctx, BACKEND_JOB_INFO_ESTIMATE, cmd.c_str()) == bRC_Error){ return bRC_Error; @@ -2404,6 +2446,7 @@ bRC METAPLUGIN::queryParameter(bpContext *ctx, struct query_pkt *qp) DMSG0(ctx, D1, "METAPLUGIN::queryParameter: got EOD\n"); backend.ctx->signal_term(ctx); backend.ctx->terminate(ctx); + qp->result = NULL; ret = bRC_OK; } else { /* @@ -2736,7 +2779,7 @@ static bRC queryParameter(bpContext *ctx, struct query_pkt *qp) { ASSERT_CTX; - DMSG2(ctx, D1, "queryParameter: %s:%s\n", qp->command, qp->parameter); + DMSG2(ctx, D1, "queryParameter: cmd:%s param:%s\n", qp->command, qp->parameter); METAPLUGIN *self = pluginclass(ctx); return self->queryParameter(ctx, qp); } diff --git a/bacula/src/plugins/fd/pluginlib/metaplugin.h b/bacula/src/plugins/fd/pluginlib/metaplugin.h index 379d48f23..2e8408f51 100644 --- a/bacula/src/plugins/fd/pluginlib/metaplugin.h +++ b/bacula/src/plugins/fd/pluginlib/metaplugin.h @@ -91,12 +91,17 @@ public: enum MODE { NONE = 0, - BACKUP_FULL, - BACKUP_INCR, - BACKUP_DIFF, - Estimate, - Listing, - QueryParams, + Backup_Full, + BACKUP_FULL = Backup_Full, + Backup_Incr, + BACKUP_INCR = Backup_Incr, + Backup_Diff, + BACKUP_DIFF = Backup_Diff, + Estimate_Full, + Estimate_Incr, + Estimate_Diff, + // Listing, + // QueryParams, RESTORE, }; @@ -128,9 +133,9 @@ public: private: enum LISTING { - ListingNone, - ListingMode, - ListingQueryParams, + None, + Listing, + Query, }; // TODO: define a variable which will signal job cancel @@ -184,6 +189,7 @@ private: bRC send_startbackup(bpContext *ctx); bRC send_startestimate(bpContext *ctx); bRC send_startlisting(bpContext *ctx); + bRC send_startquery(bpContext *ctx); bRC send_startrestore(bpContext *ctx); bRC send_endjob(bpContext *ctx); bRC prepare_backend(bpContext *ctx, char type, char *command); diff --git a/bacula/src/plugins/fd/pluginlib/test_metaplugin_backend.c b/bacula/src/plugins/fd/pluginlib/test_metaplugin_backend.c index 4977d6e97..dd1d2ae97 100644 --- a/bacula/src/plugins/fd/pluginlib/test_metaplugin_backend.c +++ b/bacula/src/plugins/fd/pluginlib/test_metaplugin_backend.c @@ -702,10 +702,29 @@ void perform_listing(char *listing){ signal_eod(); } -void perform_restore(){ +/* + * The query param procedure + * return 3 simple parameters + */ +void perform_queryparam(char *query) +{ + /* Query Loop (5) */ + snprintf(buf, BIGBUFLEN, "%s=test1\n", query); + write_plugin('C', buf); + snprintf(buf, BIGBUFLEN, "%s=test2\n", query); + write_plugin('C', buf); + snprintf(buf, BIGBUFLEN, "%s=test3\n", query); + write_plugin('C', buf); - int len; - int fsize; + /* this is the end of all data */ + signal_eod(); +} + +/* + * The main and universal restore procedure + */ +void perform_restore() +{ bool loopgo = true; bool restore_skip_create = false; bool restore_with_core = false; @@ -792,7 +811,7 @@ void perform_restore(){ /* check if DATA command, so read the data packets */ if (strcmp(buf, "DATA\n") == 0){ - len = read_plugin(buf); + int len = read_plugin(buf); if (len == 0){ /* empty file to restore */ LOG("#> Empty file."); @@ -801,7 +820,7 @@ void perform_restore(){ LOG("#> file data saved."); } loopgo = true; - fsize = len; + int fsize = len; while (loopgo){ len = read_plugin(buf); fsize += len; @@ -833,6 +852,7 @@ int main(int argc, char** argv) { int len; char *listing; + char *query; buf = (char*)malloc(BIGBUFLEN); if (buf == NULL){ @@ -846,6 +866,10 @@ int main(int argc, char** argv) { if (listing == NULL){ exit(255); } + query = (char*)malloc(BUFLEN); + if (query == NULL){ + exit(255); + } mypid = getpid(); snprintf(buf, 4096, "%s/%s_backend_%d.log", LOGDIR, PLUGINNAME, mypid); @@ -929,6 +953,10 @@ int main(int argc, char** argv) { strcpy(listing, buf); continue; } + if (sscanf(buf, "query=%s\n", buf) == 1){ + strcpy(query, buf); + continue; + } } write_plugin('I', "TEST3"); if (!regress_error_plugin_params){ @@ -959,6 +987,9 @@ int main(int argc, char** argv) { if (strcmp(buf, "ListingStart\n") == 0){ perform_listing(listing); } else + if (strcmp(buf, "QueryStart\n") == 0){ + perform_queryparam(query); + } else if (strcmp(buf, "RestoreStart\n") == 0){ perform_restore(); } diff --git a/regress/scripts/metaplugin-protocol-tests.sh b/regress/scripts/metaplugin-protocol-tests.sh index d0fdeaa53..6fc8e7e1e 100755 --- a/regress/scripts/metaplugin-protocol-tests.sh +++ b/regress/scripts/metaplugin-protocol-tests.sh @@ -281,6 +281,41 @@ TEST=$((TEST+1)) done +# test query mode +TEST=1 + +cat <${cwd}/tmp/bconcmds +@# +@# Query +@# +@output /dev/null +messages +@$out ${cwd}/tmp/qlog${TEST}.out +setdebug level=500 client=$CLIENT trace=1 +.query client=$CLIENT plugin="$Plugin" parameter="m_id" +messages +@output +quit +END_OF_DATA +run_bconsole +TEST=$((TEST+1)) + +cat <${cwd}/tmp/bconcmds +@# +@# Query +@# +@output /dev/null +messages +@$out ${cwd}/tmp/qlog${TEST}.out +setdebug level=500 client=$CLIENT trace=1 +.query client=$CLIENT plugin="invalid" parameter="invalid" +messages +@output +quit +END_OF_DATA +run_bconsole +TEST=$((TEST+1)) + stop_bacula RET=$(grep "jobstatus:" ${cwd}/tmp/log1.out | awk '{print $2}') @@ -407,4 +442,18 @@ then rstat=5 fi +RET=$(grep -c "m_id=test" ${cwd}/tmp/qlog1.out) +if [ "$RET" -ne 3 ] +then + echo "qlog1" "$RET" + estat=2 +fi + +RET=$(grep -c "invalid=test" ${cwd}/tmp/qlog2.out) +if [ "$RET" -gt 0 ] +then + echo "qlog2" "$RET" + estat=3 +fi + end_test