/* * flex_string_append * * Not thread-safe */ void flex_string_append(flex_string *fs, const char *more) { fs->string_length += strlen(more); flex_string_check_alloc(fs, fs->string_length + 1); sstrncat(fs->buffer, more, fs->buffer_length - strlen(fs->buffer)); }
void Mod_fw_start_log_capture(FW_handle_T handle) { struct fw_handle *fwh = handle->fwh; struct bpf_program bpfp; char *pflog_if, *net_if; char errbuf[PCAP_ERRBUF_SIZE]; char filter[PCAPFSIZ] = "ip and port 25 and action pass " "and tcp[13]&0x12=0x2"; pflog_if = Config_get_str(handle->config, "pflog_if", "firewall", PFLOG_IF); net_if = Config_get_str(handle->config, "net_if", "firewall", NULL); if((fwh->pcap_handle = pcap_open_live(pflog_if, PCAPSNAP, 1, PCAPTIMO, errbuf)) == NULL) { i_critical("failed to initialize: %s", errbuf); } if(pcap_datalink(fwh->pcap_handle) != DLT_PFLOG) { pcap_close(fwh->pcap_handle); fwh->pcap_handle = NULL; i_critical("invalid datalink type"); } if(net_if != NULL) { sstrncat(filter, " and on ", PCAPFSIZ); sstrncat(filter, net_if, PCAPFSIZ); } if((pcap_compile(fwh->pcap_handle, &bpfp, filter, PCAPOPTZ, 0) == -1) || (pcap_setfilter(fwh->pcap_handle, &bpfp) == -1)) { i_critical("%s", pcap_geterr(fwh->pcap_handle)); } pcap_freecode(&bpfp); #ifdef BIOCLOCK if(ioctl(pcap_fileno(fwh->pcap_handle), BIOCLOCK) < 0) { i_critical("BIOCLOCK: %s", strerror(errno)); } #endif fwh->entries = List_create(destroy_log_entry); }
/* * ccsip_encode_call_info_hdr * * Description: * * Encode the call info header using the passed in feature id and * feature specific data. * * The miscParms parameter will usually be null. It exists in case * you want to toss in an additional string parm without using the * encoding mechanism. An example would be "extraParm= text". * * Remember to delete the store in the return parm. It is the * caller's responsibility. */ char * ccsip_encode_call_info_hdr (cc_call_info_t *call_info_p, const char *misc_parms_p) { static const char *fname = "ccsip_encode_call_info_hdr"; char *header; header = (char *) cpr_malloc(MAX_SIP_HEADER_LENGTH); if (!header) { return NULL; } if (!call_info_p) { cpr_free(header); return NULL; } snprintf(header, MAX_SIP_HEADER_LENGTH, "<%s", URN_REMOTECC); switch (call_info_p->type) { case CC_FEAT_HOLD: case CC_FEAT_RESUME: if (call_info_p->type == CC_FEAT_HOLD) { sstrncat(header, SIP_CI_HOLD_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); } else { sstrncat(header, SIP_CI_RESUME_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); } sstrncat(header, ">", MAX_SIP_HEADER_LENGTH - strlen(header)); switch (call_info_p->data.hold_resume_reason) { case CC_REASON_NONE: case CC_REASON_INTERNAL: case CC_REASON_SWAP: break; case CC_REASON_XFER: sstrncat(header, "; reason= ", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, SIP_CI_HOLD_REASON_XFER, MAX_SIP_HEADER_LENGTH - strlen(header)); break; case CC_REASON_CONF: sstrncat(header, "; reason= ", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, SIP_CI_HOLD_REASON_CONF, MAX_SIP_HEADER_LENGTH - strlen(header)); break; default: CCSIP_DEBUG_ERROR(SIP_F_PREFIX "unsupported hold_resume_reason", fname); cpr_free(header); return NULL; } /* Add swap information */ if (call_info_p->data.call_info_feat_data.swap == TRUE) { sstrncat(header, "; operation= swap", MAX_SIP_HEADER_LENGTH - strlen(header)); } if (call_info_p->data.call_info_feat_data.protect == TRUE) { sstrncat(header, "; protect= true; noholdreversion", MAX_SIP_HEADER_LENGTH - strlen(header)); } break; case CC_FEAT_INIT_CALL: /* Add global call id here */ if (call_info_p->data.initcall.gcid[0] != '\0') { sstrncat(header, "callinfo>; gci= ", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, call_info_p->data.initcall.gcid, MAX_SIP_HEADER_LENGTH - strlen(header)); } else { cpr_free(header); return NULL; } /* Add the monitor mode here if it exists */ if (call_info_p->data.initcall.monitor_mode != CC_MONITOR_NONE) { sstrncat(header, "; mode=", MAX_SIP_HEADER_LENGTH - strlen(header)); switch (call_info_p->data.initcall.monitor_mode) { case CC_MONITOR_SILENT : sstrncat(header, SIP_CI_SILENT_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); break; case CC_MONITOR_COACHING : sstrncat(header, SIP_CI_COACHING_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); break; default: break; } } break; case CC_FEAT_TOGGLE_TO_WHISPER_COACHING: sstrncat(header, "callinfo>", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, "; mode=", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, SIP_CI_COACHING_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); break; case CC_FEAT_TOGGLE_TO_SILENT_MONITORING: sstrncat(header, "callinfo>", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, "; mode=", MAX_SIP_HEADER_LENGTH - strlen(header)); sstrncat(header, SIP_CI_SILENT_STR, MAX_SIP_HEADER_LENGTH - strlen(header)); break; default: cpr_free(header); return NULL; } if (misc_parms_p) { sstrncat(header, misc_parms_p, MAX_SIP_HEADER_LENGTH - strlen(header)); } sstrncat(header, "\0", MAX_SIP_HEADER_LENGTH - strlen(header)); return (header); }
/** * This function will create the PUBLISH message and send it. it also starts the retry timer. * * @param[in] pcb_p - pointer to PCB * @param[in] authen - boolean that indicates whether to add authorization header. * * @return TRUE if it successfully sent PUBLISH * Otherwise, FALSE is returned * * @pre (pcb_p != NULL) */ static boolean sipSPISendPublish (ccsip_publish_cb_t *pcb_p, boolean authen) { static const char fname[] = "sipSPISendPublish"; static uint32_t cseq = 0; char dest_sip_addr_str[MAX_IPADDR_STR_LEN]; char *domainloc; char src_addr_str[MAX_IPADDR_STR_LEN]; char sip_temp_str[MAX_SIP_URL_LENGTH]; char sip_temp_tag[MAX_SIP_URL_LENGTH]; uint8_t mac_address[MAC_ADDRESS_LENGTH]; char via[SIP_MAX_VIA_LENGTH]; int max_forwards_value = 70; static uint16_t count = 1; sipMessage_t *request = NULL; int timeout = 0; request = GET_SIP_MESSAGE(); if (!request) { return FALSE; } /* * Populate full RURI if it is not yet. Sometimes, applications may only provide user part. */ if (pcb_p->full_ruri[0] == 0) { sstrncpy(pcb_p->full_ruri, "sip:", MAX_SIP_URL_LENGTH); sstrncat(pcb_p->full_ruri, pcb_p->ruri, MAX_SIP_URL_LENGTH - sizeof("sip:")); /* check if it has host part */ domainloc = strchr(pcb_p->full_ruri, '@'); if (domainloc == NULL) { domainloc = pcb_p->full_ruri + strlen(pcb_p->full_ruri); if ((domainloc - pcb_p->full_ruri) < (MAX_SIP_URL_LENGTH - 1)) { /* Do not include @ when there is no user part */ if (pcb_p->ruri[0] != '\0') { *domainloc++ = '@'; } ipaddr2dotted(dest_sip_addr_str, &pcb_p->hb.dest_sip_addr); sstrncpy(domainloc, dest_sip_addr_str, MAX_SIP_URL_LENGTH - (domainloc - (pcb_p->full_ruri))); } } } ipaddr2dotted(src_addr_str, &pcb_p->hb.src_addr); // Add request line if (HSTATUS_SUCCESS != sippmh_add_request_line(request, sipGetMethodString(sipMethodPublish), pcb_p->full_ruri, SIP_VERSION)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Request line\n", fname); free_sip_message(request); return (FALSE); } // Add local Via snprintf(via, sizeof(via), "SIP/2.0/%s %s:%d;%s=%s%.8x", sipTransportGetTransportType(1, TRUE, NULL), src_addr_str, pcb_p->hb.local_port, VIA_BRANCH, VIA_BRANCH_START, (unsigned int) cpr_rand()); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_VIA, via)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding VIA header\n", fname); free_sip_message(request); return (FALSE); } // Add To Header snprintf(sip_temp_str, MAX_SIP_URL_LENGTH, "<%s>", pcb_p->full_ruri); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_TO, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding TO header\n", fname); free_sip_message(request); return (FALSE); } // Add From Header. sstrncat(sip_temp_str, ";tag=", MAX_SIP_URL_LENGTH - strlen(sip_temp_str)); sip_util_make_tag(sip_temp_tag); sstrncat(sip_temp_str, sip_temp_tag, MAX_SIP_URL_LENGTH - strlen(sip_temp_str)); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_FROM, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding FROM header\n", fname); free_sip_message(request); return (FALSE); } // Add Call-ID Header. platform_get_wired_mac_address(mac_address); count++; snprintf(pcb_p->hb.sipCallID, MAX_SIP_CALL_ID, "%.4x%.4x-%.4x%.4x-%.8x-%.8x@%s", // was MAX_SIP_URL_LENGTH mac_address[0] * 256 + mac_address[1], mac_address[2] * 256 + mac_address[3], mac_address[4] * 256 + mac_address[5], count, (unsigned int) cpr_rand(), (unsigned int) cpr_rand(), src_addr_str); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_CALLID, pcb_p->hb.sipCallID)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding CALLID header\n", fname); free_sip_message(request); return (FALSE); } // Add Contact header. Contact header is not needed as per RFC. BUT CCM needs it. snprintf(sip_temp_str, MAX_SIP_URL_LENGTH, "<sip:%.4x%.4x%.4x@%s:%d>", mac_address[0] * 256 + mac_address[1], mac_address[2] * 256 + mac_address[3], mac_address[4] * 256 + mac_address[5], src_addr_str, pcb_p->hb.local_port); if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_CONTACT, sip_temp_str)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Contact header\n", fname); free_sip_message(request); return (FALSE); } // Add Cseq. cseq++; if (cseq == 0) { cseq = 1; } if (HSTATUS_SUCCESS != sippmh_add_cseq(request, sipGetMethodString(sipMethodPublish), cseq)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding CSEQ header\n", fname); free_sip_message(request); return (FALSE); } // Add UserAgent header (void) sippmh_add_text_header(request, SIP_HEADER_USER_AGENT, sipHeaderUserAgent); // Add SIP-If-Match header. if (pcb_p->entity_tag != NULL) { if (HSTATUS_SUCCESS != sippmh_add_text_header(request, SIP_HEADER_SIPIFMATCH, pcb_p->entity_tag)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Event header\n", fname); free_sip_message(request); return (FALSE); } } // Add Expires Header if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_EXPIRES, pcb_p->hb.orig_expiration)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Expires header\n", fname); free_sip_message(request); return (FALSE); } // Add max-forwards header config_get_value(CFGID_SIP_MAX_FORWARDS, &max_forwards_value, sizeof(max_forwards_value)); if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_MAX_FORWARDS, max_forwards_value)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Max-Forwards header\n", fname); free_sip_message(request); return (FALSE); } // add Authorization header if (authen) { if (HSTATUS_SUCCESS != sippmh_add_text_header(request, AUTHOR_HDR(pcb_p->hb.authen.status_code), pcb_p->hb.authen.authorization)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Authorization header\n", fname); free_sip_message(request); return (FALSE); } } // Add content, if any if (pcb_p->hb.event_data_p) { if (add_content(pcb_p->hb.event_data_p, request, fname) == FALSE) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Content\n", fname); free_sip_message(request); return (FALSE); } } else { if (HSTATUS_SUCCESS != sippmh_add_int_header(request, SIP_HEADER_CONTENT_LENGTH, 0)) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"Error in adding Content-Len\n", fname); free_sip_message(request); return (FALSE); } } ccsip_common_util_set_retry_settings(&pcb_p->hb, &timeout); if (sipTransportCreateSendMessage(NULL, request, sipMethodPublish, &(pcb_p->hb.dest_sip_addr), (int16_t) pcb_p->hb.dest_sip_port, FALSE, TRUE, timeout, pcb_p, RELDEV_NO_STORED_MSG) < 0) { CCSIP_DEBUG_ERROR(SIP_F_PREFIX"failed to send PUBLISH message\n", fname); return (FALSE); } return (TRUE); }
/*! \brief It inizializes the source file when the user wants to read a PSML file on disk. Upon returning from this method, this class will have the entire PSML file 'parsed', i.e. an array will contain the starting offset of any PSML fragment as it is on the file on disk. This is not a real parsing sice we still have each PSML fragment in ascii, instead of being properly formatted with the proper internal structures. Howewever, this will allow the user to ask for a specific packet; at that time we will parse the specific PSML fragment (with DOM) and we return it properly formatted the user. \param FileName: string containing the PSML file to open. \return nbSUCCESS if everything is fine, nbFAILURE otherwise. In case of error, the error message can be retrieved by the GetLastError() method. */ int CPSMLReader::InitializeSource(char *FileName) { char StartTag[NETPDL_MAX_STRING]; int BufferPtr; int StartTagLength; unsigned long CurrentOffset; char *AsciiBuffer; if (m_NetPDLDecodingEngine) { errorsnprintf(__FILE__, __FUNCTION__, __LINE__, m_errbuf, sizeof(m_errbuf), "The nbPSMLReader has already been configured to manage packets returned by " "the nbPacketDecoder. If you want to read a file, you have to use another nbPSMLReader instance."); return nbFAILURE; } /* Here we have two choices in parsing the document: - parse the whole file at once, with Xerces native code - parse each packet within a different instance. The first method is very fast (test showed 1/4 of the time compared to the second method), but the memory consumption is very very high. So, in order to make everything scalable, this implementation parses each packet within different DOM documents, and we keep in memory only what we need for parsing the current packet. */ m_sourceOnDiskFileHandle= fopen(FileName, "r+b"); if (m_sourceOnDiskFileHandle == NULL) { errorsnprintf(__FILE__, __FUNCTION__, __LINE__, m_errbuf, sizeof(m_errbuf), "Unable to open the PSML file."); return nbFAILURE; } // Format a string with the starting tag we have to look for (<packet>) StartTagLength= ssnprintf(StartTag, sizeof(StartTag), "<%s>", PSML_PACKET); BufferPtr= 0; CurrentOffset= 0; AsciiBuffer= m_asciiBuffer.GetStartBufferPtr(); while( !feof( m_sourceOnDiskFileHandle ) ) { unsigned int ReadBytes; char *TagPtr; // Read data from file; we have a buffer with size m_asciiBuffer.GetBufferTotSize() ReadBytes= fread(&AsciiBuffer[BufferPtr], sizeof (char), m_asciiBuffer.GetBufferTotSize() - 1 - BufferPtr, m_sourceOnDiskFileHandle); AsciiBuffer[BufferPtr + ReadBytes]= 0; // If we're still at the beginnning of the file, let's locate the summary if (CurrentOffset == 0) { char StructureTag[NETPDL_MAX_STRING]; char *StartStructure, *EndStructure; // Locate the starting point of the <structure> ssnprintf(StructureTag, sizeof(StructureTag), "<%s>", PSML_INDEXSTRUCTURE); StartStructure= strstr(AsciiBuffer, StructureTag); // Locate the ending point of the <structure> ssnprintf(StructureTag, sizeof(StructureTag), "<%s>", PSML_PACKET); EndStructure= strstr(AsciiBuffer, StructureTag); // Save the structure within an ascii buffer m_summarySection= new char [EndStructure - StartStructure]; if (m_summarySection == NULL) { errorsnprintf(__FILE__, __FUNCTION__, __LINE__, m_errbuf, sizeof(m_errbuf), "Not enough memory to contain the summary session"); return nbFAILURE; } m_summarySection[0]= 0; sstrncat(m_summarySection, StartStructure, (int) (EndStructure - StartStructure - 1)); } // Let's locate all the <packet> contained in this buffer TagPtr= m_asciiBuffer.GetStartBufferPtr(); while ((TagPtr= strstr(TagPtr, StartTag) )) { m_packetList[m_currNumPackets]= (int) (CurrentOffset + TagPtr - AsciiBuffer); m_currNumPackets++; // Check if the vector is enough; if not, let's allocate a new one, and let's hope it is enough if (CheckPacketListSize() == nbFAILURE) return nbFAILURE; TagPtr++; } // Check if presumably we have still something to read from file if (ReadBytes == (m_asciiBuffer.GetBufferTotSize() - 1 - BufferPtr)) { char *AsciiBufferPtr; AsciiBufferPtr= m_asciiBuffer.GetStartBufferPtr(); // Copy some of the bytes at the end of the buffer to the beginning // of the new one, so that we can speed up the process (strstr() can scan a contiguous buffer) strncpy(AsciiBufferPtr, &AsciiBufferPtr[m_asciiBuffer.GetBufferTotSize() - StartTagLength], StartTagLength - 1); BufferPtr= StartTagLength - 1; CurrentOffset= CurrentOffset + (m_asciiBuffer.GetBufferTotSize() - StartTagLength); } } if (m_currNumPackets == 0) { errorsnprintf(__FILE__, __FUNCTION__, __LINE__, m_errbuf, sizeof(m_errbuf), "Initializing a PSML file with no packets in it. Are you sure the input data is correct?."); return nbFAILURE; } // If we have N packet, we have (N+1) meaningful cells within this vector m_packetList[m_currNumPackets]= ftell(m_sourceOnDiskFileHandle); return nbSUCCESS; }
/** * Inserts localized strings into existing strings with escape characters. * @param destination the return phrase holder * @param source the phrase with escape characters. * @param len the input length to cap the maximum value * @return pointer to the new string */ cc_string_t ccsnap_EscapeStrToLocaleStr(cc_string_t destination, cc_string_t source, int len) { static const char *fname="ccsnap_EscapeStrToLocaleStr"; char phrase_collector[MAX_LOCALE_STRING_LEN] = { '\0' }; char* phrase_collector_ptr = phrase_collector; char* esc_string_itr = (char*)source; int remaining_length = 0; cc_string_t ret_str = strlib_empty(); if(destination == NULL){ CCAPP_DEBUG(DEB_F_PREFIX"Error: destination is NULL\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname)); return NULL; } if(source == NULL){ CCAPP_DEBUG(DEB_F_PREFIX"Error: source is NULL\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname)); strlib_free(destination); return strlib_empty(); } if(source[0] == '\0'){ strlib_free(destination); return strlib_empty(); } if (len == LEN_UNKNOWN) { len = strlen(source) + MAX_LOCALE_PHRASE_LEN; } if (len <= 0){ CCAPP_DEBUG(DEB_F_PREFIX"Error: cannot write string of length <= 0\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname)); strlib_free(destination); return strlib_empty(); } if (len > MAX_LOCALE_STRING_LEN){ len = MAX_LOCALE_STRING_LEN; } remaining_length = len; while( *esc_string_itr != NUL && remaining_length > 0 && strlen(phrase_collector_ptr) < (size_t)(len-1)) { int rtn = CC_SUCCESS; int phrase_index = 0; char* phrase_bucket_ptr = (char*)cpr_malloc(remaining_length * sizeof(char)); if (phrase_bucket_ptr == NULL) { CCAPP_ERROR(DEB_F_PREFIX"Error: phrase_bucket_ptr is NULL\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname)); strlib_free(destination); return NULL; } phrase_bucket_ptr[0] = '\0'; switch(*esc_string_itr){ case OLD_CUCM_DICTIONARY_ESCAPE_TAG: phrase_index += CALL_CONTROL_PHRASE_OFFSET; // Do not set break to combine common code case NEW_CUCM_DICTIONARY_ESCAPE_TAG: esc_string_itr++; phrase_index += (int)(*esc_string_itr); rtn = platGetPhraseText(phrase_index, phrase_bucket_ptr, remaining_length-1); if(rtn == CC_FAILURE) break; sstrncat(phrase_collector_ptr, (cc_string_t)phrase_bucket_ptr, remaining_length); remaining_length--; break; default: // We need length 2 to concat 1 char and a terminating char sstrncat(phrase_collector_ptr, esc_string_itr, 1 + sizeof(char)); remaining_length--; break; } esc_string_itr++; cpr_free(phrase_bucket_ptr); } ret_str = strlib_malloc(phrase_collector_ptr, len); if (!ret_str) { /* * If a malloc error occurred, give them back what they had. * It's not right, but it's better than nothing. */ ret_str = destination; } else { strlib_free(destination); } CCAPP_DEBUG(DEB_F_PREFIX"Localization String returning %s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), ret_str); return (ret_str); }
/** Main execution routine @param argc Number of args (0) @param argv Args (always empty) */ int main (int argc, char *argv[]) { /* --------------------------------------------------------------------- * Alert! setuid program with root privileges * ---------------------------------------------------------------------*/ /* syslog */ openlog ("odcgi", LOG_PID, LOG_USER); script_env_t env; /* Agent address */ //! @todo: what if eth0 don't exists? snprintf (env.agent_address, MAX_ENV_SIZE, "%s", getip ("eth0")); //! @todo: lots of static variables. Maybe some can be reused to save memory char http_gui[8]; //char http_style[10]; char http_logout[8]; char http_user[256]; char http_pass[256]; char http_session[1024]; char http_noheader[8]; char http_newuser[256]; char http_newpass1[256]; char http_newpass2[256]; char http_deluser[256]; char http_moduser[256]; char http_modpass1[256]; char http_modpass2[256]; char http_modoldpass[256]; char http_getfile[256]; char http_resource[50]; char http_play_mjpg[100]; char http_temp[100]; /* Configuration vars */ FILE *fh; read_config_file (fh, OD_APP_I18N_CONF, lang, "en"); //read_config_file(fh,OD_APP_STYLE_CONF,style,"default"); //read_config_file(fh,OD_APP_SKIN_CONF,skin,"silver"); /* Get HTTP variables */ cgi_t *cgi = cgi_alloc (); cgi_get_param_by_name (cgi, "GUI", http_gui, sizeof (http_gui)); cgi_get_param_by_name (cgi, "LOGOUT", http_logout, sizeof (http_logout)); cgi_get_param_by_name (cgi, "USER", http_user, sizeof (http_user)); cgi_get_param_by_name (cgi, "PASS", http_pass, sizeof (http_pass)); cgi_get_param_by_name (cgi, "HTSESSID", http_session, sizeof (http_session)); cgi_get_param_by_name (cgi, "NOHEADER", http_noheader, sizeof (http_noheader)); cgi_get_param_by_name (cgi, "NEWUSER", http_newuser, sizeof (http_newuser)); cgi_get_param_by_name (cgi, "NEWPASS1", http_newpass1, sizeof (http_newpass1)); cgi_get_param_by_name (cgi, "NEWPASS2", http_newpass2, sizeof (http_newpass2)); cgi_get_param_by_name (cgi, "DELUSER", http_deluser, sizeof (http_deluser)); cgi_get_param_by_name (cgi, "MODUSER", http_moduser, sizeof (http_moduser)); cgi_get_param_by_name (cgi, "MODPASS1", http_modpass1, sizeof (http_modpass1)); cgi_get_param_by_name (cgi, "MODPASS2", http_modpass2, sizeof (http_modpass2)); cgi_get_param_by_name (cgi, "MODOLDPASS", http_modoldpass, sizeof (http_modoldpass)); cgi_get_param_by_name (cgi, "FILE", http_getfile, sizeof (http_getfile)); cgi_get_param_by_name (cgi, "resource", http_resource, sizeof (http_resource)); cgi_get_param_by_name (cgi, "play_mjpg", http_play_mjpg, sizeof (http_play_mjpg)); // if (cgi_get_param_by_name(cgi,"style", http_style, sizeof(http_style))==1) // { // //cgi_get_cookie("HTSTYLE", http_style, sizeof(http_style)); // strncpy(style, http_style, sizeof(http_style)); // cgi_http_header_set_cookie("HTSTYLE", style); // } // Si se ha solicitado una hoja de estilo, la entregamos if (cgi_get_param_by_name (cgi, "css", http_temp, sizeof (http_temp)) == 1) { syslog (LOG_NOTICE, "printing style: %s\n", http_temp); odcgi_print_file (http_temp); cgi_free (cgi); return 0; } /* // Si se ha solicitado el javascript específico, lo entregamos if (cgi_get_param_by_name(cgi, "js", http_temp, sizeof(http_temp))==1) { syslog(LOG_NOTICE, "printing script: %s\n", http_temp); odcgi_print_file(http_temp); return 0; } */ if (strlen (http_session) == 0) { cgi_get_cookie ("HTSESSID", http_session, sizeof (http_session)); syslog (LOG_NOTICE, "session from cookie: %s\n", http_session); } /* get gui type */ if (strcmp (http_gui, "XML") == 0) gui = xml; if (strcmp (http_gui, "none") == 0) gui = none; /* login process */ if (odcgi_login (&env, http_user, http_pass, http_session, sizeof (http_session)) == -1) { syslog (LOG_NOTICE, "login failed: %s-%s\n", http_user, http_pass); cgi_free (cgi); return -1; } // syslog(LOG_NOTICE, "env.user: %s\n", env.user); // syslog(LOG_NOTICE, "http_user: %s\n", http_user); /* check logout */ if (odcgi_logout (&env, http_logout)) { cgi_free (cgi); return -1; } /* --------------------------------------------------------------------- * Login OK: odcgi is setuid root * --------------------------------------------------------------------- */ //syslog(LOG_NOTICE, "[odcgi] userid: %d\n", getuid()); /* root has not access */ if (odcgi_check_root (http_user)) { cgi_free (cgi); return -1; } /* --------------------------------------------------------------------- * Login OK: * + admin has root privileges * + normal user has Linux privileges * --------------------------------------------------------------------- */ syslog (LOG_NOTICE, "[odcgi] user: %s, uid: %d, guid: %d\n", env.user, getuid (), getgid ()); /* NO USER MANAGEMENT FUNCTIONS IN // adds a new user if (odcgi_add_user (http_newuser, http_newpass1, http_newpass2) == -1) { cgi_free (cgi); return -1; } // delete user if (odcgi_del_user (http_deluser) == -1) { cgi_free (cgi); return -1; } // modify user password if (odcgi_mod_user (http_moduser, http_modoldpass, http_modpass1, http_modpass2) == -1) { cgi_free (cgi); return -1; } */ /* set session */ /* Privilege separation: drop root privileges */ // syslog(LOG_NOTICE, "set session %s\n", http_session); // syslog(LOG_NOTICE, "[odcgi] session_set_ids user: %s\n", env.user); session_set_ids (env.user); syslog (LOG_NOTICE, "[odcgi] dropped privileges user: %s, uid: %d, guid: %d\n", env.user, getuid (), getgid ()); /* File reference with user permissions applied */ if (strlen (http_getfile) > 5) { char buffer[1024] = "/media/"; strcat (buffer, http_getfile); if (http_send_file (buffer)) { cgi_free (cgi); return 0; } else { //! @todo Mostrar error } } /* play mjpg file */ if (strlen (http_play_mjpg) > 3) { syslog (LOG_NOTICE, "play: %s\n", http_play_mjpg); mjpg_play (http_play_mjpg); cgi_free (cgi); return 0; } switch (gui) { case xml: cgi_http_header_begin ("text/xml"); break; case html: cgi_http_header_begin ("text/html"); break; default: cgi_http_header_begin ("text/plain"); } /* Resource reference */ //TODO Verificar permisos de usuario if (strlen (http_resource) > 3) { syslog (LOG_NOTICE, "Serving resource %s\n", http_resource); if (mjpg_streaming_rsc (http_resource)) { cgi_free (cgi); return 0; } else { //printf("<div id='connfail'><p class='error'>%s</p></div>\n", // T(ODCGI_ERROR__CONNECTION_FAILURE)); cgi_free (cgi); return 0; } } syslog (LOG_NOTICE, "1.session: %s\n", http_session); cgi_http_header_set_cookie ("HTSESSID", http_session); // cgi_get_cookie("HTSTYLE", style, sizeof(style)); // cgi_http_header_set_cookie("HTSTYLE", style); cgi_http_header_end (); /* --------------------------------------------------------------------- * User privileges * ---------------------------------------------------------------------*/ size_t len = cgi->decoded_url->size; char path_info[256 + len]; path_info[0] = 0; sstrncpy (path_info, cgi_get_path_info (cgi), sizeof (path_info)); syslog (LOG_NOTICE, "path_info %s - %d\n", path_info, strlen (path_info)); // If any POST/GET vars matches with submit_X.sh, X.sh is the target // then replace 'path_info'. char options[256 + len]; int index = 0; char varname[256]; char varvalue[256 + len]; int has_option = 0; char scriptname[256] = ""; char path[256 + len]; path[0] = 0; while (cgi_get_param_by_index (cgi, index, varname, sizeof (varname), varvalue, sizeof (varvalue))) { // Replace "+" for " " for (int i=0;i<sizeof(varvalue);i++) { if (varvalue[i]=='+') varvalue[i]=' '; } syslog (LOG_DEBUG, "CGIParam %d %s=%s\n", index, varname, varvalue); if (strcmp (varname, "GUI") == 0) { // Ignore } else if (strcmp (varname, "odcgioptionsel") == 0) { sstrncat (options, varvalue, sizeof (options)); sstrncat (options, " ", sizeof (options)); has_option = 1; } else if (strncmp (varname, "submit_", 7) == 0) { syslog (LOG_NOTICE, "Submit redirection found at %s\n", varname); sstrncpy (scriptname, varname + 7, sizeof (scriptname)); //sstrncpy(path_info, scriptname, sizeof(path_info)); snprintf (path, sizeof (path), "/usr/local/opendomo/%s", scriptname); syslog (LOG_DEBUG, "debugging %s - %s [%s]\n", scriptname, path, options); break; } index++; } /* Check PATH variable */ if (strlen (path_info) == 0) strcpy (path_info, "/"); /* filters */ if (!match (path_info, "^/[a-záéíóúàèäëïöüñçA-ZÁÉÍÓÚÀÈÄËÏÖÜÑÇ0-9_/]*\\.{0,1}[a-záéíóúàèäëïöüñçA-ZÁÉÍÓÚÀÈÄËÏÖÜÑÇ0-9_/+ =?:]*$")) { odcgi_print_header ("error", env.user); syslog (LOG_ERR, "%s\n", ODCGI_ERROR__INVALID_PATH); odcgi_msg_error (ODCGI_ERROR__INVALID_PATH, "Invalid character found in the command."); printf ("\n<!-- PATH_INFO: %s-->\n", path_info); odcgi_print_footer ("", 0, cgi); cgi_free (cgi); return -1; } int err = 0; char *param_regex = "[$;'\\\"]"; if (strstr (cgi_get_query_string (cgi), "..")) err = 1; else if (strstr (cgi_get_decoded_url (cgi), "..")) err = 2; else if (strlen (cgi_get_query_string (cgi)) > 0 && match (cgi_get_query_string (cgi), param_regex)) err = 3; else if (strlen (cgi_get_decoded_url (cgi)) > 0 && match (cgi_get_decoded_url (cgi), param_regex)) err = 4; if (err!=0) { odcgi_print_header ("error", env.user); syslog (LOG_ERR, "%s\n", ODCGI_ERROR__INVALID_PATH); odcgi_msg_error (ODCGI_ERROR__INVALID_PATH, "Invalid character found in the parameters."); printf ("\n<!-- PATH ERROR: %d (not allowed) \n\t%s \n\t %s -->\n", err, cgi_get_query_string (cgi), cgi_get_decoded_url (cgi)); odcgi_print_footer ("", 0, cgi); cgi_free (cgi); return -1; } // If PATH is not modified, use the default path in CONF_DIR. if (path[0] == 0) { snprintf (path, sizeof (path), "%s/%s", OD_CFG_ROOT_DIR, path_info); } /* root directory */ if (chdir (OD_CFG_ROOT_DIR) != 0) { odcgi_print_header ("error", env.user); syslog (LOG_ERR, "%s\n", ODCGI_ERROR__ROOT_PATH_ACCESS); odcgi_msg_error (ODCGI_ERROR__ROOT_PATH_ACCESS, "Cannot access the configuration directory. " "Missing privileges or misconfiguration"); odcgi_print_footer ("", 0, cgi); cgi_free (cgi); return -1; } char name[256 + len]; char value[256 + len]; char prename[256 + len]; char *shname; string_t *cmd = string_alloc (""); file_t fs; strcpy (scriptname, basename (path)); /* HTML-head begin */ odcgi_print_header (scriptname, env.user); printf ("<!-- path: %s, path_info: %s-->\n", path, path_info); /* Check NOHEADER */ if ((gui == html) && (atoi (http_noheader) != 1)) { string_assign_str (cmd, "/usr/bin/categories.sh "); string_append (cmd, path_info); script_exec (cmd->str, "header", &env); if (strlen (path_info) < 2) { printf (" <div class='applicationTitle'><h1>OpenDomo</h1></div>\n"); } else { printf (" <div class='root'><a href='" OD_URI "/'> </a></div>\n"); } } sstrncpy (prename, path, sizeof (prename)); shname = strtok (prename, " "); file_set_filename (&fs, shname); strcpy (scriptname, basename (path)); /* if dir: list contents */ if (file_is_dir (&fs)) { string_assign_str (cmd, "/usr/bin/list.sh "); string_append (cmd, path_info); string_append (cmd, " contents"); script_exec (cmd->str, "main", &env); } else { /* if file: execute */ // The path might be a redirection (no actual link in ..opendomo/root/) if (!file_is_file (&fs)) { snprintf (path, sizeof (path), "/usr/local/opendomo/%s", basename (scriptname)); printf ("\n<!-- debug paths: %s / %s [%s] -->\n", path, path_info, scriptname); file_set_filename (&fs, path); if (!file_is_file (&fs)) // If it's still not a valid path, abort { odcgi_msg_error (ODCGI_ERROR__SCRIPT_NOT_FOUND, "The script was not found. " "Maybe the function you are requiring " "is not installed in this system"); printf ("<!-- BASENAME: %s -->\n", basename (scriptname)); odcgi_print_footer ("", 0, cgi); cgi_free (cgi); return 1; } } //printf("<!-- debug path: %s -->\n", path); //char *p = strrchr(path, '/'); if (has_option /*&& p */ ) { string_assign_str (cmd, path); string_append (cmd, " "); string_append (cmd, options); } else { string_assign_str (cmd, path); string_append (cmd, " "); } printf ("\n<!-- decoded_url: %s \n\tquery_string: %s-->\n", cgi->decoded_url->str, cgi->query_string->str); int i = 0; while (cgi_get_param_by_index (cgi, i++, name, sizeof (name), value, sizeof (value))) { if (strcmp (name, ODCGI_SESSION_NAME) == 0) { // Ignoring session name var ... } else if (strncmp (name, "GUI", 3) == 0) { // Ignoring GUI param } else if (strncmp (name, "submit_", 7) == 0) { // Ignoring possible submit redirection ... } else { //for (i = 0; i < sizeof(value); i++){ // if (value[i]=='+') value[i]=' '; //} // Avoid overwritting a defined environment var if (getenv (name) == NULL) setenv (name, value, 1); string_append (cmd, " \""); string_append (cmd, value); string_append (cmd, "\" "); } } string_replace (cmd, "+", " "); string_replace (cmd, "'", "'"); printf ("<!-- cmd (file): %s -->\n", cmd->str); //fflush(stdout); // Force flush, otherwise an error will preceed stdout // Check the returned value of script_exec() int ret = script_exec (cmd->str, "main", &env); if (ret != 0) { /* else: empty div */ printf ("<div id='main'><p class='error'>%s</p></div>", ODCGI_ERROR__SCRIPT_NOT_FOUND); } } /* Print scripts */ //odcgi_print_script(path); DEPRECATED /* HTML end */ if (atoi (http_noheader) != 1) { odcgi_print_footer ("", BUTTON_LOGOUT + BUTTON_DEBUG, cgi); } string_free (cmd); cgi_free (cgi); closelog (); return 0; }