Mercurial > trustbridge
diff cinst/main.c @ 310:f758460ca437
Merged
author | Sascha Wilde <wilde@intevation.de> |
---|---|
date | Fri, 04 Apr 2014 09:54:19 +0200 |
parents | fac7e1b0e558 |
children | f17226aa2e09 |
line wrap: on
line diff
--- a/cinst/main.c Fri Apr 04 09:53:55 2014 +0200 +++ b/cinst/main.c Fri Apr 04 09:54:19 2014 +0200 @@ -7,23 +7,26 @@ * 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----- + * The first parameter to this process should be list=<file_name> + * of the certificate list to work on. The second parameter should + * be instruction=<instruction_file_name>|uninstall * - * Followed by additional instruction lines of: + * instruction_file_name should be the absolute path to an + * instructions file formatted as: + * * I:<certificate> * R:<certificate> * + * Line breaks can be system dependent in the Instructions file. + * * 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 + * 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. + * are part of the list. * **/ #include <stdio.h> @@ -34,8 +37,10 @@ #include "strhelp.h" #include "listutil.h" +#include "logging.h" #include "errorcodes.h" #include "windowsstore.h" +#include "nssstore.h" /* The certificate list + instructions may only be so long as * twice the accepted certificatelist size */ @@ -43,40 +48,62 @@ /* @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. + * Reads instructions from an input file into the to_install + * and to_remove buffers. + * + * Lines starting with I: are treated as install instructions. + * Lines starting with R: are treated as remove instructions. + * Other lines are ignored. + * * Terminates in OOM conditions. * * The caller needs to free the memory allocated by this function * even when an error is returned. * - * Uninstall certificates are all certificates that are pa - * - * @param[out] certificate_list the parsed certificate list + * @param[in] file_name absolute path to the instructions file. * @param[out] to_install strv of installation instructions or NULL * @param[out] to_remove strv of remove instructions or NULL - * @param[out] all_certs strv of uninstallation instructions or NULL * * @returns: 0 on success. An error code otherwise. */ -int -readInput (char **certificate_list, char ***to_install, - char ***to_remove, char ***all_certs) +static int +read_instructions_file (char *file_name, char ***to_install, + char ***to_remove) { int lines_read = 0; - int readingList = 0; - size_t list_size = 0; char buf[MAX_LINE_LENGTH + 2]; + FILE *f = NULL; + long file_size; - if (*certificate_list || *to_install || *to_remove) + if (*to_install || *to_remove) { - printf ("Error invalid parameters\n"); + printf ("Error invalid parameters.\n"); return -1; } - while (fgets (buf, MAX_LINE_LENGTH + 1, stdin) ) + f = fopen (file_name, "rb"); + if (f == NULL) + return ERR_NO_INSTRUCTIONS; + + fseek (f, 0, SEEK_END); + file_size = ftell (f); + if (file_size <= 0) { - size_t len = strlen (buf); /* fgets ensures buf is terminated */ + fclose (f); + return ERR_NO_INSTRUCTIONS; + } + + fseek (f, 0, SEEK_SET); + + if (file_size + 1 == 0) + { + fclose (f); + return ERR_INVALID_INSTRUCTIONS; + } + + while (fgets (buf, MAX_LINE_LENGTH + 1, f) ) + { + size_t len = strlen (buf); /* fgets ensures buf is terminated */ if (len <= 3) { printf ("Line too short.\n"); @@ -87,50 +114,20 @@ printf ("Too many lines\n"); return ERR_TOO_MUCH_INPUT; } - - if (buf[len - 2] != '\r') - { - if (buf[len - 1] != '\n') - { - printf ("Line too long.\n"); - return ERR_INVALID_INPUT; - } - buf[len - 1] = '\r'; - buf[len] = '\n'; - buf[len + 1] = '\0'; - len++; - } - - 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, &list_size, buf, len); - } - else if (strcmp ("UNINSTALL\r\n", buf) == 0) - { - /* Remove trailing \r\n */ - strv_append (to_remove, buf, len - 2); - continue; - } if (*buf == 'I') { - /* Remove leading I: and trailing \r\n */ - strv_append (readingList ? all_certs : to_install, buf + 2, len - 4); + char *trimmed = buf+2; + /* Remove leading I: and trailing whitespace */ + str_trim(&trimmed); + strv_append (to_install, trimmed, strlen(trimmed)); continue; } if (*buf == 'R') { - /* Remove leading R: and trailing \r\n */ - strv_append (readingList ? all_certs : to_remove, buf + 2, len - 4); + char *trimmed = buf+2; + /* Remove leading R: and trailing whitespace */ + str_trim(&trimmed); + strv_append (to_remove, trimmed, strlen(trimmed)); continue; } } @@ -170,7 +167,7 @@ bool found = false; for (j = 0; all_certs[j]; j++) { - if (strncmp (to_validate[i], all_certs[j], MAX_LINE_LENGTH - 2) == + if (strncmp (to_validate[i], all_certs[j], MAX_LINE_LENGTH) == 0) { found = true; @@ -179,7 +176,7 @@ } if (!found) { - printf ("Install instruction with invalid certificate\n."); + DEBUGPRINTF ("Failed to find certificate; \n%s\n", to_validate[i]); return ERR_INVALID_INSTRUCTIONS; } } @@ -189,47 +186,103 @@ int -main () +main (int argc, char **argv) { - char **to_install = NULL; - char **to_remove = NULL; - char **all_certs = NULL; - char *certificate_list = NULL; + /* TODO handle wchar arguments on Windows or do conversion dance */ + char **to_install = NULL, + **to_remove = NULL, + **all_valid_certs = NULL; + int ret = -1; + + char *certificate_list = NULL, + *certificate_file_name = NULL, + *instruction_file_name = NULL; size_t list_len = 0; - int ret = -1; - bool uninstall = false; + list_status_t list_status; + bool do_uninstall = false; - ret = readInput (&certificate_list, &to_install, &to_remove, &all_certs); + /* Some very static argument parsing. list= and instructions= is only + added to make it more transparent how this programm is called if + a user looks at the detailed uac dialog. */ + if (argc != 3 || strncmp(argv[1], "list=", 5) != 0 || + strncmp(argv[2], "instructions=", 13) != 0) + { + ERRORPRINTF ("Invalid arguments.\n" + "Expected arguments: list=<certificate_list> \n" + " instructions=<instructions_file>|uninstall\n"); + return ERR_INVALID_PARAMS; + } + + certificate_file_name = strchr(argv[1], '=') + 1; + instruction_file_name = strchr(argv[2], '=') + 1; + + if (!certificate_file_name || !instruction_file_name) + { + ERRORPRINTF ("Invalid arguments.\n" + "Expected arguments: list=<certificate_list> \n" + " instructions=<instructions_file>|uninstall\n"); + return ERR_INVALID_PARAMS; + } + + if (strncmp(instruction_file_name, "uninstall", 9) == 0) + { + do_uninstall = true; + instruction_file_name = NULL; + } + + list_status = read_and_verify_list (certificate_file_name, &certificate_list, + &list_len); + + if (list_status != Valid) + { + if (list_status == InvalidSignature) + { + return ERR_INVALID_SIGNATURE; + } + + return ERR_INVALID_INPUT_NO_LIST; + } + + all_valid_certs = get_certs_from_list (certificate_list, list_len); + + if (!all_valid_certs) + { + /* Impossible */ + return -1; + } + + + /* For uninstall we are done now */ + if (do_uninstall) + { +#ifdef WIN32 + ret = write_stores_win (NULL, all_valid_certs); + if (ret != 0) + { + ERRORPRINTF ("Failed to write windows stores retval: %i\n", ret); + } +#endif + ret = write_stores_nss (NULL, all_valid_certs); + return ret; + } + + ret = read_instructions_file (instruction_file_name, &to_install, + &to_remove); if (ret) { return ret; } - if (!certificate_list) - { - return ERR_INVALID_INPUT_NO_LIST; - } - - list_len = strnlen (certificate_list, MAX_INPUT_SIZE); - - ret = verify_list (certificate_list, list_len); - - if (ret) - { - 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 */ if (to_install) { - ret = validate_instructions (all_certs, to_install); + ret = validate_instructions (all_valid_certs, to_install); if (ret) { return ret; @@ -238,39 +291,27 @@ if (to_remove) { - if (to_remove[0] - && strncmp ("UNINSTALL", to_remove[0], MAX_LINE_LENGTH) == 0) + ret = validate_instructions (all_valid_certs, to_remove); + if (ret) { - uninstall = true; - strv_free (to_remove); - to_remove = NULL; - } - else - { - ret = validate_instructions (all_certs, to_remove); - if (ret) - { - return ret; - } + return ret; } } - if (uninstall) +#ifdef WIN32 + ret = write_stores_win (to_install, to_remove); + if (ret != 0) { - /* To uninstall does not have to be verified as it part of the - * signed list.*/ - to_remove = all_certs; + ERRORPRINTF ("Failed to write windows stores retval: %i\n", ret); } - else +#endif + ret = write_stores_nss (to_install, to_remove); + + if (ret != 0) { - strv_free (all_certs); - all_certs = NULL; + ERRORPRINTF ("Failed to write nss stores"); } -#ifdef WIN32 - return write_stores_win (to_install, to_remove); -#endif - /* Make valgrind happy */ strv_free (to_install); strv_free (to_remove);