2 Copyright (C) 2015-2020 IoT.bzh
4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
30 #include <libxml/tree.h>
33 #include "wgtpkg-files.h"
34 #include "wgtpkg-workdir.h"
35 #include "wgtpkg-digsig.h"
36 #include "wgtpkg-xmlsec.h"
41 #if !defined(DEFAULT_KEY_FILE)
42 #define DEFAULT_KEY_FILE "key.pem"
44 #if !defined(DEFAULT_CERT_FILE)
45 #define DEFAULT_CERT_FILE "cert.pem"
48 const char appname[] = "wgtpkg-sign";
50 static unsigned int get_number(const char *value)
53 unsigned long int val;
55 val = strtoul(value, &end, 10);
56 if (*end || 0 == val || val >= UINT_MAX || *value == '-') {
57 ERROR("bad number value %s", value);
60 return (unsigned int)val;
63 static void make_realpath(char **x)
65 char *p = realpath(*x, NULL);
67 ERROR("realpath failed for %s", *x);
77 " %s version="AFM_VERSION"\n"
79 " Copyright (C) 2015-2020 \"IoT.bzh\"\n"
80 " AFB comes with ABSOLUTELY NO WARRANTY.\n"
90 "usage: %s [-f] [-k keyfile] [-c certfile]... [-d number | -a] directory\n"
92 " -k keyfile the private key to use for author signing\n"
93 " -c certfile the certificate(s) to use for author signing\n"
94 " -d number the number of the distributor signature (zero for automatic)\n"
95 " -a the author signature\n"
96 " -f force overwriting\n"
105 static struct option options_l[] = {
106 { "author", no_argument, NULL, 'a' },
107 { "certificate", required_argument, NULL, 'c' },
108 { "distributor", required_argument, NULL, 'd' },
109 { "force", no_argument, NULL, 'f' },
110 { "help", no_argument, NULL, 'h' },
111 { "key", required_argument, NULL, 'k' },
112 { "quiet", no_argument, NULL, 'q' },
113 { "verbose", no_argument, NULL, 'v' },
114 { "version", no_argument, NULL, 'V' },
118 static const char options_s[] = "ac:d:fhk:qvV";
120 /* install the widgets of the list */
121 int main(int ac, char **av)
123 int i, force, ncert, author;
125 char *keyfile, *certfiles[MAXCERT+1], *directory;
130 force = ncert = author = 0;
132 keyfile = directory = NULL;
134 i = getopt_long(ac, av, options_s, options_l, NULL);
139 if (ncert == MAXCERT) {
140 ERROR("maximum count of certificates reached");
143 certfiles[ncert++] = optarg;
147 ERROR("key already set");
153 if (number != UINT_MAX) {
154 ERROR("number already set");
157 number = get_number(optarg);
179 ERROR("missing argument");
182 ERROR("unrecognized option");
187 /* remaining arguments and final checks */
189 ERROR("no directory set");
192 directory = av[optind++];
194 ERROR("extra parameters found");
198 /* set default values */
200 keyfile = DEFAULT_KEY_FILE;
202 certfiles[ncert++] = DEFAULT_CERT_FILE;
205 if (stat(directory, &s)) {
206 ERROR("can't find directory %s", directory);
209 if (!S_ISDIR(s.st_mode)) {
210 ERROR("%s isn't a directory", directory);
213 if (access(keyfile, R_OK) != 0) {
214 ERROR("can't access private key %s", keyfile);
217 for(i = 0 ; i < ncert ; i++)
218 if (access(certfiles[i], R_OK) != 0) {
219 ERROR("can't access certificate %s", certfiles[i]);
223 /* init xmlsec module */
227 /* compute absolutes paths */
228 make_realpath(&keyfile);
229 for(i = 0 ; i < ncert ; i++)
230 make_realpath(&certfiles[i]);
232 /* set and enter the workdir */
233 if (set_workdir(directory, 0))
241 else if (number == UINT_MAX)
242 for (number = 1; get_signature(number) != NULL ; number++);
244 if (!force && get_signature(number) != NULL) {
245 ERROR("can't overwrite existing signature %s", get_signature(number)->name);
249 NOTICE("-- SIGNING content of directory %s for number %u", directory, number);
251 certfiles[ncert] = NULL;
252 return !!create_digsig(number, keyfile, (const char**)certfiles);