/* send failed result */ void send_failed_result(gm_job_t * exec_job, int sig) { struct timeval end_time; char buffer[GM_BUFFERSIZE]; char * signame; buffer[0] = '\x0'; gm_log( GM_LOG_TRACE, "send_failed_result()\n"); gettimeofday(&end_time, NULL); exec_job->finish_time = end_time; exec_job->return_code = STATE_CRITICAL; signame = nr2signal(sig); snprintf( buffer, sizeof( buffer )-1, "(Return code of %d is out of bounds. Worker exited by signal %s on worker: %s)", sig, signame, mod_gm_opt->identifier); free(exec_job->output); exec_job->output = strdup( buffer ); free(signame); send_result_back(exec_job); return; }
int main(void) { plan(60); /* lowercase */ char test[100]; ok(lc(NULL) == NULL, "lc(NULL)"); strcpy(test, "Yes"); like(lc(test), "yes", "lc(yes)"); strcpy(test, "YES"); like(lc(test), "yes", "lc(YES)"); strcpy(test, "yeS"); like(lc(test), "yes", "lc(yeS)"); /* trim */ strcpy(test, " text "); like(ltrim(test), "text ", "ltrim()"); strcpy(test, " text "); like(rtrim(test), " text", "rtrim()"); strcpy(test, " text "); like(trim(test), "text", "trim()"); char *test2; test2 = strdup(" text "); like(trim(test2), "text", "trim()"); free(test2); /* parse_yes_or_no */ ok(parse_yes_or_no(NULL, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 1"); ok(parse_yes_or_no(NULL, GM_DISABLED) == GM_DISABLED, "parse_yes_or_no 2"); strcpy(test, ""); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 3"); strcpy(test, ""); ok(parse_yes_or_no(test, GM_DISABLED) == GM_DISABLED, "parse_yes_or_no 4"); strcpy(test, "yes"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 5"); strcpy(test, "true"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 6"); strcpy(test, "Yes"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 7"); strcpy(test, "1"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 8"); strcpy(test, "On"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_ENABLED, "parse_yes_or_no 9"); strcpy(test, "Off"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 10"); strcpy(test, "false"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 11"); strcpy(test, "no"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 12"); strcpy(test, "0"); ok(parse_yes_or_no(test, GM_ENABLED) == GM_DISABLED, "parse_yes_or_no 13"); /* trim */ ok(trim(NULL) == NULL, "trim(NULL)"); strcpy(test, " test "); like(trim(test), "^test$", "trim(' test ')"); strcpy(test, "\ntest\n"); like(trim(test), "^test$", "trim('\\ntest\\n')"); /* reading keys */ mod_gm_opt_t *mod_gm_opt; mod_gm_opt = malloc(sizeof(mod_gm_opt_t)); int rc = set_default_options(mod_gm_opt); ok(rc == 0, "setting default options"); mod_gm_opt->keyfile = strdup("t/data/test1.key"); read_keyfile(mod_gm_opt); //printf_hex(mod_gm_opt->crypt_key, 32); test[0]='\x0'; int i = 0; char hex[4]; for(i=0; i<32; i++) { hex[0] = '\x0'; snprintf(hex, 4, "%02x", mod_gm_opt->crypt_key[i]); strncat(test, hex, 4); } like(test, "3131313131313131313131313131313131313131313131313131313131310000", "read keyfile t/data/test1.key"); free(mod_gm_opt->keyfile); mod_gm_opt->keyfile = strdup("t/data/test2.key"); read_keyfile(mod_gm_opt); like(mod_gm_opt->crypt_key, "abcdef", "reading keyfile t/data/test2.key"); free(mod_gm_opt->keyfile); mod_gm_opt->keyfile = strdup("t/data/test3.key"); read_keyfile(mod_gm_opt); //printf_hex(mod_gm_opt->crypt_key, 32); like(mod_gm_opt->crypt_key, "11111111111111111111111111111111", "reading keyfile t/data/test3.key"); ok(strlen(mod_gm_opt->crypt_key) == 32, "key size for t/data/test3.key"); /* encrypt */ char * key = "test1234"; char * encrypted = malloc(GM_BUFFERSIZE); char * text = "test message"; char * base = "a7HqhQEE8TQBde9uknpPYQ=="; mod_gm_crypt_init(key); int len; len = mod_gm_encrypt(&encrypted, text, GM_ENCODE_AND_ENCRYPT); ok(len == 24, "length of encrypted only"); like(encrypted, base, "encrypted string"); /* decrypt */ char * decrypted = malloc(GM_BUFFERSIZE); mod_gm_decrypt(&decrypted, encrypted, GM_ENCODE_AND_ENCRYPT); like(decrypted, text, "decrypted text"); free(decrypted); free(encrypted); /* base 64 */ char * base64 = malloc(GM_BUFFERSIZE); len = mod_gm_encrypt(&base64, text, GM_ENCODE_ONLY); ok(len == 16, "length of encode only"); like(base64, "dGVzdCBtZXNzYWdl", "base64 only string"); /* debase 64 */ char * debase64 = malloc(GM_BUFFERSIZE); mod_gm_decrypt(&debase64, base64, GM_ENCODE_ONLY); like(debase64, text, "debase64 text"); free(debase64); free(base64); /* file_exists */ ok(file_exists("01_utils") == 1, "file_exists('01_utils')"); ok(file_exists("non-exist") == 0, "file_exists('non-exist')"); /* nr2signal */ char * signame1 = nr2signal(9); like(signame1, "SIGKILL", "get SIGKILL for 9"); free(signame1); char * signame2 = nr2signal(15); like(signame2, "SIGTERM", "get SIGTERM for 15"); free(signame2); /* string2timeval */ struct timeval t; string2timeval("100.50", &t); ok(t.tv_sec == 100, "string2timeval 1"); ok(t.tv_usec == 50, "string2timeval 2"); string2timeval("100", &t); ok(t.tv_sec == 100, "string2timeval 3"); ok(t.tv_usec == 0, "string2timeval 4"); string2timeval("", &t); ok(t.tv_sec == 0, "string2timeval 5"); ok(t.tv_usec == 0, "string2timeval 6"); string2timeval(NULL, &t); ok(t.tv_sec == 0, "string2timeval 7"); ok(t.tv_usec == 0, "string2timeval 8"); /* command line parsing */ mod_gm_free_opt(mod_gm_opt); mod_gm_opt = renew_opts(); strcpy(test, "server=host:4730"); parse_args_line(mod_gm_opt, test, 0); like(mod_gm_opt->server_list[0], "host:4730", "server=host:4730"); ok(mod_gm_opt->server_num == 1, "server_number = %d", mod_gm_opt->server_num); mod_gm_free_opt(mod_gm_opt); mod_gm_opt = renew_opts(); strcpy(test, "server=:4730"); parse_args_line(mod_gm_opt, test, 0); like(mod_gm_opt->server_list[0], "localhost:4730", "server=:4730"); ok(mod_gm_opt->server_num == 1, "server_number = %d", mod_gm_opt->server_num); mod_gm_free_opt(mod_gm_opt); mod_gm_opt = renew_opts(); strcpy(test, "server=localhost:4730"); parse_args_line(mod_gm_opt, test, 0); strcpy(test, "server=localhost:4730"); parse_args_line(mod_gm_opt, test, 0); like(mod_gm_opt->server_list[0], "localhost:4730", "duplicate server"); ok(mod_gm_opt->server_num == 1, "server_number = %d", mod_gm_opt->server_num); mod_gm_free_opt(mod_gm_opt); mod_gm_opt = renew_opts(); strcpy(test, "server=localhost:4730,localhost:4730,:4730,host:4730,"); parse_args_line(mod_gm_opt, test, 0); like(mod_gm_opt->server_list[0], "localhost:4730", "duplicate server"); like(mod_gm_opt->server_list[1], "host:4730", "duplicate server"); ok(mod_gm_opt->server_num == 2, "server_number = %d", mod_gm_opt->server_num); /* escape newlines */ char * escaped = gm_escape_newlines(" test\n", GM_DISABLED); is(escaped, " test\\n", "untrimmed escape string"); free(escaped); escaped = gm_escape_newlines(" test\n", GM_ENABLED); is(escaped, "test", "trimmed escape string"); free(escaped); /* md5 sum */ char * sum = NULL; strcpy(test, ""); sum = md5sum(test); like(sum, "d41d8cd98f00b204e9800998ecf8427e", "md5sum()"); free(sum); strcpy(test, "The quick brown fox jumps over the lazy dog."); sum = md5sum(test); like(sum, "e4d909c290d0fb1ca068ffaddf22cbd0", "md5sum()"); free(sum); mod_gm_free_opt(mod_gm_opt); return exit_status(); }
/* execute this command with given timeout */ int execute_safe_command(gm_job_t * exec_job, int fork_exec, char * identifier) { int pipe_stdout[2] , pipe_stderr[2]; int return_code; int pclose_result; char *plugin_output, *plugin_error; char *bufdup; char buffer[GM_BUFFERSIZE], buf_error[GM_BUFFERSIZE]; struct timeval start_time,end_time; pid_t pid = 0; buffer[0] = '\x0'; buf_error[0] = '\x0'; gm_log( GM_LOG_TRACE, "execute_safe_command()\n" ); // mark all filehandles to close on exec int x; for(x = 0; x<=64; x++) fcntl(x, F_SETFD, FD_CLOEXEC); signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); if(exec_job->start_time.tv_sec == 0) { gettimeofday(&start_time,NULL); exec_job->start_time = start_time; } /* fork a child process */ if(fork_exec == GM_ENABLED) { if(pipe(pipe_stdout) != 0) perror("pipe stdout"); if(pipe(pipe_stderr) != 0) perror("pipe stderr"); pid=fork(); /*fork error */ if( pid == -1 ) { exec_job->output = strdup("(Error On Fork)"); exec_job->return_code = 3; return(GM_ERROR); } } /* we are in the child process */ if( fork_exec == GM_DISABLED || pid == 0 ) { /* become the process group leader */ setpgid(0,0); pid = getpid(); if( fork_exec == GM_ENABLED ) { close(pipe_stdout[0]); close(pipe_stderr[0]); } signal(SIGALRM, check_alarm_handler); alarm(exec_job->timeout); /* run the plugin check command */ pclose_result = run_check(exec_job->command_line, &plugin_output, &plugin_error); return_code = pclose_result; if(fork_exec == GM_ENABLED) { if(write(pipe_stdout[1], plugin_output, strlen(plugin_output)+1) <= 0) perror("write stdout"); if(write(pipe_stderr[1], plugin_error, strlen(plugin_error)+1) <= 0) perror("write"); if(pclose_result == -1) { char error[GM_BUFFERSIZE]; snprintf(error, sizeof(error), "error on %s: %s", identifier, strerror(errno)); if(write(pipe_stdout[1], error, strlen(error)+1) <= 0) perror("write"); } return_code = real_exit_code(pclose_result); free(plugin_output); free(plugin_error); _exit(return_code); } else { snprintf( buffer, sizeof( buffer )-1, "%s", plugin_output ); snprintf( buf_error, sizeof( buf_error )-1, "%s", plugin_error ); free(plugin_output); free(plugin_error); } } /* we are the parent */ if( fork_exec == GM_DISABLED || pid > 0 ){ if( fork_exec == GM_ENABLED) { gm_log( GM_LOG_TRACE, "started check with pid: %d\n", pid); close(pipe_stdout[1]); close(pipe_stderr[1]); waitpid(pid, &return_code, 0); gm_log( GM_LOG_TRACE, "finished check from pid: %d with status: %d\n", pid, return_code); /* get all lines of plugin output */ if(read(pipe_stdout[0], buffer, sizeof(buffer)-1) < 0) perror("read"); if(read(pipe_stderr[0], buf_error, sizeof(buf_error)-1) < 0) perror("read"); } return_code = real_exit_code(return_code); /* file not executable? */ if(return_code == 126) { return_code = STATE_CRITICAL; snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. (worker: %s)", identifier); } /* file not found errors? */ else if(return_code == 127) { return_code = STATE_CRITICAL; snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. (worker: %s)", identifier); } /* signaled */ else if(return_code >= 128 && return_code < 144) { char * signame = nr2signal((int)(return_code-128)); bufdup = strdup(buffer); snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. Plugin exited by signal %s. (worker: %s)\\n%s", (int)(return_code), signame, identifier, bufdup); return_code = STATE_CRITICAL; free(bufdup); free(signame); } /* other error codes > 3 */ else if(return_code > 3) { gm_log( GM_LOG_DEBUG, "check exited with exit code > 3. Exit: %d\n", (int)(return_code)); gm_log( GM_LOG_DEBUG, "stdout: %s\n", buffer); bufdup = strdup(buffer); snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. (worker: %s)\\n%s", (int)(return_code), identifier, bufdup); free(bufdup); if(return_code != 25 && mod_gm_opt->workaround_rc_25 == GM_DISABLED) { return_code = STATE_CRITICAL; } } exec_job->output = strdup(buffer); exec_job->error = strdup(buf_error); exec_job->return_code = return_code; if( fork_exec == GM_ENABLED) { close(pipe_stdout[0]); close(pipe_stderr[0]); } } alarm(0); current_child_pid = 0; pid = 0; /* record check result info */ gettimeofday(&end_time, NULL); exec_job->finish_time = end_time; /* did we have a timeout? */ if(exec_job->timeout < ((int)end_time.tv_sec - (int)exec_job->start_time.tv_sec)) { exec_job->return_code = 2; exec_job->early_timeout = 1; if ( !strcmp( exec_job->type, "service" ) ) snprintf( buffer, sizeof( buffer ) -1, "(Service Check Timed Out On Worker: %s)", identifier); if ( !strcmp( exec_job->type, "host" ) ) snprintf( buffer, sizeof( buffer ) -1, "(Host Check Timed Out On Worker: %s)", identifier); free(exec_job->output); exec_job->output = strdup( buffer ); } return(GM_OK); }