wilde@121: /** wilde@121: * @file wilde@121: * @brief Mozilla installation process aheinecke@99: * aheinecke@99: * Reads from stdin a list of instructions in the form: aheinecke@99: * aheinecke@99: * I:\r\n aheinecke@99: * R:\r\n aheinecke@99: * ... aheinecke@99: * aheinecke@130: * The maximum size of an input line is 9999 characters aheinecke@99: * (including the \r\n) at the end of the line. aheinecke@99: * aheinecke@99: * Certificates marked with I: will be installed and the ones aheinecke@99: * marked with R: will be searched and if available removed from aheinecke@99: * the databases. aheinecke@99: * aheinecke@99: * This tool tries to find all NSS databases the user has aheinecke@99: * access to and to execute the instructions on all of them. aheinecke@99: * aheinecke@99: * If there are other processes accessing the databases the caller aheinecke@99: * has to ensure that those are terminated before this process is aheinecke@99: * executed. aheinecke@99: * aheinecke@99: * Returns 0 on success (Even when no stores where found) an error value aheinecke@99: * as defined in errorcodes.h otherwise. aheinecke@99: * aheinecke@99: * Success messages are written to stdout. Errors to stderr. For logging aheinecke@99: * purposes each installation / removal of a certificate will be reported aheinecke@99: * with the profile name that it modified. aheinecke@99: * aheinecke@99: */ aheinecke@99: aheinecke@44: /* @brief IniParser for mozilla profiles.ini aheinecke@44: * wilde@110: * Parse data to find values formed in aheinecke@44: * aheinecke@44: * [Profile99] aheinecke@44: * IsRelative=1 aheinecke@44: * Path=Profiles/fooo.bar aheinecke@44: * aheinecke@44: * or aheinecke@44: * [Profile0] aheinecke@44: * IsRelative=0 aheinecke@44: * Path=c:\foo\bar\baz aheinecke@44: * aheinecke@44: * Mozilla also accepts the ini file on Windows even if it is UTF-16 aheinecke@44: * encoded. aheinecke@44: * */ aheinecke@44: wilde@173: #include wilde@119: #include wilde@119: #include wilde@119: #include wilde@119: #include wilde@173: #include wilde@119: wilde@173: #include wilde@113: #include wilde@147: #include wilde@119: #include wilde@113: wilde@113: #ifndef _WIN32 wilde@173: #define LINUX 1 wilde@113: #else wilde@173: #define LINUX 0 wilde@113: #endif wilde@113: wilde@147: #define LINEBUFLEN 1000 wilde@147: wilde@119: /** wilde@119: * @brief Global Return Code wilde@119: * wilde@119: * This will be retuned by the programm and might be set to an wilde@119: * error code on fatal errors and to and warning code on non-fatal wilde@119: * errors. In case of mor than one warning the warning codes will be wilde@119: * ORed together. wilde@119: */ wilde@119: int return_code = 0; aheinecke@44: aheinecke@44: /** wilde@180: * @brief Return users home path, on windows including drive letter wilde@180: * @returns a pointer to a string containing the home path, it should wilde@180: * be freed by the caller. wilde@180: */ wilde@180: static char * wilde@180: get_home() wilde@180: { wilde@180: char *home, *homevar, *fqhome; wilde@180: char *homedrive = NULL; wilde@180: wilde@180: size_t len; wilde@180: if (LINUX) wilde@180: homevar = "HOME"; wilde@180: else wilde@180: homevar = "HOMEPATH"; wilde@180: wilde@180: if ((home = getenv(homevar)) == NULL) wilde@180: { wilde@180: DEBUGFPRINT("DEBUG: FATAL! No HOME in environment.\n"); wilde@180: exit(ERR_MOZ_HOMELESS); wilde@180: } wilde@180: wilde@180: len = strlen(home); wilde@180: if (!LINUX) wilde@180: homedrive = getenv("HOMEDRIVE"); wilde@180: wilde@180: if (homedrive != NULL) wilde@180: len += strlen(homedrive); wilde@180: wilde@180: len++; /* Room for \0 */ wilde@180: fqhome = xmalloc(len); wilde@180: wilde@180: if (homedrive == NULL) wilde@180: snprintf(fqhome, len, "%s", home); wilde@180: else wilde@180: snprintf(fqhome, len, "%s%s", homedrive, home); wilde@180: wilde@180: return fqhome; wilde@180: } wilde@180: wilde@180: /** wilde@119: * @brief Get a list of all mozilla profile directories aheinecke@44: * aheinecke@44: * Read the profiles.ini and extract all profile paths from that. aheinecke@44: * wilde@121: * @param[in] inifile_name path of the profile.ini to read. aheinecke@44: * @return NULL terminated array of strings containing containing the aheinecke@44: * absolute path of the profile directories. The array needs to aheinecke@44: * be freed by the caller. aheinecke@44: */ wilde@119: static char ** wilde@119: get_profile_dirs (char *inifile_name) wilde@119: { wilde@119: char **dirs = NULL; wilde@147: char *inifile_dirname; wilde@119: FILE *inifile; wilde@147: char line[LINEBUFLEN]; wilde@147: char *key; wilde@147: char *value; wilde@147: char path[LINEBUFLEN]; wilde@147: char *fqpath; wilde@119: bool inprofile = false; wilde@147: bool relative_path = false; aheinecke@44: wilde@119: if ((inifile = fopen(inifile_name, "r")) != NULL) wilde@119: { wilde@175: DEBUGFPRINT("DEBUG: Searching for profile paths in: '%s'\n", inifile_name); wilde@175: wilde@147: inifile_dirname = port_dirname(inifile_name); wilde@147: while (fgets(line, LINEBUFLEN, inifile) != NULL) wilde@119: { wilde@147: /* Determine if we are in an profile section */ wilde@147: if (str_starts_with(line, "[Profile")) wilde@147: { wilde@147: relative_path = false; wilde@147: inprofile = true; wilde@147: } wilde@119: else if (line[0] == '[') wilde@119: inprofile = false; wilde@147: wilde@147: /* If we are in a profile parse path related stuff */ wilde@147: if (inprofile) wilde@147: { wilde@157: key = strtok(line, "="); wilde@157: value = strtok(NULL, "="); wilde@147: str_trim(&value); wilde@147: if (str_equal(key, "Path")) wilde@147: { wilde@147: if (relative_path) wilde@147: snprintf(path, LINEBUFLEN, "%s/%s", inifile_dirname, value); wilde@147: else wilde@147: strncpy(path, value, LINEBUFLEN); wilde@147: if ((fqpath = port_realpath(path)) != NULL) wilde@147: { wilde@180: DEBUGFPRINT("DEBUG: Found profile path: '%s'\n", fqpath); wilde@147: strv_append(&dirs, fqpath, strlen(fqpath)); wilde@147: free (fqpath); wilde@147: } wilde@147: else wilde@175: { wilde@180: DEBUGFPRINT("DEBUG: WARN! Non existent profile path: '%s'\n", path); wilde@175: return_code |= WARN_MOZ_PROFILE_DOES_NOT_EXIST; wilde@175: } wilde@147: } wilde@147: else if (str_equal(key, "IsRelative") && wilde@147: str_starts_with(value, "1")) wilde@147: relative_path = true; wilde@147: } wilde@119: } bernhard@179: fclose(inifile); wilde@119: } wilde@119: else wilde@119: { wilde@180: DEBUGFPRINT("DEBUG: WARN! Could not open ini file: '%s'\n", inifile_name); wilde@119: return_code |= WARN_MOZ_FAILED_TO_OPEN_INI; wilde@119: } wilde@119: return dirs; wilde@119: } aheinecke@44: wilde@173: /** wilde@173: * @brief Search for mozilla profiles.ini files wilde@173: * wilde@173: * Use well known paths and heuristics to find the current users wilde@173: * profiles.ini files on GNU/Linux and Windows systems. wilde@173: * wilde@173: * @return NULL terminated array of strings containing the absolute wilde@173: * path of the profiles.ini files. The array needs to be freed by the wilde@173: * caller. wilde@173: */ wilde@173: static char ** wilde@173: get_profile_inis () wilde@173: { wilde@173: char **inis = NULL; wilde@173: char path[LINEBUFLEN]; wilde@173: char *fqpath; wilde@180: char *mozdirname; wilde@173: DIR *mozdir; wilde@173: struct dirent *mozdirent; wilde@180: char *home = get_home(); wilde@173: wilde@173: if (LINUX) wilde@173: { wilde@180: mozdirname = ".mozilla"; wilde@173: } wilde@173: else wilde@173: { wilde@180: mozdirname = "AppData/Roaming/Mozilla"; wilde@180: } wilde@180: wilde@180: snprintf(path, LINEBUFLEN, "%s/%s", home, mozdirname); wilde@180: if ((mozdir = opendir(path)) != NULL) wilde@180: { wilde@180: while ((mozdirent = readdir(mozdir)) != NULL) wilde@180: { wilde@180: snprintf(path, LINEBUFLEN, "%s/%s/%s", wilde@180: home, wilde@180: mozdirname, wilde@180: mozdirent->d_name); wilde@180: if (port_isdir(path)) wilde@180: { wilde@180: snprintf(path, LINEBUFLEN, "%s/%s/%s/%s", wilde@180: home, wilde@180: mozdirname, wilde@180: mozdirent->d_name, wilde@180: "profiles.ini"); wilde@180: DEBUGFPRINT("DEBUG: checking for %s...\n", path); wilde@180: if ((fqpath = port_realpath(path)) != NULL) wilde@180: { wilde@180: strv_append(&inis, fqpath, strlen(fqpath)); wilde@180: DEBUGFPRINT("DEBUG: Found mozilla ini file: '%s'\n", fqpath); wilde@180: free(fqpath); wilde@180: } wilde@180: } wilde@180: } wilde@180: closedir(mozdir); wilde@180: } wilde@180: else wilde@180: { wilde@180: DEBUGFPRINT("DEBUG: Could not open %s/%s\n", home, mozdirname); wilde@180: exit(WARN_MOZ_NO_PROFILES); wilde@173: } wilde@173: return inis; wilde@173: } wilde@173: wilde@173: wilde@113: int wilde@173: main () wilde@113: { wilde@119: int x = 0; wilde@173: int y = 0; wilde@173: char **mozinis, **pdirs; wilde@173: if ((mozinis = get_profile_inis()) != NULL) wilde@173: while (mozinis[y] != NULL) wilde@173: { wilde@173: pdirs = wilde@173: get_profile_dirs(mozinis[y++]); wilde@173: if (pdirs != NULL) wilde@173: { wilde@173: while (pdirs[x] != NULL) wilde@173: puts(pdirs[x++]); wilde@173: strv_free(pdirs); wilde@173: } wilde@173: } wilde@119: exit(return_code); aheinecke@44: }