23#error "Missing APP_VERSION"
26#define MAR_CHANNEL_ID "LOOnlineUpdater"
29#if !defined(NO_SIGN_VERIFY) && (!defined(_WIN32) || defined(MAR_NSS))
36 const char *
const *certNames,
42 printf(
"Version: %s\n", APP_VERSION);
48 printf(
"Create a MAR file:\n");
49 printf(
" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
50 "-c archive.mar [files...]\n");
51 printf(
" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
52 "-c archive.mar -f input_file.txt\n");
54 printf(
"Extract a MAR file:\n");
55 printf(
" mar [-C workingDir] -x archive.mar\n");
57 printf(
"Sign a MAR file:\n");
58 printf(
" mar [-C workingDir] -d NSSConfigDir -n certname -s "
59 "archive.mar out_signed_archive.mar\n");
61 printf(
"Strip a MAR signature:\n");
62 printf(
" mar [-C workingDir] -r "
63 "signed_input_archive.mar output_archive.mar\n");
65 printf(
"Extract a MAR signature:\n");
66 printf(
" mar [-C workingDir] -n(i) -X "
67 "signed_input_archive.mar base_64_encoded_signature_file\n");
69 printf(
"Import a MAR signature:\n");
70 printf(
" mar [-C workingDir] -n(i) -I "
71 "signed_input_archive.mar base_64_encoded_signature_file "
72 "changed_signed_output.mar\n");
73 printf(
"(i) is the index of the certificate to extract\n");
74#if defined(MACOSX) || (defined(_WIN32) && !defined(MAR_NSS))
75 printf(
"Verify a MAR file:\n");
76 printf(
" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
77 printf(
"At most %d signature certificate DER files are specified by "
80 printf(
"Verify a MAR file:\n");
81 printf(
" mar [-C workingDir] -d NSSConfigDir -n certname "
82 "-v signed_archive.mar\n");
83 printf(
"At most %d signature certificate names are specified by "
86 printf(
"At most %d verification certificate names are specified by "
89 printf(
"Print information on a MAR file:\n");
90 printf(
" mar -t archive.mar\n");
92 printf(
"Print detailed information on a MAR file including signatures:\n");
93 printf(
" mar -T archive.mar\n");
95 printf(
"Refresh the product information block of a MAR file:\n");
96 printf(
" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
97 "-i unsigned_archive_to_refresh.mar\n");
99 printf(
"Print executable version:\n");
100 printf(
" mar --version\n");
101 printf(
"This program does not handle unicode file paths properly\n");
107 (void) mar; (void) unused;
113static int mar_test(
const char *path) {
120 printf(
"SIZE\tMODE\tNAME\n");
127int main(
int argc,
char **argv) {
128 char *NSSConfigDir =
NULL;
131 char *productVersion = APP_VERSION;
132#ifndef NO_SIGN_VERIFY
136 uint32_t certCount = 0;
137 int32_t sigIndex = -1;
139#if !defined(NO_SIGN_VERIFY)
143#if (!defined(_WIN32) && !defined(MACOSX)) || defined(MAR_NSS)
148 memset((
void*)certNames, 0,
sizeof(certNames));
149#if defined(_WIN32) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
150 memset((
void*)certBuffers, 0,
sizeof(certBuffers));
152#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(_WIN32)) || \
154 memset(DERFilePaths, 0,
sizeof(DERFilePaths));
155 memset(fileSizes, 0,
sizeof(fileSizes));
158 if (argc > 1 && 0 == strcmp(argv[1],
"--version")) {
169 if (argv[1][0] ==
'-' && (argv[1][1] ==
'c' ||
170 argv[1][1] ==
't' || argv[1][1] ==
'x' ||
171 argv[1][1] ==
'v' || argv[1][1] ==
's' ||
172 argv[1][1] ==
'i' || argv[1][1] ==
'T' ||
173 argv[1][1] ==
'r' || argv[1][1] ==
'X' ||
174 argv[1][1] ==
'I')) {
177 }
else if (argv[1][0] ==
'-' && argv[1][1] ==
'C') {
182#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(_WIN32)) || \
187 else if (argv[1][0] ==
'-' &&
189 (argv[1][2] == (
char)(
'0' + certCount) || argv[1][2] ==
'\0')) {
194 DERFilePaths[certCount++] = argv[2];
200 else if (argv[1][0] ==
'-' && argv[1][1] ==
'd') {
201 NSSConfigDir = argv[2];
207 }
else if (argv[1][0] ==
'-' &&
209 (argv[1][2] == (
char)(
'0' + certCount) ||
210 argv[1][2] ==
'\0' ||
211 !strcmp(argv[2],
"-X") ||
212 !strcmp(argv[2],
"-I"))) {
217 certNames[certCount++] = argv[2];
218 if (strlen(argv[1]) > 2 &&
219 (!strcmp(argv[2],
"-X") || !strcmp(argv[2],
"-I")) &&
220 argv[1][2] >=
'0' && argv[1][2] <=
'9') {
221 sigIndex = argv[1][2] -
'0';
229 }
else if (argv[1][0] ==
'-' && argv[1][1] ==
'H') {
230 MARChannelID = argv[2];
234 }
else if (argv[1][0] ==
'-' && argv[1][1] ==
'V') {
235 productVersion = argv[2];
245 if (argv[1][0] !=
'-') {
250 switch (argv[1][1]) {
255 if (argv[argc - 2][0] ==
'-' && argv[argc - 2][1] ==
'f')
262 files = (
char **)malloc(
sizeof(
char*)*10000);
264 file = fopen(argv[argc - 1],
"r");
267 printf(
"%d %s", errno, strerror(errno));
268 printf(
"Could not open file: %s", argv[argc - 1]);
272 while(fgets(buf, 1000, file) !=
NULL)
276 for (j=strlen(buf)-1;j>=0 && (buf[j]==
'\n' || buf[j]==
'\r');j--)
279 str_len = strlen(buf) + 1;
280 files[num_files] = (
char*)malloc(
sizeof(
char)*str_len);
281 strcpy(files[num_files], buf);
285 return mar_create(argv[2], num_files, files, &infoBlock);
288 return mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
298 uint32_t numSignatures, numAdditionalBlocks;
299 int hasSignatureBlock, hasAdditionalBlock;
304 NULL, &numAdditionalBlocks)) {
305 if (hasSignatureBlock) {
306 printf(
"Signature block found with %d signature%s\n",
308 numSignatures != 1 ?
"s" :
"");
310 if (hasAdditionalBlock) {
311 printf(
"%d additional block%s found:\n",
313 numAdditionalBlocks != 1 ?
"s" :
"");
318 printf(
" - Product Information Block:\n");
319 printf(
" - MAR channel name: %s\n"
320 " - Product version: %s\n",
338#ifndef NO_SIGN_VERIFY
341 if (sigIndex == -1) {
342 fprintf(stderr,
"ERROR: Signature index was not passed.\n");
346 fprintf(stderr,
"ERROR: Signature index is out of range: %d.\n",
354 if (sigIndex == -1) {
355 fprintf(stderr,
"ERROR: signature index was not passed.\n");
359 fprintf(stderr,
"ERROR: Signature index is out of range: %d.\n",
370 if (certCount == 0) {
375#if (!defined(_WIN32) && !defined(MACOSX)) || defined(MAR_NSS)
376 if (!NSSConfigDir || certCount == 0) {
382 fprintf(stderr,
"ERROR: Could not initialize crypto library.\n");
388 for (k = 0; k < certCount; ++k) {
389#if (defined(_WIN32) || defined(MACOSX)) && !defined(MAR_NSS)
391 &certBuffers[k], &fileSizes[k]);
401 certs[k] = PK11_FindCertFromNickname(certNames[k],
NULL);
403 certBuffers[k] = certs[k]->derCert.data;
404 fileSizes[k] = certs[k]->derCert.len;
410 fprintf(stderr,
"ERROR: could not read file %s", DERFilePaths[k]);
421 fprintf(stderr,
"ERROR: Could not open MAR file.\n");
425 for (k = 0; k < certCount; ++k) {
426#if (defined(_WIN32) || defined(MACOSX)) && !defined(MAR_NSS)
427 free((
void*)certBuffers[k]);
430 CERT_DestroyCertificate(certs[k]);
435 int hasSignatureBlock;
438 fprintf(stderr,
"ERROR: could not determine if MAR is old or new.\n");
439 }
else if (!hasSignatureBlock) {
440 fprintf(stderr,
"ERROR: The MAR file is in the old format so has"
441 " no signature to verify.\n");
448 if (!NSSConfigDir || certCount == 0 || argc < 4) {
static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused)
static void print_usage(void)
int NSSInitCryptoContext(const char *NSSConfigDir)
Initializes the NSS context.
static void print_version(void)
int main(int argc, char **argv)
int mar_repackage_and_sign(const char *NSSConfigDir, const char *const *certNames, uint32_t certCount, const char *src, const char *dest)
Writes out a copy of the MAR at src but with embedded signatures.
static int mar_test(const char *path)
#define MAR_MAX_CERT_SIZE
int refresh_product_info_block(const char *path, struct ProductInformationBlock *infoBlock)
Refreshes the product information block with the new information.
int mar_create(const char *dest, int num_files, char **files, struct ProductInformationBlock *infoBlock)
Create a MAR file from a set of files.
int get_mar_file_info(const char *path, int *hasSignatureBlock, uint32_t *numSignatures, int *hasAdditionalBlocks, uint32_t *offsetAdditionalBlocks, uint32_t *numAdditionalBlocks)
Determines the MAR file information.
void mar_close(MarFile *mar)
Close a MAR file that was opened using mar_open.
int mar_enum_items(MarFile *mar, MarItemCallback callback, void *closure)
Enumerate all MAR items via callback function.
MarFile * mar_open(const char *path)
Open a MAR file for reading.
int read_product_info_block(char *path, struct ProductInformationBlock *infoBlock)
Reads the product info block from the MAR file's additional block section.
int import_signature(const char *src, uint32_t sigIndex, const char *base64SigFile, const char *dest)
Imports a base64 encoded signature into a MAR file.
int extract_signature(const char *src, uint32_t sigIndex, const char *dest)
Extracts a signature from a MAR file, base64 encodes it, and writes it out.
int strip_signature_block(const char *src, const char *dest)
Writes out a copy of the MAR at src but with the signature block stripped.
int mar_read_entire_file(const char *filePath, uint32_t maxSize, const uint8_t **data, uint32_t *size)
int mar_verify_signatures(MarFile *mar, const uint8_t *const *certData, const uint32_t *certDataSizes, uint32_t certCount)
Verifies a MAR file by verifying each signature with the corresponding certificate.
The MAR item data structure.