view cinst/mozilla.c @ 92:4980b0deb773

Fix memleak in case of invalid signature
author Andre Heinecke <aheinecke@intevation.de>
date Fri, 21 Mar 2014 09:47:54 +0000
parents b3e8e047bc2c
children bc1e6732f43c
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

/* @brief IniParser for mozilla profiles.ini
 *
 * Parse data to find values formed in 
 *
 * [Profile99]
 * IsRelative=1
 * Path=Profiles/fooo.bar
 *
 * or
 * [Profile0]
 * IsRelative=0
 * Path=c:\foo\bar\baz
 *
 * Mozilla also accepts the ini file on Windows even if it is UTF-16
 * encoded.
 * */


/**
 *  @brief Read a file into memory.
 *
 * @param[in] fileName Name of the file (UTF-8 encoded).
 * @param[out] data Newly allocated pointer to the file content.
 * @param[out] size Size in Bytes of the file content.
 * @param[in] maxSize the maximum size to read.
 *
 * @return 0 on success an error code otherwise.
 */

#define RAF_UNKNOWN -1
#define RAF_UNREADABLE -2
#define RAF_STATFAILED -3
#define RAF_TOOLARGE -4
#define RAF_OUTOFCORE -5
int readFile(const char *fileName, char **data, size_t *size,
             const size_t maxSize)
{
    int fd = -1;
    struct stat fileStat;
    int rc = 0;
    ssize_t bRead = 0;
    int retval = -1;

    memset(&fileStat, 0, sizeof(fileStat));

    fd = open(fileName, O_RDONLY);
    if (fd == -1) {
        printf("Error: %s \n", strerror(errno));
        retval = RAF_UNREADABLE;
        goto cleanup;
    }

    rc = fstat(fd, &fileStat);
    if (rc < 0) {
        printf ("Stat failed with rc: %i\n", rc);
        retval = RAF_STATFAILED;
        goto cleanup;
    }

    // Check the size of the file
    if (!fileStat.st_size) {
        printf("Size zero\n");
        retval = RAF_STATFAILED;
        goto cleanup;
    }

    if (fileStat.st_size > maxSize &&
            fileStat.st_size > 0) {
        printf("File too large\n");
        retval = RAF_TOOLARGE;
        goto cleanup;
    }

    *size = (size_t) fileStat.st_size;

    *data = (char*) malloc(*size);

    if (*data == NULL) {
        retval = RAF_OUTOFCORE;
        goto cleanup;
    }

    bRead = read(fd, *data, *size);

    if (bRead < 0 || (size_t) bRead != *size) {
        printf("Read failed\n");
        if (bRead == -1) {
            printf("Error: %s \n", strerror(errno));
        }
        retval = RAF_UNKNOWN;
        *size = 0;
        if (*data) {
            free(*data);
            printf("Nulling data\n");
            *data = NULL;
        }
        goto cleanup;
    }

cleanup:

    if (fd && fd != -1) {
        close(fd);
        fd = -1;
    }

    return retval;
}


#ifndef _WIN32

#define INI_LOCATIONS {                   \
    "/.mozilla/firefox/profiles.ini",     \
    "/.mozilla/thunderbird/profiles.ini", \
    NULL }

/**
 * @brief Get a list of all mozilla profile directories for this user
 *
 * Read the profiles.ini and extract all profile paths from that.
 *
 * @return NULL terminated array of strings containing containing the
 * absolute path of the profile directories. The array needs to
 * be freed by the caller.
 */
char **getProfilePaths() {
    char *homedir = NULL,
        **retval = NULL;
    const char* const iniLocations[] = INI_LOCATIONS;
    int i = 0;

    homedir = getenv ("HOME");

    if (!homedir) {
        printf ("Could not get HOME\n");
        return NULL;
    }

    for (i = 0; iniLocations[i] != NULL; i++) {
        char *candidate[MAX_PATH_LEN],
             *fileContent = NULL;
        const size_t needed = strnlen (homedir, MAX_PATH_LEN) +
                        strnlen (iniLocations[i], MAX_PATH_LEN);
               fileSize = 0;
        int err = 0;

        memset (candidate, 0, MAX_PATH_LEN);

        /* Verify that addition of strlen did not overflow and
         * that the buffer is large enough */
        if (needed < strnlen (homedir, MAX_PATH_LEN_LEN) || needed >= MAX_PATH - 1) {
            printf ("Error invalid HOME environment variable");
            return NULL;
        }

        strncpy (candidate, homedir, MAX_PATH_LEN);
        /* Environment might have been modified */
        if (candidate[MAX_PATH_LEN - 1] != '\0') {
            printf ("Error invalid HOME");
            return NULL;
        }
        strncat (candidate, iniLocations[i], MAX_PATH_LEN - strnlen(candidate,
                    MAX_PATH_LEN) - 1);

        rc = readFile (candidate, &fileContent, &fileSize, MAX_FILESIZE);

        if (err) {
            printf ("Failed to read file.\n");
            continue;
        }
        parseIni (fileContent, &retval);
    }
}
#else /* _WIN32 */
char **getProfilePaths() {
    return NULL;
}
#endif

int main(int argc, char *argv) {
}

http://wald.intevation.org/projects/trustbridge/