void test_calculate_crc32(CuTest *tc) { char *data = "xi'an-chengdu-hangzhou-beijing"; uint32_t crc32 = calculate_crc32((uint8_t*)data, strlen(data)); CuAssertIntEquals(tc, -1266222823, crc32); crc32 = calculate_crc32((uint8_t*)data, strlen(data)); CuAssertIntEquals(tc, -1266222823, crc32); }
void readFrom(const char *buffer, std::size_t length) { if (buffer == NULL) throw nrpe::nrpe_exception("No buffer."); if (length != get_packet_length()) throw nrpe::nrpe_exception("Invalid packet length: " + strEx::s::xtos(length) + " != " + strEx::s::xtos(get_packet_length()) + " configured payload is: " + strEx::s::xtos(get_payload_length())); const nrpe::data::packet *p = reinterpret_cast<const nrpe::data::packet*>(buffer); type_ = swap_bytes::ntoh<int16_t>(p->packet_type); if ((type_ != nrpe::data::queryPacket)&&(type_ != nrpe::data::responsePacket)) throw nrpe::nrpe_exception("Invalid packet type: " + strEx::s::xtos(type_)); version_ = swap_bytes::ntoh<int16_t>(p->packet_version); if (version_ != nrpe::data::version2) throw nrpe::nrpe_exception("Invalid packet version." + strEx::s::xtos(version_)); crc32_ = swap_bytes::ntoh<u_int32_t>(p->crc32_value); // Verify CRC32 // @todo Fix this, currently we need a const buffer so we cannot change the CRC to 0. char * tb = new char[length+1]; memcpy(tb, buffer, length); nrpe::data::packet *p2 = reinterpret_cast<nrpe::data::packet*>(tb); p2->crc32_value = 0; calculatedCRC32_ = calculate_crc32(tb, get_packet_length()); delete [] tb; if (crc32_ != calculatedCRC32_) throw nrpe::nrpe_exception("Invalid checksum in NRPE packet: " + strEx::s::xtos(crc32_) + "!=" + strEx::s::xtos(calculatedCRC32_)); // Verify CRC32 end result_ = swap_bytes::ntoh<int16_t>(p->result_code); payload_ = fetch_payload(p); }
int pl_decompress(pl_buffer *input, pl_buffer **output, const char *key, int check_compression) { pl_buffer *result; unsigned int data_size, real_size, *header, header_size, crc32_ptr_compresed, i; char *data; if(!input) return PL_DECOMP_INVALID; if(check_compression && pl_check_compression(input) != PL_CHECK_COMPRESSESED) { return PL_DECOMP_CHECK_COMP; } *output = NULL; header = (unsigned int*)((char*)input->buffer + pl_header_magic_text_size); // skip version ++header; // get crc32 of compressed crc32_ptr_compresed = *header++; // get real size real_size = *header++; // get compressed size data_size = *header; header_size = PL_HEADER_ITEMS_SIZE + pl_header_magic_text_size; // check buffer crc if(crc32_ptr_compresed != calculate_crc32((char*)input->buffer + header_size, data_size)) { return PL_DECOMP_WRONG_KEY; } // decompress result = pl_buf_create(real_size + 16); // with dummy if(!result) { return PL_DECOMP_MEMORY; } result->length = lzf_decompress((char*)input->buffer + header_size, data_size, result->buffer, result->allocated_size); if(result->length == 0) { pl_buf_destroy(result); return PL_DECOMP_DECOMPRESS; } result->length = real_size; *output = result; return PL_DECOMP_OK; }
const char* create_buffer() { delete [] tmpBuffer; unsigned int packet_length = nrpe::length::get_packet_length(payload_length_); tmpBuffer = new char[packet_length+1]; memset(tmpBuffer, 0, packet_length+1); nrpe::data::packet *p = reinterpret_cast<nrpe::data::packet*>(tmpBuffer); p->result_code = swap_bytes::hton<int16_t>(result_); p->packet_type = swap_bytes::hton<int16_t>(type_); p->packet_version = swap_bytes::hton<int16_t>(version_); if (payload_.length() >= payload_length_) throw nrpe::nrpe_exception("To much data cant create return packet (truncate data)"); update_payload(p, payload_); p->crc32_value = 0; crc32_ = p->crc32_value = swap_bytes::hton<u_int32_t>(calculate_crc32(tmpBuffer, packet_length)); return tmpBuffer; }
/* tests whether or not a client request is valid */ int validate_request(packet *pkt){ u_int32_t packet_crc32; u_int32_t calculated_crc32; char *ptr; #ifdef ENABLE_COMMAND_ARGUMENTS int x; #endif /***** DECRYPT REQUEST ******/ /* check the crc 32 value */ packet_crc32=ntohl(pkt->crc32_value); pkt->crc32_value=0L; calculated_crc32=calculate_crc32((char *)pkt,sizeof(packet)); if(packet_crc32!=calculated_crc32){ syslog(LOG_ERR,"Error: Request packet had invalid CRC32."); return ERROR; } /* make sure this is the right type of packet */ if(ntohs(pkt->packet_type)!=QUERY_PACKET || ntohs(pkt->packet_version)!=NRPE_PACKET_VERSION_2){ syslog(LOG_ERR,"Error: Request packet type/version was invalid!"); return ERROR; } /* make sure buffer is terminated */ pkt->buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; /* client must send some kind of request */ if(!strcmp(pkt->buffer,"")){ syslog(LOG_ERR,"Error: Request contained no query!"); return ERROR; } /* make sure request doesn't contain nasties */ if(contains_nasty_metachars(pkt->buffer)==TRUE){ syslog(LOG_ERR,"Error: Request contained illegal metachars!"); return ERROR; } /* make sure the request doesn't contain arguments */ if(strchr(pkt->buffer,'!')){ #ifdef ENABLE_COMMAND_ARGUMENTS if(allow_arguments==FALSE){ syslog(LOG_ERR,"Error: Request contained command arguments, but argument option is not enabled!"); return ERROR; } #else syslog(LOG_ERR,"Error: Request contained command arguments!"); return ERROR; #endif } /* get command name */ #ifdef ENABLE_COMMAND_ARGUMENTS ptr=strtok(pkt->buffer,"!"); #else ptr=pkt->buffer; #endif command_name=strdup(ptr); if(command_name==NULL){ syslog(LOG_ERR,"Error: Memory allocation failed"); return ERROR; } #ifdef ENABLE_COMMAND_ARGUMENTS /* get command arguments */ if(allow_arguments==TRUE){ for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){ ptr=strtok(NULL,"!"); if(ptr==NULL) break; macro_argv[x]=strdup(ptr); if(macro_argv[x]==NULL){ syslog(LOG_ERR,"Error: Memory allocation failed"); return ERROR; } if(!strcmp(macro_argv[x],"")){ syslog(LOG_ERR,"Error: Request contained an empty command argument"); return ERROR; } } } #endif return OK; }
/* handles a client connection */ void handle_connection(int sock){ u_int32_t calculated_crc32; command *temp_command; packet receive_packet; packet send_packet; int bytes_to_send; int bytes_to_recv; char buffer[MAX_INPUT_BUFFER]; char raw_command[MAX_INPUT_BUFFER]; char processed_command[MAX_INPUT_BUFFER]; int result=STATE_OK; int early_timeout=FALSE; int rc; int x; #ifdef DEBUG FILE *errfp; #endif #ifdef HAVE_SSL SSL *ssl=NULL; #endif /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Handling the connection..."); #ifdef OLDSTUFF /* socket should be non-blocking */ fcntl(sock,F_SETFL,O_NONBLOCK); #endif /* set connection handler */ signal(SIGALRM,my_connection_sighandler); alarm(connection_timeout); #ifdef HAVE_SSL /* do SSL handshake */ if(result==STATE_OK && use_ssl==TRUE){ if((ssl=SSL_new(ctx))!=NULL){ SSL_set_fd(ssl,sock); /* keep attempting the request if needed */ while(((rc=SSL_accept(ssl))!=1) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); if(rc!=1){ syslog(LOG_ERR,"Error: Could not complete SSL handshake. %d\n",SSL_get_error(ssl,rc)); #ifdef DEBUG errfp=fopen("/tmp/err.log","w"); ERR_print_errors_fp(errfp); fclose(errfp); #endif return; } } else{ syslog(LOG_ERR,"Error: Could not create SSL connection structure.\n"); #ifdef DEBUG errfp=fopen("/tmp/err.log","w"); ERR_print_errors_fp(errfp); fclose(errfp); #endif return; } } #endif bytes_to_recv=sizeof(receive_packet); if(use_ssl==FALSE) rc=recvall(sock,(char *)&receive_packet,&bytes_to_recv,socket_timeout); #ifdef HAVE_SSL else{ while(((rc=SSL_read(ssl,&receive_packet,bytes_to_recv))<=0) && (SSL_get_error(ssl,rc)==SSL_ERROR_WANT_READ)); } #endif /* recv() error or client disconnect */ if(rc<=0){ /* log error to syslog facility */ syslog(LOG_ERR,"Could not read request from client, bailing out..."); #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); syslog(LOG_INFO,"INFO: SSL Socket Shutdown.\n"); } #endif return; } /* we couldn't read the correct amount of data, so bail out */ else if(bytes_to_recv!=sizeof(receive_packet)){ /* log error to syslog facility */ syslog(LOG_ERR,"Data packet from client was too short, bailing out..."); #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif return; } #ifdef DEBUG fp=fopen("/tmp/packet","w"); if(fp){ fwrite(&receive_packet,1,sizeof(receive_packet),fp); fclose(fp); } #endif /* make sure the request is valid */ if(validate_request(&receive_packet)==ERROR){ /* log an error */ syslog(LOG_ERR,"Client request was invalid, bailing out..."); /* free memory */ free(command_name); command_name=NULL; for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){ free(macro_argv[x]); macro_argv[x]=NULL; } #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif return; } /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Host is asking for command '%s' to be run...",receive_packet.buffer); /* disable connection alarm - a new alarm will be setup during my_system */ alarm(0); /* if this is the version check command, just spew it out */ if(!strcmp(command_name,NRPE_HELLO_COMMAND)){ snprintf(buffer,sizeof(buffer),"NRPE v%s",PROGRAM_VERSION); buffer[sizeof(buffer)-1]='\x0'; /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Response: %s",buffer); result=STATE_OK; } /* find the command we're supposed to run */ else{ temp_command=find_command(command_name); if(temp_command==NULL){ snprintf(buffer,sizeof(buffer),"NRPE: Command '%s' not defined",command_name); buffer[sizeof(buffer)-1]='\x0'; /* log error to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"%s",buffer); result=STATE_CRITICAL; } else{ /* process command line */ if(command_prefix==NULL) strncpy(raw_command,temp_command->command_line,sizeof(raw_command)-1); else snprintf(raw_command,sizeof(raw_command)-1,"%s %s",command_prefix,temp_command->command_line); raw_command[sizeof(raw_command)-1]='\x0'; process_macros(raw_command,processed_command,sizeof(processed_command)); /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Running command: %s",processed_command); /* run the command */ strcpy(buffer,""); result=my_system(processed_command,command_timeout,&early_timeout,buffer,sizeof(buffer)); /* log debug info */ if(debug==TRUE) syslog(LOG_DEBUG,"Command completed with return code %d and output: %s",result,buffer); /* see if the command timed out */ if(early_timeout==TRUE) snprintf(buffer,sizeof(buffer)-1,"NRPE: Command timed out after %d seconds\n",command_timeout); else if(!strcmp(buffer,"")) snprintf(buffer,sizeof(buffer)-1,"NRPE: Unable to read output\n"); buffer[sizeof(buffer)-1]='\x0'; /* check return code bounds */ if((result<0) || (result>3)){ /* log error to syslog facility */ syslog(LOG_ERR,"Bad return code for [%s]: %d", buffer,result); result=STATE_UNKNOWN; } } } /* free memory */ free(command_name); command_name=NULL; for(x=0;x<MAX_COMMAND_ARGUMENTS;x++){ free(macro_argv[x]); macro_argv[x]=NULL; } /* strip newline character from end of output buffer */ if(buffer[strlen(buffer)-1]=='\n') buffer[strlen(buffer)-1]='\x0'; /* clear the response packet buffer */ bzero(&send_packet,sizeof(send_packet)); /* fill the packet with semi-random data */ randomize_buffer((char *)&send_packet,sizeof(send_packet)); /* initialize response packet data */ send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2); send_packet.packet_type=(int16_t)htons(RESPONSE_PACKET); send_packet.result_code=(int16_t)htons(result); strncpy(&send_packet.buffer[0],buffer,MAX_PACKETBUFFER_LENGTH); send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; /* calculate the crc 32 value of the packet */ send_packet.crc32_value=(u_int32_t)0L; calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet)); send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32); /***** ENCRYPT RESPONSE *****/ /* send the response back to the client */ bytes_to_send=sizeof(send_packet); if(use_ssl==FALSE) sendall(sock,(char *)&send_packet,&bytes_to_send); #ifdef HAVE_SSL else SSL_write(ssl,&send_packet,bytes_to_send); #endif #ifdef HAVE_SSL if(ssl){ SSL_shutdown(ssl); SSL_free(ssl); } #endif /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Return Code: %d, Output: %s",result,buffer); return; }
int main(int argc, char **argv) { int sd; int rc; int result; data_packet send_packet; int bytes_to_send; char input[MAX_INPUT_BUFFER]; char input_buffer[MAX_INPUT_BUFFER]; char *temp_ptr; char host_name[MAX_HOSTNAME_LENGTH]; char svc_description[MAX_DESCRIPTION_LENGTH]; char plugin_output[MAX_PLUGINOUTPUT_LENGTH]; int total_packets = 0; int16_t return_code; u_int32_t calculated_crc32; char *inputptr, *ptr1, *ptr2, *ptr3, *ptr4; /* process command-line arguments */ result = process_arguments(argc, argv); if (result != OK || show_help == TRUE || show_license == TRUE || show_version == TRUE) { if (result != OK) printf("Incorrect command line arguments supplied\n"); printf("\n"); printf("NSCA Client %s\n", PROGRAM_VERSION); printf("Copyright (c) 2010-2012 Icinga Development Team and Community Contributors (http://www.icinga.org)\n"); printf("Copyright (c) 2000-2007 Ethan Galstad (www.nagios.org)\n"); printf("Last Modified: %s\n", MODIFICATION_DATE); printf("License: GPL v2\n"); printf("Encryption Routines: "); #ifdef HAVE_LIBMCRYPT printf("AVAILABLE"); #else printf("NOT AVAILABLE"); #endif printf("\n"); printf("\n"); } if (result != OK || show_help == TRUE) { printf("Usage: %s -H <host_address> [-p port] [-to to_sec] [-d delim] [-c config_file]\n", argv[0]); printf("\n"); printf("Options:\n"); printf(" <host_address> = The IP address of the host running the NSCA daemon\n"); printf(" [port] = The port on which the daemon is running - default is %s\n", DEFAULT_SERVER_PORT); printf(" [to_sec] = Number of seconds before connection attempt times out.\n"); printf(" (default timeout is %d seconds)\n", DEFAULT_SOCKET_TIMEOUT); printf(" [delim] = Delimiter to use when parsing input (defaults to a tab)\n"); printf(" [config_file] = Name of config file to use\n"); printf("\n"); printf("Note:\n"); printf("This utility is used to send passive check results to the NSCA daemon. Host and\n"); printf("Service check data that is to be sent to the NSCA daemon is read from standard\n"); printf("input. Input should be provided in the following format (tab-delimited unless\n"); printf("overriden with -d command line argument, one entry per line):\n"); printf("\n"); printf("Service Checks:\n"); printf("<host_name>[tab]<svc_description>[tab]<return_code>[tab]<plugin_output>[newline]\n\n"); printf("Host Checks:\n"); printf("<host_name>[tab]<return_code>[tab]<plugin_output>[newline]\n\n"); printf("When submitting multiple simultaneous results, separate each set with the ETB\n"); printf("character (^W or 0x17)\n"); printf("\n"); } if (show_license == TRUE) display_license(); if (result != OK || show_help == TRUE || show_license == TRUE || show_version == TRUE) do_exit(STATE_UNKNOWN); /* read the config file */ result = read_config_file(config_file); /* exit if there are errors... */ if (result == ERROR) { printf("Error: Config file '%s' contained errors...\n", config_file); do_exit(STATE_CRITICAL); } /* generate the CRC 32 table */ generate_crc32_table(); /* initialize alarm signal handling */ signal(SIGALRM, alarm_handler); /* set socket timeout */ alarm(socket_timeout); time(&start_time); /* try to connect to the host at the given port number */ result = my_tcp_connect(server_name, server_port, &sd); /* we couldn't connect */ if (result != STATE_OK) { printf("Error: Could not connect to host %s on port %s\n", server_name, server_port); do_exit(STATE_CRITICAL); } #ifdef DEBUG printf("Connected okay...\n"); #endif /* read the initialization packet containing the IV and timestamp */ result = read_init_packet(sd); if (result != OK) { printf("Error: Could not read init packet from server\n"); close(sd); do_exit(STATE_CRITICAL); } #ifdef DEBUG printf("Got init packet from server\n"); #endif /* initialize encryption/decryption routines with the IV we received from the server */ if (encrypt_init(password, encryption_method, received_iv, &CI) != OK) { printf("Error: Failed to initialize encryption libraries for method %d\n", encryption_method); close(sd); do_exit(STATE_CRITICAL); } #ifdef DEBUG printf("Initialized encryption routines\n"); #endif /**** WE'RE CONNECTED AND READY TO SEND ****/ /* read all data from STDIN until there isn't anymore */ while (!feof(stdin)) { int c = getc(stdin); if (c == -1) { break; } int pos = 0; while (c != 23) { if (c == -1) { // in case we don't terminate properly, or are in single-input mode. break; } input_buffer[pos] = c; c = getc(stdin); pos++; } input_buffer[pos] = 0; strip(input_buffer); if (!strcmp(input_buffer, "")) continue; /* get the host name */ ptr1 = strtok(input_buffer, delimiter); if (ptr1 == NULL) continue; /* get the service description or return code */ ptr2 = strtok(NULL, delimiter); if (ptr2 == NULL) continue; /* get the return code or plugin output */ ptr3 = strtok(NULL, delimiter); if (ptr3 == NULL) continue; /* get the plugin output - if NULL, this is a host check result */ ptr4 = strtok(NULL, "\x0"); strncpy(host_name, ptr1, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\x0'; if (ptr4 == NULL) { strcpy(svc_description, ""); return_code = atoi(ptr2); ptr3 = escape_newlines(ptr3); strncpy(plugin_output, ptr3, sizeof(plugin_output) - 1); } else { strncpy(svc_description, ptr2, sizeof(svc_description) - 1); return_code = atoi(ptr3); ptr4 = escape_newlines(ptr4); strncpy(plugin_output, ptr4, sizeof(plugin_output) - 1); } svc_description[sizeof(svc_description) - 1] = '\x0'; plugin_output[sizeof(plugin_output) - 1] = '\x0'; /* increment count of packets we're sending */ total_packets++; /* clear the packet buffer */ bzero(&send_packet, sizeof(send_packet)); /* fill the packet with semi-random data */ randomize_buffer((char *)&send_packet, sizeof(send_packet)); /* copy the data we want to send into the packet */ send_packet.packet_version = (int16_t)htons(NSCA_PACKET_VERSION_3); send_packet.return_code = (int16_t)htons(return_code); strcpy(&send_packet.host_name[0], host_name); strcpy(&send_packet.svc_description[0], svc_description); strcpy(&send_packet.plugin_output[0], plugin_output); /* use timestamp provided by the server */ send_packet.timestamp = (u_int32_t)htonl(packet_timestamp); /* calculate the crc 32 value of the packet */ send_packet.crc32_value = (u_int32_t)0L; calculated_crc32 = calculate_crc32((char *)&send_packet, sizeof(send_packet)); send_packet.crc32_value = (u_int32_t)htonl(calculated_crc32); /* encrypt the packet */ encrypt_buffer((char *)&send_packet, sizeof(send_packet), password, encryption_method, CI); /* send the packet */ bytes_to_send = sizeof(send_packet); rc = sendall(sd, (char *)&send_packet, &bytes_to_send); /* there was an error sending the packet */ if (rc == -1) { printf("Error: Could not send data to host\n"); close(sd); do_exit(STATE_UNKNOWN); } /* for some reason we didn't send all the bytes we were supposed to */ else if (bytes_to_send < sizeof(send_packet)) { printf("Warning: Sent only %d of %d bytes to host\n", rc, sizeof(send_packet)); close(sd); return STATE_UNKNOWN; } } #ifdef DEBUG printf("Done sending data\n"); #endif /* close the connection */ close(sd); printf("%d data packet(s) sent to host successfully.\n", total_packets); /* exit cleanly */ do_exit(STATE_OK); /* no compiler complaints here... */ return STATE_OK; }
int main(int argc, char **argv){ u_int32_t packet_crc32; u_int32_t calculated_crc32; int16_t result; int rc; packet send_packet; packet receive_packet; int bytes_to_send; int bytes_to_recv; result=process_arguments(argc,argv); if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ if(result!=OK) printf("Incorrect command line arguments supplied\n"); printf("\n"); printf("NRPE Plugin for Nagios\n"); printf("Copyright (c) 1999-2008 Ethan Galstad ([email protected])\n"); printf("Version: %s\n",PROGRAM_VERSION); printf("Last Modified: %s\n",MODIFICATION_DATE); printf("License: GPL v2 with exemptions (-l for more info)\n"); #ifdef HAVE_SSL printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); #endif printf("\n"); } if(result!=OK || show_help==TRUE){ printf("Usage: check_nrpe -H <host> [ -b <bindaddr> ] [-4] [-6] [-n] [-u] [-p <port>] [-t <timeout>] [-c <command>] [-a <arglist...>]\n"); printf("\n"); printf("Options:\n"); printf(" -n = Do no use SSL\n"); printf(" -u = Make socket timeouts return an UNKNOWN state instead of CRITICAL\n"); printf(" <host> = The address of the host running the NRPE daemon\n"); printf(" <bindaddr> = bind to local address\n"); printf(" -4 = user ipv4 only\n"); printf(" -6 = user ipv6 only\n"); printf(" [port] = The port on which the daemon is running (default=%d)\n",DEFAULT_SERVER_PORT); printf(" [timeout] = Number of seconds before connection times out (default=%d)\n",DEFAULT_SOCKET_TIMEOUT); printf(" [command] = The name of the command that the remote daemon should run\n"); printf(" [arglist] = Optional arguments that should be passed to the command. Multiple\n"); printf(" arguments should be separated by a space. If provided, this must be\n"); printf(" the last option supplied on the command line.\n"); printf("\n"); printf("Note:\n"); printf("This plugin requires that you have the NRPE daemon running on the remote host.\n"); printf("You must also have configured the daemon to associate a specific plugin command\n"); printf("with the [command] option you are specifying here. Upon receipt of the\n"); printf("[command] argument, the NRPE daemon will run the appropriate plugin command and\n"); printf("send the plugin output and return code back to *this* plugin. This allows you\n"); printf("to execute plugins on remote hosts and 'fake' the results to make Nagios think\n"); printf("the plugin is being run locally.\n"); printf("\n"); } if(show_license==TRUE) display_license(); if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) exit(STATE_UNKNOWN); /* generate the CRC 32 table */ generate_crc32_table(); #ifdef HAVE_SSL /* initialize SSL */ if(use_ssl==TRUE){ SSL_library_init(); SSLeay_add_ssl_algorithms(); meth=SSLv23_client_method(); SSL_load_error_strings(); if((ctx=SSL_CTX_new(meth))==NULL){ printf("CHECK_NRPE: Error - could not create SSL context.\n"); exit(STATE_CRITICAL); } /* ADDED 01/19/2004 */ /* use only TLSv1 protocol */ SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); } #endif /* initialize alarm signal handling */ signal(SIGALRM,alarm_handler); /* set socket timeout */ alarm(socket_timeout); /* try to connect to the host at the given port number */ if((sd=my_connect(server_name, &hostaddr, server_port, address_family, bind_address)) < 0 ) { exit (255); } else { result=STATE_OK; } #ifdef HAVE_SSL /* do SSL handshake */ if(result==STATE_OK && use_ssl==TRUE){ if((ssl=SSL_new(ctx))!=NULL){ SSL_CTX_set_cipher_list(ctx,"ADH"); SSL_set_fd(ssl,sd); if((rc=SSL_connect(ssl))!=1){ printf("CHECK_NRPE: Error - Could not complete SSL handshake.\n"); #ifdef DEBUG printf("SSL_connect=%d\n",rc); /* rc=SSL_get_error(ssl,rc); printf("SSL_get_error=%d\n",rc); printf("ERR_get_error=%lu\n",ERR_get_error()); printf("%s\n",ERR_error_string(rc,NULL)); */ ERR_print_errors_fp(stdout); #endif result=STATE_CRITICAL; } } else{ printf("CHECK_NRPE: Error - Could not create SSL connection structure.\n"); result=STATE_CRITICAL; } /* bail if we had errors */ if(result!=STATE_OK){ SSL_CTX_free(ctx); close(sd); exit(result); } } #endif /* we're connected and ready to go */ if(result==STATE_OK){ /* clear the packet buffer */ bzero(&send_packet,sizeof(send_packet)); /* fill the packet with semi-random data */ randomize_buffer((char *)&send_packet,sizeof(send_packet)); /* initialize packet data */ send_packet.packet_version=(int16_t)htons(NRPE_PACKET_VERSION_2); send_packet.packet_type=(int16_t)htons(QUERY_PACKET); strncpy(&send_packet.buffer[0],query,MAX_PACKETBUFFER_LENGTH); send_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; /* calculate the crc 32 value of the packet */ send_packet.crc32_value=(u_int32_t)0L; calculated_crc32=calculate_crc32((char *)&send_packet,sizeof(send_packet)); send_packet.crc32_value=(u_int32_t)htonl(calculated_crc32); /***** ENCRYPT REQUEST *****/ /* send the packet */ bytes_to_send=sizeof(send_packet); if(use_ssl==FALSE) rc=sendall(sd,(char *)&send_packet,&bytes_to_send); #ifdef HAVE_SSL else{ rc=SSL_write(ssl,&send_packet,bytes_to_send); if(rc<0) rc=-1; } #endif if(rc==-1){ printf("CHECK_NRPE: Error sending query to host.\n"); close(sd); return STATE_UNKNOWN; } /* wait for the response packet */ bytes_to_recv=sizeof(receive_packet); if(use_ssl==FALSE) rc=recvall(sd,(char *)&receive_packet,&bytes_to_recv,socket_timeout); #ifdef HAVE_SSL else rc=SSL_read(ssl,&receive_packet,bytes_to_recv); #endif /* reset timeout */ alarm(0); /* close the connection */ #ifdef HAVE_SSL if(use_ssl==TRUE){ SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); } #endif graceful_close(sd,1000); /* recv() error */ if(rc<0){ printf("CHECK_NRPE: Error receiving data from daemon.\n"); return STATE_UNKNOWN; } /* server disconnected */ else if(rc==0){ printf("CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages.\n"); return STATE_UNKNOWN; } /* receive underflow */ else if(bytes_to_recv<sizeof(receive_packet)){ printf("CHECK_NRPE: Receive underflow - only %d bytes received (%d expected).\n",bytes_to_recv,sizeof(receive_packet)); return STATE_UNKNOWN; } /***** DECRYPT RESPONSE *****/ /* check the crc 32 value */ packet_crc32=ntohl(receive_packet.crc32_value); receive_packet.crc32_value=0L; calculated_crc32=calculate_crc32((char *)&receive_packet,sizeof(receive_packet)); if(packet_crc32!=calculated_crc32){ printf("CHECK_NRPE: Response packet had invalid CRC32.\n"); close(sd); return STATE_UNKNOWN; } /* check packet version */ if(ntohs(receive_packet.packet_version)!=NRPE_PACKET_VERSION_2){ printf("CHECK_NRPE: Invalid packet version received from server.\n"); close(sd); return STATE_UNKNOWN; } /* check packet type */ if(ntohs(receive_packet.packet_type)!=RESPONSE_PACKET){ printf("CHECK_NRPE: Invalid packet type received from server.\n"); close(sd); return STATE_UNKNOWN; } /* get the return code from the remote plugin */ result=(int16_t)ntohs(receive_packet.result_code); /* print the output returned by the daemon */ receive_packet.buffer[MAX_PACKETBUFFER_LENGTH-1]='\x0'; if(!strcmp(receive_packet.buffer,"")) printf("CHECK_NRPE: No output returned from daemon.\n"); else printf("%s\n",receive_packet.buffer); } /* reset the alarm */ else alarm(0); return result; }
int WritePacket( const PacketReadWriteInfo & info, Packet * packet, uint8_t * buffer, int bufferSize ) { assert( packet ); assert( buffer ); assert( bufferSize > 0 ); assert( info.protocolId ); assert( info.packetFactory ); assert( info.streamAllocator ); const int numPacketTypes = info.packetFactory->GetNumPacketTypes(); WriteStream stream( buffer, bufferSize, *info.streamAllocator ); stream.SetContext( info.context ); for ( int i = 0; i < info.prefixBytes; ++i ) { uint8_t zero = 0; if ( !stream.SerializeBits( zero, 8 ) ) { debug_printf( "serialize prefix byte failed (write packet)\n" ); return 0; } } uint32_t crc32 = 0; if ( !info.rawFormat ) { if ( !stream.SerializeBits( crc32, 32 ) ) { debug_printf( "serialize crc32 failed (write packet)\n" ); return 0; } } int packetType = packet->GetType(); assert( numPacketTypes > 0 ); if ( numPacketTypes > 1 ) { if ( !stream.SerializeInteger( packetType, 0, numPacketTypes - 1 ) ) return 0; } if ( !packet->SerializeInternal( stream ) ) { debug_printf( "serialize packet type %d failed (write packet)\n", packetType ); return 0; } if ( !stream.SerializeCheck( "end of packet" ) ) { debug_printf( "serialize check at end of packed failed (write packet)\n" ); return 0; } stream.Flush(); if ( !info.rawFormat ) { uint32_t network_protocolId = host_to_network( info.protocolId ); crc32 = calculate_crc32( (uint8_t*) &network_protocolId, 4 ); crc32 = calculate_crc32( buffer + info.prefixBytes, stream.GetBytesProcessed() - info.prefixBytes, crc32 ); *((uint32_t*)(buffer+info.prefixBytes)) = host_to_network( crc32 ); } if ( stream.GetError() ) { debug_printf( "stream error %d (write packet)\n", stream.GetError() ); return 0; } return stream.GetBytesProcessed(); }
Packet * ReadPacket( const PacketReadWriteInfo & info, const uint8_t * buffer, int bufferSize, int * errorCode ) { assert( buffer ); assert( bufferSize > 0 ); assert( info.protocolId != 0 ); assert( info.packetFactory ); assert( info.streamAllocator ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_NONE; ReadStream stream( buffer, bufferSize, *info.streamAllocator ); stream.SetContext( info.context ); for ( int i = 0; i < info.prefixBytes; ++i ) { uint32_t dummy = 0; if ( !stream.SerializeBits( dummy, 8 ) ) { debug_printf( "serialize prefix byte failed (read packet)\n" ); return 0; } } uint32_t read_crc32 = 0; if ( !info.rawFormat ) { if ( !stream.SerializeBits( read_crc32, 32 ) ) { debug_printf( "serialize crc32 failed (read packet)\n" ); return 0; } uint32_t network_protocolId = host_to_network( info.protocolId ); uint32_t crc32 = calculate_crc32( (const uint8_t*) &network_protocolId, 4 ); uint32_t zero = 0; crc32 = calculate_crc32( (const uint8_t*) &zero, 4, crc32 ); crc32 = calculate_crc32( buffer + info.prefixBytes + 4, bufferSize - 4 - info.prefixBytes, crc32 ); if ( crc32 != read_crc32 ) { debug_printf( "corrupt packet. expected crc32 %x, got %x (read packet)\n", crc32, read_crc32 ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_CRC32_MISMATCH; return NULL; } } int packetType = 0; const int numPacketTypes = info.packetFactory->GetNumPacketTypes(); assert( numPacketTypes > 0 ); if ( numPacketTypes > 1 ) { if ( !stream.SerializeInteger( packetType, 0, numPacketTypes - 1 ) ) { debug_printf( "invalid packet type %d (read packet)\n", packetType ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_INVALID_PACKET_TYPE; return NULL; } } if ( info.allowedPacketTypes ) { if ( !info.allowedPacketTypes[packetType] ) { debug_printf( "packet type %d not allowed (read packet)\n", packetType ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_PACKET_TYPE_NOT_ALLOWED; return NULL; } } Packet * packet = info.packetFactory->CreatePacket( packetType ); if ( !packet ) { debug_printf( "create packet type %d failed (read packet)\n", packetType ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_CREATE_PACKET_FAILED; return NULL; } if ( !packet->SerializeInternal( stream ) ) { debug_printf( "serialize packet type %d failed (read packet)\n", packetType ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_SERIALIZE_PACKET_FAILED; goto cleanup; } #if YOJIMBO_SERIALIZE_CHECKS if ( !stream.SerializeCheck( "end of packet" ) ) { debug_printf( "serialize check failed at end of packet type %d (read packet)\n", packetType ); if ( errorCode ) *errorCode = YOJIMBO_PROTOCOL_ERROR_SERIALIZE_CHECK_FAILED; goto cleanup; } #endif // #if YOJIMBO_SERIALIZE_CHECKS if ( stream.GetError() ) { debug_printf( "stream error %d (read packet)\n", stream.GetError() ); if ( errorCode ) *errorCode = stream.GetError(); goto cleanup; } return packet; cleanup: info.packetFactory->DestroyPacket( packet ); return NULL; }
void test_calculate_crc32_with_empty(CuTest *tc) { char *data = "xi'an-chengdu-hangzhou-beijing"; uint32_t crc32 = calculate_crc32((uint8_t*)data, 0); CuAssertIntEquals(tc, 0xFFFFFFFF, crc32); }
int main(int argc, char *argv[]) { #if 0 BinaryInFile ts_file("Stream1-2.ts"); lm_pid_remux(ts_file.GetDataPointer(), ts_file.GetSize()); ts_file.Save("output.ts"); #endif #if 0 unsigned int i = 0; for (auto &st_name: MP2TS::gStreamTypeName) { std::cout << "0x" << std::hex << std::setfill('0') << std::setw(2) << i << " : " << st_name << std::endl; ++i; } #endif #if 1 MP2TS::Demux tsdemux("Stream1-2.ts"); //MP2TS::Demux tsdemux("football.ts"); //MP2TS::Demux tsdemux("decode_test_background_20120726_480p-1M.ts"); //MP2TS::Demux tsdemux("Beauty_3840x2160_120fps_420_8bit_HEVC_TS.ts"); // Make is quiet tsdemux.SetVerbosity(false); // Processing Loop std::cout << "PES Packets Processing Loop" << std::endl; std::cout << "-----------------------------------------------------" << std::endl; unsigned int total_ts_packets = 0; MP2TS::PES_Packet *packet; while (!tsdemux.IsEOF()) { tsdemux.Get(packet); if (tsdemux.Error() == MP2TS::ErrorCode::NONE) { //std::cout << tsdemux.NumberOfTSPackets() << " TS packets have been read" << std::endl; total_ts_packets += tsdemux.NumberOfTSPackets(); //std::cout << "Total TS Packet Read = " << total_ts_packets << std::endl; if (packet) { std::cout << "Received a " << packet->mSize << " bytes packet." << std::endl; std::cout << "Packet State " << packet->mState << std::endl; tsdemux.Parse(packet); delete packet; } } else { std::cout << "Error !!" << std::endl; break; } } // Output channel map std::cout << "Channel Map" << std::endl; std::cout << "-----------------------------------------------------" << std::endl; for (auto &channel: tsdemux.GetChannelMap()) { std::cout << channel.first << " @ PID "<< channel.second.mPMTPID << std::endl; std::cout << " Channel PMT PDI = " << std::hex << std::setfill('0') << std::setw(4) << channel.second.mPMTPID << std::dec << std::endl; unsigned int stream_num = 0; for (auto &stream: channel.second.mStreams) { std::cout << " " << stream_num << ": Stream Type 0x" << std::hex << std::setfill('0') << std::setw(4) << stream.GetStreamTypeName() << std::dec << std::endl; std::cout << " " << stream_num << ": Stream PID 0x" << std::hex << std::setfill('0') << std::setw(4) << stream.mPID << std::dec << std::endl; ++stream_num; } } #endif #if 0 unsigned char crc_buffer[] = {0x0,0xb0,0x0d,0x00,0x01,0xc1,0x0,0x0,0x0,0x1,0xe0,0x20}; //unsigned char crc_buffer[] = {0x0,0xb0,0x0d,0x59,0x81,0xeb,0x0,0x0,0x0,0x1,0xe0,0x42}; // Calculate current CRC unsigned long crc = calculate_crc32(crc_buffer, 12); std::cout << "PAT CRC = " << std::hex << std::setfill('0') << std::setw(8) << crc << std::endl; std::cout << std::dec; #endif }
/* handle reading from a client connection */ static void handle_connection_read(int sock, void *data) { data_packet receive_packet; u_int32_t packet_crc32; u_int32_t calculated_crc32; struct crypt_instance *CI; time_t packet_time; time_t current_time; int16_t return_code; unsigned long packet_age = 0L; int bytes_to_recv; int rc; char host_name[MAX_HOSTNAME_LENGTH]; char svc_description[MAX_DESCRIPTION_LENGTH]; char plugin_output[MAX_PLUGINOUTPUT_LENGTH]; int packet_length = sizeof(receive_packet); int plugin_length = MAX_PLUGINOUTPUT_LENGTH; CI = data; /* process all data we get from the client... */ /* read the packet from the client */ bytes_to_recv = sizeof(receive_packet); rc = recvall(sock, (char *)&receive_packet, &bytes_to_recv, socket_timeout); /* recv() error or client disconnect */ if (rc <= 0) { if (bytes_to_recv == OLD_PACKET_LENGTH) { packet_length = OLD_PACKET_LENGTH; plugin_length = OLD_PLUGINOUTPUT_LENGTH; } else { if (debug == TRUE) syslog(LOG_ERR, "End of connection..."); encrypt_cleanup(decryption_method, CI); close(sock); if (mode == SINGLE_PROCESS_DAEMON) return; else do_exit(STATE_OK); } } /* we couldn't read the correct amount of data, so bail out */ if (bytes_to_recv != packet_length) { syslog(LOG_ERR, "Data sent from client was too short (%d < %d), aborting...", bytes_to_recv, packet_length); encrypt_cleanup(decryption_method, CI); close(sock); return; if (mode == SINGLE_PROCESS_DAEMON) return; else do_exit(STATE_CRITICAL); } /* if we're single-process, we need to set things up so we handle the next packet after this one... */ if (mode == SINGLE_PROCESS_DAEMON) register_read_handler(sock, handle_connection_read, (void *)CI); /* decrypt the packet */ decrypt_buffer((char *)&receive_packet, packet_length, password, decryption_method, CI); /* make sure this is the right type of packet */ if (ntohs(receive_packet.packet_version) != NSCA_PACKET_VERSION_3) { syslog(LOG_ERR, "Received invalid packet type/version from client - possibly due to client using wrong password or crypto algorithm?"); /*return;*/ close(sock); if (mode == SINGLE_PROCESS_DAEMON) return; else do_exit(STATE_OK); } /* check the crc 32 value */ packet_crc32 = ntohl(receive_packet.crc32_value); receive_packet.crc32_value = 0L; calculated_crc32 = calculate_crc32((char *)&receive_packet, packet_length); if (packet_crc32 != calculated_crc32) { syslog(LOG_ERR, "Dropping packet with invalid CRC32 - possibly due to client using wrong password or crypto algorithm?"); /*return;*/ close(sock); if (mode == SINGLE_PROCESS_DAEMON) return; else do_exit(STATE_OK); } /* host name */ strncpy(host_name, receive_packet.host_name, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\0'; /* check the timestamp in the packet */ packet_age = (unsigned long)(current_time - packet_time); if (debug == TRUE) syslog(LOG_ERR, "Time difference in packet: %lu seconds for host %s", packet_age, host_name); if ((max_packet_age > 0 && (packet_age > max_packet_age) && (packet_age >= 0)) || ((max_packet_age > 0) && (packet_age < (0 - max_packet_age)) && (packet_age < 0)) ) { syslog(LOG_ERR, "Dropping packet with stale timestamp for %s - packet was %lu seconds old.", host_name, packet_age); close(sock); if (mode == SINGLE_PROCESS_DAEMON) return; else do_exit(STATE_OK); } /**** GET THE SERVICE CHECK INFORMATION ****/ /* plugin return code */ return_code = ntohs(receive_packet.return_code); /* service description */ strncpy(svc_description, receive_packet.svc_description, sizeof(svc_description) - 1); svc_description[sizeof(svc_description) - 1] = '\0'; /* plugin output */ strncpy(plugin_output, receive_packet.plugin_output, plugin_length - 1); plugin_output[plugin_length - 1] = '\0'; /* log info to syslog facility */ if (debug == TRUE) { if (!strcmp(svc_description, "")) syslog(LOG_NOTICE, "HOST CHECK -> Host Name: '%s', Return Code: '%d', Output: '%s'", host_name, return_code, plugin_output); else syslog(LOG_NOTICE, "SERVICE CHECK -> Host Name: '%s', Service Description: '%s', Return Code: '%d', Output: '%s'", host_name, svc_description, return_code, plugin_output); } /* write the check result to the external command file. * Note: it's OK to hang at this point if the write doesn't succeed, as there's * no way we could handle any other connection properly anyway. so we don't * use poll() - which fails on a pipe with any data, so it would cause us to * only ever write one command at a time into the pipe. */ if (check_result_path == NULL) { write_check_result(host_name, svc_description, return_code, plugin_output, time(NULL)); } else { write_checkresult_file(host_name, svc_description, return_code, plugin_output, time(NULL)); } return; }