void file_free(OBJECT * filename, int is_recursive) { file_info_t * ff; /* do nothing if cache is uninitialized */ if ( !filecache_hash ) return; ff = file_info( filename ); hash_free( filecache_hash, (HASHDATA*)ff ); /* freed directories must free all their files and subdirectories */ if ( ff->is_dir ) { printf( "dir_free: %s\n", filename ); if ( !ff->files ) printf( "directory without files: %s\n", filename ); else { LIST * files = ff->files; for ( ; files; files = list_next( files ) ) if ( is_recursive || file_is_file( files->value ) ) file_free( files->value, is_recursive ); } } else { printf( "file_free: %s\n", filename ); } }
/** Print plain text file @param path File path @todo unify with http_send_file */ void odcgi_print_file (const char *path) { openlog ("odcgi", LOG_PID, LOG_USER); char filename[1024]; // Building the full path snprintf (filename, sizeof (filename), "%s%s", OD_CFG_ROOT_DIR, path); file_t fs; file_set_filename (&fs, filename); syslog (LOG_NOTICE, "%s\n", filename); printf ("Cache-Control: max-age=3600, must-revalidate\n"); printf ("Content-Type: text/plain\n\n"); if (file_is_file (&fs)) { printf ("/* %s: */\n", filename); file_print (&fs); } else { printf ("/* File (%s) does not exist */\n\n", filename); } }
/** 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; }