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@224: #include wilde@224: #include wilde@224: #include wilde@224: #include wilde@119: #include wilde@119: #include wilde@119: #include wilde@119: #include wilde@173: #include wilde@119: wilde@230: #define DEBUGPREFIX "MOZ-" wilde@226: #include "debug.h" wilde@230: wilde@226: #include "errorcodes.h" wilde@226: #include "portpath.h" wilde@226: #include "strhelp.h" wilde@113: wilde@228: wilde@113: #ifndef _WIN32 wilde@197: #define CONFDIRS ".mozilla", ".thunderbird" wilde@223: #define TARGET_LINUX 1 wilde@113: #else wilde@197: #define CONFDIRS "Mozilla", "Thunderbird" wilde@223: #define TARGET_LINUX 0 wilde@113: #endif wilde@113: wilde@229: /** wilde@229: * @brief Length of string buffers used wilde@229: * wilde@229: * The maximal length of input is defined as 9999 (+ terminating \0). wilde@229: * We use it for other other input puffers besides the IPC input, too. wilde@229: * (One size fits all). wilde@229: */ wilde@229: #define LINEBUFLEN 10000 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@194: * @brief Return configuration base directory. wilde@194: * @returns A pointer to a string containing the path to the base wilde@194: * directory holding the configuration directories for e.g. mozilla wilde@194: * and thunderbird. wilde@180: */ wilde@180: static char * wilde@194: get_conf_basedir() wilde@180: { wilde@194: char *cdir, *envvar; wilde@180: wilde@223: if (TARGET_LINUX) wilde@194: envvar = "HOME" ; wilde@180: else wilde@194: envvar = "APPDATA"; wilde@180: wilde@194: if ((cdir = getenv(envvar)) != NULL) wilde@194: return cdir; wilde@194: else wilde@180: { wilde@228: DEBUGPRINTF("FATAL! No %s in environment.\n", envvar); wilde@180: exit(ERR_MOZ_HOMELESS); wilde@180: } 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@228: DEBUGPRINTF("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@228: DEBUGPRINTF("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@228: DEBUGPRINTF("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@228: DEBUGPRINTF("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@173: DIR *mozdir; wilde@173: struct dirent *mozdirent; wilde@194: char *confbase = get_conf_basedir(); wilde@197: const char *confdirs[] = { CONFDIRS, NULL }; wilde@173: wilde@197: for (int i=0; confdirs[i] != NULL; i++) wilde@173: { wilde@197: snprintf(path, LINEBUFLEN, "%s/%s", wilde@197: confbase, wilde@197: confdirs[i]); wilde@197: if ((mozdir = opendir(path)) != NULL) wilde@180: { wilde@197: while ((mozdirent = readdir(mozdir)) != NULL) wilde@180: { wilde@197: snprintf(path, LINEBUFLEN, "%s/%s/%s", wilde@194: confbase, wilde@197: confdirs[i], wilde@197: mozdirent->d_name); wilde@197: if (port_isdir(path) wilde@197: && (strcmp(mozdirent->d_name, "..") != 0)) wilde@180: { wilde@197: snprintf(path, LINEBUFLEN, "%s/%s/%s/%s", wilde@197: confbase, wilde@197: confdirs[i], wilde@197: mozdirent->d_name, wilde@197: "profiles.ini"); wilde@228: DEBUGPRINTF("checking for %s...\n", path); wilde@197: if ((fqpath = port_realpath(path)) != NULL) wilde@197: { wilde@197: strv_append(&inis, fqpath, strlen(fqpath)); wilde@228: DEBUGPRINTF("Found mozilla ini file: '%s'\n", fqpath); wilde@197: free(fqpath); wilde@197: } wilde@180: } wilde@180: } wilde@197: closedir(mozdir); wilde@180: } wilde@197: else wilde@197: { wilde@228: DEBUGPRINTF("Could not open %s/%s\n", confbase, confdirs[i]); wilde@197: } wilde@180: } wilde@197: if (inis == NULL) wilde@180: { wilde@228: DEBUGPRINTF("No ini files found - will do nothing!\n"); wilde@180: exit(WARN_MOZ_NO_PROFILES); wilde@173: } wilde@173: return inis; wilde@173: } wilde@173: wilde@223: /** wilde@223: * @brief list certificates from nss certificate store wilde@223: * @param[in] confdir the directory with the certificate store wilde@223: */ wilde@223: static void wilde@223: nss_list_certs (char *confdir) wilde@223: { wilde@223: CERTCertList *list; wilde@223: CERTCertListNode *node; wilde@223: char *name; wilde@224: wilde@223: if (NSS_Initialize(confdir, "", "", "secmod.db", NSS_INIT_READONLY) wilde@223: == SECSuccess) wilde@223: { wilde@223: list = PK11_ListCerts(PK11CertListAll, NULL); wilde@223: for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); wilde@223: node = CERT_LIST_NEXT(node)) { wilde@223: name = node->appData; wilde@223: wilde@223: printf ("Found certificate \"%s\"\n", name); wilde@223: } wilde@223: CERT_DestroyCertList(list); wilde@223: NSS_Shutdown(); wilde@223: } wilde@223: else wilde@227: DEBUGPRINTF("Could not open nss cer store in %s!", confdir); wilde@223: } wilde@223: wilde@173: wilde@113: int wilde@173: main () wilde@113: { 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@223: for (int x=0; pdirs[x] != NULL; x++) wilde@223: { wilde@223: puts(pdirs[x]); wilde@223: nss_list_certs(pdirs[x]); wilde@223: } wilde@173: strv_free(pdirs); wilde@173: } wilde@173: } wilde@119: exit(return_code); aheinecke@44: }