void __glob_gdn( const char* a_path, const char* a_fnpattern, VArray &a_va ) // glob getdirname { VString pat = a_fnpattern; pat += "*"; a_va.undef(); DIR *dir; dirent *de; if ( !a_path || a_path[0] == 0 ) dir = opendir("."); else dir = opendir( a_path ); if (dir) { while ( (de = readdir(dir)) ) { if ( strcmp( de->d_name, "." ) == 0 || strcmp( de->d_name, ".." ) == 0 ) continue; if ( a_fnpattern[0] == 0 || FNMATCH( pat, de->d_name)==0 ) { VString str; // = a_path; str += de->d_name; if ( file_is_dir( a_path + str ) ) { str += "/"; a_va.push(str); } } } closedir(dir); } }
/* Finds the next element of the given directory and stores the element's name in the given buffer. Returns true if an element was found, false if not. NOTE : "." and ".." are not considered true elements, and will never be returned by this function. */ bool dir_readdir (struct file *dir, char *buf) { ASSERT (file_is_dir (dir)); bool locked = file_lock (dir); /* If the cursor is before the third entry, then it's pointing at "." or "..", since these are *always* the first two directory entries. Seek to beyond them, since we don't want to return them. */ off_t min_cursor = 2 * sizeof (struct dir_entry); if (file_tell (dir) < min_cursor) file_seek (dir, min_cursor); bool success = false; while (true) { struct dir_entry e; if (file_read (dir, &e, sizeof e) != sizeof e) goto done; if (e.in_use) { strlcpy (buf, e.name, NAME_MAX + 1); return true; goto done; } } done: if (locked) file_unlock (dir); return success; }
int file_mkdir(char *name, int pflag) { char *buffer=g_alloca(sizeof(char)*(strlen(name)+1)); int ret; char *next; dbg(1,"enter %s %d\n",name,pflag); if (!pflag) { if (file_is_dir(name)) return 0; #if defined HAVE_API_WIN32_BASE || defined _MSC_VER return mkdir(name); #else return mkdir(name, 0777); #endif } strcpy(buffer, name); next=buffer; while ((next=strchr(next, '/'))) { *next='\0'; if (*buffer) { ret=file_mkdir(buffer, 0); if (ret) return ret; } *next++='/'; } if (pflag == 2) return 0; return file_mkdir(buffer, 0); }
/* NOTE - Assumes that the caller has already acquired a lock on dir. */ static int lookup (struct file *dir, const char *name, off_t *out_ofs, struct dir_entry *out_entry) { ASSERT (file_is_dir (dir)); struct dir_entry e; size_t ofs; ASSERT (name != NULL); int return_value = -1; /* Search the directory for the given element. */ size_t dir_size = inode_length (dir->inode); for (ofs = 0; ofs < dir_size; ofs += sizeof e) { inode_read_at (dir->inode, &e, sizeof e, ofs); if (e.in_use && !strcmp (name, e.name)) { if (out_ofs) *out_ofs = ofs; if (out_entry) *out_entry = e; return_value = e.inode_sector; break; } } return return_value; }
static int opkg_download_cache(const char *src, const char *dest_file_name, curl_progress_func cb, void *data) { char *cache_name = xstrdup(src); char *cache_location, *p; int err = 0; if (!conf->cache || str_starts_with(src, "file:")) { err = opkg_download(src, dest_file_name, cb, data, 0); goto out1; } if(!file_is_dir(conf->cache)){ opkg_msg(ERROR, "%s is not a directory.\n", conf->cache); err = 1; goto out1; } for (p = cache_name; *p; p++) if (*p == '/') *p = ','; /* looks nicer than | or # */ sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name); if (file_exists(cache_location)) opkg_msg(NOTICE, "Copying %s.\n", cache_location); else { /* cache file with funky name not found, try simple name */ free(cache_name); char *filename = strrchr(dest_file_name,'/'); if (filename) cache_name = xstrdup(filename+1); // strip leading '/' else cache_name = xstrdup(dest_file_name); free(cache_location); sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name); if (file_exists(cache_location)) opkg_msg(NOTICE, "Copying %s.\n", cache_location); else { err = opkg_download(src, cache_location, cb, data, 0); if (err) { (void) unlink(cache_location); goto out2; } } } err = file_copy(cache_location, dest_file_name); out2: free(cache_location); out1: free(cache_name); return err; }
int file_move(const char *src, const char *dst, size_t bs) { if (rename(src, dst) == 0) return 0; if (bs == 0) return -1; if (file_is_dir(src)) { WARN("Cannot move directory by copying"); return -1; } if (file_copy(src, dst, -1, bs, 0) < 0) return -1; return unlink(src); }
/* Adds a file named NAME to DIR, which must not already contain a file by that name. The file's inode is in sector INODE_SECTOR. Returns true if successful, false on failure. Fails if NAME is invalid (i.e. too long) or a disk or memory error occurs. */ bool dir_add (struct file *dir, const char *name, block_sector_t inode_sector) { ASSERT (file_is_dir (dir)); struct dir_entry e; size_t ofs; bool success = false; ASSERT (dir != NULL); ASSERT (name != NULL); /* Check NAME for validity. */ if (*name == '\0' || strlen (name) > NAME_MAX) return false; bool locked = file_lock (dir); /* Check that NAME is not in use. */ if (dir_lookup (dir, name) >= 0) goto done; /* Set OFS to offset of free slot. If there are no free slots, then it will be set to the current end-of-file. inode_read_at() will only return a short read at end of file. Otherwise, we'd need to verify that we didn't get a short read due to something intermittent such as low memory. */ size_t dir_size = inode_length (dir->inode); for (ofs = 0; ofs < dir_size; ofs += sizeof e) { inode_read_at (dir->inode, &e, sizeof e, ofs); if (!e.in_use) break; } /* Write slot. */ e.in_use = true; strlcpy (e.name, name, sizeof e.name); e.inode_sector = inode_sector; success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e; done: if (locked) file_unlock (dir); return success; }
/* Returns whether or not the given directory is empty (an empty directory is one in which the only entries are "." and ".."). NOTE : Assumes the caller has already acquired a lock on the directory. */ bool dir_is_empty (struct file *dir) { ASSERT (file_is_dir (dir)); /* Look through all the directory entries, counting up the entries that are in use. */ size_t dir_size = inode_length (dir->inode); struct dir_entry e; size_t ofs; size_t entries = 0; for (ofs = 0; ofs < dir_size; ofs += sizeof e) { inode_read_at (dir->inode, &e, sizeof e, ofs); if (e.in_use) entries++; } /* A directory should never have less than 2 entries. */ ASSERT (entries >= 2); /* The directory is empty if it contains only "." and ".." - 2 entries. */ return entries == 2; }
/* Removes any entry for NAME in DIR. Returns true if successful, false on failure, which occurs only if there is no file with the given NAME. */ bool dir_remove (struct file *dir, const char *name) { ASSERT (file_is_dir (dir)); struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; int sector; ASSERT (dir != NULL); ASSERT (name != NULL); bool locked = file_lock (dir); /* Find directory entry. */ if ((sector = lookup (dir, name, &ofs, &e)) < 0) goto done; /* Open inode. */ inode = inode_open (sector); if (inode == NULL) goto done; /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ inode_remove (inode); success = true; done: if (locked) file_unlock (dir); if (inode) inode_close (inode); return success; }
void remove_data_files_and_list(pkg_t * pkg) { str_list_t installed_dirs; str_list_t *installed_files; str_list_elt_t *iter; char *file_name; conffile_t *conffile; int removed_a_dir; pkg_t *owner; int rootdirlen = 0; int r; installed_files = pkg_get_installed_files(pkg); if (installed_files == NULL) { opkg_msg(ERROR, "Failed to determine installed " "files for %s. None removed.\n", pkg->name); return; } str_list_init(&installed_dirs); /* don't include trailing slash */ if (opkg_config->offline_root) rootdirlen = strlen(opkg_config->offline_root); for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) { file_name = (char *)iter->data; owner = file_hash_get_file_owner(file_name); if (owner != pkg) /* File may have been claimed by another package. */ continue; if (!file_is_symlink(file_name) && file_is_dir(file_name)) { str_list_append(&installed_dirs, file_name); continue; } conffile = pkg_get_conffile(pkg, file_name + rootdirlen); if (conffile) { if (conffile_has_been_modified(conffile)) { opkg_msg(NOTICE, "Not deleting modified conffile %s.\n", file_name); continue; } } if (!opkg_config->noaction) { opkg_msg(INFO, "Deleting %s.\n", file_name); unlink(file_name); } else opkg_msg(INFO, "Not deleting %s. (noaction)\n", file_name); file_hash_remove(file_name); } /* Remove empty directories */ if (!opkg_config->noaction) { do { removed_a_dir = 0; for (iter = str_list_first(&installed_dirs); iter; iter = str_list_next(&installed_dirs, iter)) { file_name = (char *)iter->data; r = rmdir(file_name); if (r == 0) { opkg_msg(INFO, "Deleting %s.\n", file_name); removed_a_dir = 1; str_list_remove(&installed_dirs, &iter); } } } while (removed_a_dir); } pkg_free_installed_files(pkg); pkg_remove_installed_files_list(pkg); /* Don't print warning for dirs that are provided by other packages */ for (iter = str_list_first(&installed_dirs); iter; iter = str_list_next(&installed_dirs, iter)) { file_name = (char *)iter->data; owner = file_hash_get_file_owner(file_name); if (owner) { free(iter->data); iter->data = NULL; str_list_remove(&installed_dirs, &iter); } } /* cleanup */ while (!void_list_empty(&installed_dirs)) { iter = str_list_pop(&installed_dirs); free(iter->data); free(iter); } str_list_deinit(&installed_dirs); }
/** 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; }
/* To reduce redundant error handling code [calls to abort_connection()] * most of the function is build around conditions that will assign the error * code to @state if anything goes wrong. The rest of the function will then just * do the necessary cleanups. If all works out we end up with @state being S_OK * resulting in a cache entry being created with the fragment data generated by * either reading the file content or listing a directory. */ void file_protocol_handler(struct connection *connection) { unsigned char *redirect_location = NULL; struct string page, name; struct connection_state state; int set_dir_content_type = 0; if (get_cmd_opt_bool((const unsigned char *)"anonymous")) { if (strcmp((const char *)connection->uri->string, "file:///dev/stdin") || isatty(STDIN_FILENO)) { abort_connection(connection, connection_state(S_FILE_ANONYMOUS)); return; } } #ifdef CONFIG_CGI if (!execute_cgi(connection)) return; #endif /* CONFIG_CGI */ /* Treat /dev/stdin in special way */ if (!strcmp((const char *)connection->uri->string, "file:///dev/stdin")) { int fd = open("/dev/stdin", O_RDONLY); if (fd == -1) { abort_connection(connection, connection_state(-errno)); return; } set_nonblocking_fd(fd); if (!init_http_connection_info(connection, 1, 0, 1)) { abort_connection(connection, connection_state(S_OUT_OF_MEM)); close(fd); return; } connection->socket->fd = fd; connection->data_socket->fd = -1; read_from_stdin(connection); return; } /* This function works on already simplified file-scheme URI pre-chewed * by transform_file_url(). By now, the function contains no hostname * part anymore, possibly relative path is converted to an absolute one * and uri->data is just the final path to file/dir we should try to * show. */ if (!init_string(&name) || !add_uri_to_string(&name, connection->uri, URI_PATH)) { done_string(&name); abort_connection(connection, connection_state(S_OUT_OF_MEM)); return; } decode_uri_string(&name); /* In Win32, file_is_dir seems to always return 0 if the name * ends with a directory separator. */ if ((name.length > 0 && dir_sep(name.source[name.length - 1])) || file_is_dir(name.source)) { /* In order for global history and directory listing to * function properly the directory url must end with a * directory separator. */ if (name.source[0] && !dir_sep(name.source[name.length - 1])) { redirect_location = (unsigned char *)STRING_DIR_SEP; state = connection_state(S_OK); } else { state = list_directory(connection, name.source, &page); set_dir_content_type = 1; } } else { state = read_encoded_file(&name, &page); /* FIXME: If state is now S_ENCODE_ERROR we should try loading * the file undecoded. --jonas */ } done_string(&name); if (is_in_state(state, S_OK)) { struct cache_entry *cached; /* Try to add fragment data to the connection cache if either * file reading or directory listing worked out ok. */ cached = connection->cached = get_cache_entry(connection->uri); if (!connection->cached) { if (!redirect_location) done_string(&page); state = connection_state(S_OUT_OF_MEM); } else if (redirect_location) { if (!redirect_cache(cached, redirect_location, 1, 0)) state = connection_state(S_OUT_OF_MEM); } else { add_fragment(cached, 0, page.source, page.length); connection->from += page.length; if (!cached->head && set_dir_content_type) { unsigned char *head; /* If the system charset somehow * changes after the directory listing * has been generated, it should be * parsed with the original charset. */ head = straconcat((const unsigned char *)"\r\nContent-Type: text/html; charset=", get_cp_mime_name(get_cp_index((const unsigned char *)"System")), "\r\n", (unsigned char *) NULL); /* Not so gracefully handle failed memory * allocation. */ if (!head) state = connection_state(S_OUT_OF_MEM); /* Setup directory listing for viewing. */ mem_free_set(&cached->head, head); } done_string(&page); } } abort_connection(connection, state); }
/* Returns the inode encapsulated by DIR. */ struct inode * dir_get_inode (struct file *dir) { ASSERT (file_is_dir (dir)); return dir->inode; }
/* Searches for the element with the given name in the given directory. Returns the sector of the given element, or -1 if the element was not found in dir. */ int dir_lookup (struct file *dir, const char *name) { ASSERT (file_is_dir (dir)); return lookup (dir, name, NULL, NULL); }
/** * @fn int z_compress(z_t zip, const z_file_t zname, const char* password, z_clevel_et level, _Bool append, _Bool exclude_path, fifo_t files) * @brief Creation of a new ZIP file. * @param zip The ZIP context. * @param zname The zip file name. * @param password the zip password else NULL or empty. * @param level The compression level. * @param append Append mode. * @param exclude_path Exclude the file path. * @param files The file list. * @retunr 0 on success else -1. */ int z_compress(z_t zip, const z_file_t zname, const char* password, z_clevel_et level, _Bool append, _Bool exclude_path, fifo_t files) { struct z_s* z = Z_CAST(zip); z_file_t filename_try; int size_buf = 0; void* buf = NULL; zipFile zf; size_buf = Z_WRITE_BUFFER_SIZE; buf = (void*)malloc(size_buf); if (!buf) { logger(LOG_ERR, "Error allocating memory\n"); return -1; } bzero(filename_try, sizeof(z_file_t)); strcpy(filename_try, zname); if(!string_indexof(filename_try, ".") == -1) strcat(filename_try, ".zip"); zf = zipOpen64(filename_try, (append) ? 2 : 0); if (!zf) { free(buf); logger(LOG_ERR, "Error opening %s\n", filename_try); return -1; } else logger(LOG_DEBUG, "Creating %s\n", filename_try); while(!fifo_empty(files)) { const char* filenameinzip = fifo_pop(files); FILE * fin; int size_read; const char *savefilenameinzip; zip_fileinfo zi; unsigned long crc_file = 0; int zip64 = 0; memset(&zi, 0, sizeof(zip_fileinfo)); if(file_is_dir(filenameinzip)) { ((char*)filenameinzip)[strlen(filenameinzip)] = z->dir_delimiter; strncat((char*)filenameinzip, ".empty", sizeof(file_name_t)); file_touch(filenameinzip); } logger(LOG_DEBUG, "Trying to add file '%s'\n", filenameinzip); file_time(filenameinzip, (struct tm*)&zi.tmz_date); if(password != NULL && strlen(password)) if(z_get_file_crc(filenameinzip, buf, size_buf, &crc_file) != ZIP_OK) { zipClose(zf, NULL); free(buf); logger(LOG_ERR, "Error getting the crc for the file %s\n", filenameinzip); return -1; } zip64 = file_is_large_file(filenameinzip); /* The path name saved, should not include a leading slash. */ /*if it did, windows/xp and dynazip couldn't read the zip file. */ savefilenameinzip = filenameinzip; while(savefilenameinzip[0] == z->dir_delimiter) savefilenameinzip++; /*should the zip file contain any path at all?*/ if(exclude_path) { const char *tmpptr; const char *lastslash = 0; for(tmpptr = savefilenameinzip; *tmpptr; tmpptr++) { if(*tmpptr == z->dir_delimiter) lastslash = tmpptr; } if(lastslash) savefilenameinzip = lastslash+1; // base filename follows last slash. } if(zipOpenNewFileInZip3_64(zf, savefilenameinzip, &zi, NULL, 0, NULL, 0, NULL /* comment*/, (level != 0) ? Z_DEFLATED : 0, level,0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, (password != NULL && strlen(password)) ? password : NULL, crc_file, zip64) != ZIP_OK) { zipClose(zf, NULL); free(buf); logger(LOG_ERR, "Error in opening %s in zipfile\n", filenameinzip); return -1; } fin = fopen64(filenameinzip, "rb"); if(!fin) { zipCloseFileInZip(zf); zipClose(zf, NULL); free(buf); logger(LOG_ERR, "Error in opening %s for reading\n", filenameinzip); return -1; } do { size_read = (int)fread(buf,1,size_buf,fin); if(size_read < size_buf) if(!feof(fin)) { logger(LOG_ERR, "Error in reading %s\n",filenameinzip); break; } if (size_read > 0) { if(zipWriteInFileInZip(zf, buf, size_read) < 0) { logger(LOG_ERR, "Error in writing %s in the zipfile\n", filenameinzip); break; } } } while(size_read > 0); if(fin) fclose(fin); if(zipCloseFileInZip(zf) != ZIP_OK) { logger(LOG_ERR, "Error in closing %s in the zipfile\n", filenameinzip); break; } } if(zipClose(zf, NULL) != ZIP_OK) logger(LOG_ERR, "Error in closing %s\n",filename_try); free(buf); return 0; }
static void provisioning_mode() { INFO("Check for existence of device certificate"); bool need_initialization = (!file_exists(DEVICE_CERT_FILE) || !token_file_exists()); // device needs a device certificate if (!file_exists(DEVICE_CONF)) { INFO("Going back to bootloader mode, device config does not exist (Proper" "userdata image needs to be flashed first)"); reboot_reboot(REBOOT); } if (need_initialization) { sleep(5); ssl_init(); } // if no certificate exists, create a csr if (!file_exists(DEVICE_CERT_FILE)) { INFO("Device certificate not available. Switch to device provisioning mode"); if (!file_exists(DEVICE_CSR_FILE) || !file_exists(DEVICE_KEY_FILE)) { DEBUG("Create CSR (recreate if corresponding private key file misses)"); if (file_exists(SCD_TOKEN_DIR) && file_is_dir(SCD_TOKEN_DIR)) { DEBUG("CSR folder already exists"); } else if (mkdir(SCD_TOKEN_DIR, 00755) != 0) { FATAL("Failed to create CSR directory"); } #ifdef ANDROID char *hw_serial = mem_alloc0(PROPERTY_VALUE_MAX); char *hw_name = mem_alloc0(PROPERTY_VALUE_MAX); bool property_read_failure = false; if (!(property_get(PROP_SERIALNO, hw_serial, NULL) > 0)) { ERROR("Failed to read hardware serialno property"); property_read_failure = true; } if (!(property_get(PROP_HARDWARE, hw_name, NULL) > 0)) { ERROR("Failed to read hardware name property"); property_read_failure = true; } char *common_name; if (!property_read_failure) common_name = mem_printf("%s %s", hw_name, hw_serial); else common_name = mem_printf("%s %s", "x86", "0000"); DEBUG("Using common name %s", common_name); #else char *common_name = mem_strdup("common_name"); char *hw_serial = mem_strdup("hw_serial"); char *hw_name = mem_strdup("hw_unknown"); #endif // create device uuid and write to device.conf uuid_t *dev_uuid = uuid_new(NULL); const char *uid; if (!dev_uuid || (uid = uuid_string(dev_uuid)) == NULL) { FATAL("Could not create device uuid"); } DeviceConfig *dev_cfg = (DeviceConfig *) protobuf_message_new_from_textfile(DEVICE_CONF, &device_config__descriptor); if (!dev_cfg) { FATAL("Failed load device config from file \"%s\"!", DEVICE_CONF); } // set device uuid char *proto_uid = mem_strdup(uid); // free this element, as it is overwritten mem_free(dev_cfg->uuid); dev_cfg->uuid = proto_uid; // write the uuid to device config file if (protobuf_message_write_to_file(DEVICE_CONF, (ProtobufCMessage *) dev_cfg) < 0) { FATAL("Could not write device config to \"%s\"!", DEVICE_CONF); } if (ssl_create_csr(DEVICE_CSR_FILE, DEVICE_KEY_FILE, NULL, common_name, uid) != 0) { FATAL("Unable to create CSR"); } // this call also frees proto_uid protobuf_free_message((ProtobufCMessage *) dev_cfg); mem_free(hw_serial); mem_free(hw_name); mem_free(common_name); uuid_free(dev_uuid); DEBUG("CSR with keyfile created and stored"); } else { DEBUG("CSR with keyfile already exists"); } // self-sign device csr to bring the device up // corresponding cert is overwritten during provisioning DEBUG("Create self-signed certificate from CSR"); if (ssl_self_sign_csr(DEVICE_CSR_FILE, DEVICE_CERT_FILE, DEVICE_KEY_FILE) != 0) { FATAL("Unable to self sign existing device.csr"); } } else { INFO("Device certificate found"); if (file_exists(DEVICE_CSR_FILE)) { // this is the case when a non-provisioned trustme phone // created its own device.cert and user.p12 WARN("Device CSR still exists. Device was not correctly provisioned!"); } } // self-create a user token to bring the device up // is removed during provisioning if (!token_file_exists()) { DEBUG("Create initial soft token"); char *token_file = mem_printf("%s/%s%s", SCD_TOKEN_DIR, TOKEN_DEFAULT_NAME, TOKEN_DEFAULT_EXT); if (ssl_create_pkcs12_token(token_file, NULL, TOKEN_DEFAULT_PASS, TOKEN_DEFAULT_NAME) != 0) { FATAL("Unable to create initial user token"); } mem_free(token_file); } // we now have anything for a clean startup so just die and let us be restarted by init if (need_initialization) { ssl_free(); exit(0); } // remark: no certificate validation checks are carried out if (!file_exists(DEVICE_KEY_FILE) || !file_exists(SSIG_ROOT_CERT) || !file_exists(GEN_ROOT_CERT) || !token_file_exists()) { FATAL("Missing certificate chains, user token, or private key for device certificate"); } }
// filtloc and filter operate on the filenames and determine whether they // may be selected: // ALL: don't filter, in this case, filter can be NULL // BASE: filter with cmp_base(filename, filter) - only show when part up to // last extension matches // EXT: filter with cmp_ext(filename, filter) - only show when (last) extension // matches // NAME: filter with strcasecmp(filename, filter) - only show when whole name // matches char * select_file(enum filter_spec filtloc, char *filter) { char *selected_file, str[256]; int npages, pagenum = 1; const int perpage = PERPAGE - 1; DECL_LINE(backbtn); DECL_LINE(prevpage); DECL_LINE(nextpage); strcpy(sbstr, "file browser"); selected_file = malloc(PATH_MAX * sizeof(char)); selected_file[0] = '\0'; while (selected_file[0] == '\0') { char *pwd = NULL; int n; int *by, *kept; int j, nkept; int match, keep; uint16_t mode; sel = -1; clear_screen(); START_LIST(8, 48, 448, 0xFF404040, 0xFF808080, 0xFFC0C0C0) update_dir_list(); n = file_count(); by = malloc(n * sizeof(int)); kept = malloc(n * sizeof(int)); npages = 1 + n / perpage; pwd = getcwd(pwd, PATH_MAX); text(pwd, 16, 24, 1, 1, 0xFF606060, 0xFF000000); DRAW_LINE(backbtn, "back", "return to previous menu without making a selection"); if (pagenum > 1) { DRAW_LINE(prevpage, "previous page", "not all files are shown"); } j = 0; for (int i = 0; i < n; ++i) { switch (filtloc) { case ANY: match = 1; break; case BASE: match = !cmp_base(file_name(i), filter); break; case EXT: match = !cmp_ext(file_name(i), filter); break; case NAME: match = !strcasecmp(file_name(i), filter); break; default: match = 0; } if (file_is_dir(i) || match) { kept[j] = i; ++j; } } nkept = j; for (int i = perpage * (pagenum - 1); i < nkept; ++i) { if (i > pagenum * perpage) break; snprintf(str, sizeof(str), "permissions = %o", file_mode(kept[i]) & 07777); USECOLR = !USECOLR; CURCOLR = USECOLR ? BG1COLR : BG2COLR; current_y += 48; by[i] = current_y; fill_rect(0, by[i], 1024, 44, CURCOLR); text(file_name(kept[i]), col1_x, by[i] + 8, 1, 1, 0xFFFFFFFF, CURCOLR); text(str, col2_x, by[i] + 8, 1, 1, 0xFFFFFFFF, CURCOLR); } if (pagenum < npages) { DRAW_LINE(nextpage, "next page", "not all files are shown"); } while (sel == -1) { update_screen(); input_read(); if (BTN_CLICKED(backbtn)) { free(by); free(kept); return NULL; } for (int i = perpage * (pagenum - 1); i <= nkept; ++i) if (was_clicked(0, by[i], 1024, 44)) sel = kept[i]; if (BTN_CLICKED(prevpage)) { --pagenum; break; } else if (BTN_CLICKED(nextpage)) { ++pagenum; break; } } if (sel != -1) { free(by); free(kept); pagenum = 1; if (file_is_dir(sel)) { if (chdir(file_name(sel)) == -1) perror("chdir"); } else { strcpy(selected_file, pwd); strcat(selected_file, "/"); strcat(selected_file, file_name(sel)); } } } return selected_file; }