Mercurial > trustbridge
view cinst/main.c @ 149:bd5a5d3e5674
We decided to use bool. So let's use it.
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Mon, 24 Mar 2014 17:22:43 +0000 |
parents | 095d0e7f8ed4 |
children | dbbd761959ae |
line wrap: on
line source
/** * @file main.c * @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. * **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stdbool.h> #include "strhelp.h" #include "listutil.h" #include "errorcodes.h" #include "windowsstore.h" /* The certificate list + instructions may only be so long as * twice the accepted certificatelist size */ #define MAX_INPUT_SIZE MAX_LINE_LENGTH * MAX_LINES * 2 /* @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. * * Uninstall certificates are all certificates that are pa * * @param[out] certificate_list the parsed certificate list * @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) { int lines_read = 0; int readingList = 0; size_t list_size = 0; char buf[MAX_LINE_LENGTH + 2]; if (*certificate_list || *to_install || *to_remove) { printf("Error invalid parameters\n"); return -1; } while (fgets(buf, MAX_LINE_LENGTH + 1, stdin)) { size_t len = strlen(buf); /* fgets ensures buf is terminated */ if (len <= 3) { printf("Line too short.\n"); return ERR_INVALID_INPUT; } if (lines_read ++ > MAX_LINES) { 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", 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); continue; } if (*buf == 'R') { /* Remove leading R: and trailing \r\n */ strv_append(readingList ? all_certs : to_remove, buf+2, len - 4); continue; } } return 0; } /** @brief Check that the insturctions match to the list * * Only certificates part of the certificate_list are allowed * for installation. * * @param[in] all_certs strv of all valid certificates in a list * @param[in] to_validate strv of instructions * * @returns 0 on success, an error otherwise */ int validate_instructions(char **all_certs, char **to_validate) { int i = 0, j = 0; if (!all_certs || strv_length(all_certs) < 1) { /* Invalid parameters */ return -1; } if (to_validate == NULL) { /* Nothing is valid */ return 0; } for (i=0; to_validate[i]; i++) { bool found = false; for (j=0; all_certs[j]; j++) { if (strncmp(to_validate[i], all_certs[j], MAX_LINE_LENGTH - 2) == 0) { found = true; break; } } if (!found) { printf("Install instruction with invalid certificate\n."); return ERR_INVALID_INSTRUCTIONS; } } return 0; } int main() { char **to_install = NULL; char **to_remove = NULL; char **all_certs = NULL; char *certificate_list = NULL; size_t list_len = 0; int ret = -1; bool uninstall = false; ret = readInput(&certificate_list, &to_install, &to_remove, &all_certs); 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); if (ret) { return ret; } } if (to_remove) { if (to_remove[0] && strncmp("UNINSTALL", to_remove[0], MAX_LINE_LENGTH) == 0) { uninstall = true; strv_free(to_remove); to_remove = NULL; } else { ret = validate_instructions(all_certs, to_remove); if (ret) { return ret; } } } if (uninstall) { /* To uninstall does not have to be verified as it part of the * signed list.*/ to_remove = all_certs; } else { strv_free(all_certs); all_certs = NULL; } #ifdef WIN32 return install_certificates_win((const char**) to_install, true); //remove_certificates_win((const char**) to_remove, 1); #endif /* Make valgrind happy */ strv_free(to_install); strv_free(to_remove); free(certificate_list); return 0; }