view cinst/main.c @ 64:fb9f78f7ab2f

Improve error handling free memory before exiting. Include line endings in Marker lines
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 18 Mar 2014 14:14:15 +0000
parents 6acb1dae6185
children e4088afd5281
line wrap: on
line source
/** @brief Main entry point for the cinst process.
 *
 *  The cinst process may or may not be run with elevated
 *  privileges. When run with elevated privileges this
 *  process will modify system wide certificate stores.
 *  Otherwise only the users certificate stores are modified.
 *
 *  It expects a certificatelist on stdin enclosed in a
 *  -----BEGIN CERTIFICATE LIST-----
 *  ...
 *  -----END CERTIFICATE LIST-----
 *
 *  Followed by additional instruction lines of:
 *  I:<certificate>
 *  R:<certificate>
 *
 *  It will only execute the instructions if the
 *  I and R instructions are also part of the signed
 *  certificate list. The signature is validated with the
 *  built in key.
 *
 *  The special instruction "UNINSTALL" will cause the installer
 *  to remove all certificates (Even those marked with I) that
 *  are part of the list to be removed.
 *
 **/
#define MAX_LINE_LENGTH 1000
#define MAX_LINES 1000
#define MAX_INPUT_SIZE 2000000 /* MAX_LINE_LENGTH * (MAX_LINES *2) */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "strhelp.h"
#include "listutil.h"
#include "errorcodes.h"

/* @brief Read stdin into data structures.
 *
 * Reads from stdin and sorts the input into the respective
 * variables. The pointers returned need to be freed by the caller.
 * Terminates in OOM conditions.
 *
 * The caller needs to free the memory allocated by this function
 * even when an error is returned.
 *
 * @returns: 0 on success. An error code otherwise.
 */
int readInput(char **certificate_list, char ***to_install,
              char ***to_remove)
{
    int lines_read = 0;
    int readingList = 0;
    char buf[MAX_LINE_LENGTH + 1];

    while (fgets(buf, MAX_LINE_LENGTH + 1, stdin)) {
        size_t len = strlen(buf); /* fgets ensures buf is terminated */
        if (lines_read ++ > MAX_LINES) {
            printf("Too many lines\n");
            return ERR_TOO_MUCH_INPUT;
        }
        if (strcmp("-----BEGIN CERTIFICATE LIST-----\r\n", buf) == 0){
            readingList = 1;
            continue;
        }
        if (strcmp("-----END CERTIFICATE LIST-----\r\n", buf) == 0){
            readingList = 0;
            continue;
        }
        if (readingList) {
            str_append_str(certificate_list, buf, len);
            continue;
        }
        if (*buf == 'I') {
            array_append_str(to_install, buf+2, len - 2);
            continue;
        }
        if (*buf == 'R') {
            array_append_str(to_remove, buf+2, len - 2);
            continue;
        }
        if (strcmp("UNINSTALL", buf) == 0) {
            array_append_str(to_remove, buf, len - 2);
        }
    }

    return 0;
}

int validate_instructions(const char *certificate_list,
                          const size_t listLen,
                          const char **to_install,
                          const char **to_remove)
{
    /* TODO */
    return 0;
}

int main() {
    char **to_install = NULL;
    char **to_remove = NULL;
    char *certificate_list = NULL;
    size_t listLen = 0;
    int ret = -1;

    ret = readInput(&certificate_list, &to_install, &to_remove);

    if (ret != 0) {
        return ret;
    }

    if (!certificate_list) {
        return ERR_INVALID_INPUT_NO_LIST;
    }

    listLen = strnlen(certificate_list, MAX_INPUT_SIZE);

    ret = verify_list(certificate_list, listLen);

    if (ret != 0) {
        return ERR_INVALID_SIGNATURE;
    }

    if (!strv_length(to_install) && !strv_length(to_remove)) {
        return ERR_NO_INSTRUCTIONS;
    }

    /* Check that the instructions are ok to execute */
    ret = validate_instructions(certificate_list, to_install, to_remove);

    if (ret != 0) {
        return ERR_INVALID_INSTRUCTIONS;
    }

    /* Make valgrind happy */
    strfreev (to_install);
    strfreev (to_remove);
    free (certificate_list);

    return 0;
}

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