2 Copyright 2015, 2016, 2017 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;
66 "usage: %s [-f] [-k keyfile] [-c certfile]... [-d number | -a] directory\n"
68 " -k keyfile the private key to use for author signing\n"
69 " -c certfile the certificate(s) to use for author signing\n"
70 " -d number the number of the distributor signature (zero for automatic)\n"
71 " -a the author signature\n"
72 " -f force overwriting\n"
80 static struct option options[] = {
81 { "key", required_argument, NULL, 'k' },
82 { "certificate", required_argument, NULL, 'c' },
83 { "distributor", required_argument, NULL, 'd' },
84 { "author", no_argument, NULL, 'a' },
85 { "force", no_argument, NULL, 'f' },
86 { "help", no_argument, NULL, 'h' },
87 { "quiet", no_argument, NULL, 'q' },
88 { "verbose", no_argument, NULL, 'v' },
92 /* install the widgets of the list */
93 int main(int ac, char **av)
95 int i, force, ncert, author;
97 char *keyfile, *certfiles[MAXCERT+1], *directory, **x;
102 force = ncert = author = 0;
104 keyfile = directory = NULL;
106 i = getopt_long(ac, av, "hfqvak:c:d:", options, NULL);
111 if (ncert == MAXCERT) {
112 ERROR("maximum count of certificates reached");
115 certfiles[ncert++] = optarg;
117 case 'k': x = &keyfile; break;
118 case 'd': number = get_number(optarg); continue;
119 case 'f': force = 1; continue;
120 case 'a': author = 1; continue;
121 case 'h': usage(); return 0;
130 ERROR("missing argument");
133 ERROR("unrecognized option");
137 ERROR("option set twice");
143 /* remaining arguments and final checks */
145 ERROR("no directory set");
148 directory = av[optind++];
150 ERROR("extra parameters found");
154 /* set default values */
156 keyfile = DEFAULT_KEY_FILE;
158 certfiles[ncert++] = DEFAULT_CERT_FILE;
161 if (stat(directory, &s)) {
162 ERROR("can't find directory %s", directory);
165 if (!S_ISDIR(s.st_mode)) {
166 ERROR("%s isn't a directory", directory);
169 if (access(keyfile, R_OK) != 0) {
170 ERROR("can't access private key %s", keyfile);
173 for(i = 0 ; i < ncert ; i++)
174 if (access(certfiles[i], R_OK) != 0) {
175 ERROR("can't access certificate %s", certfiles[i]);
179 /* init xmlsec module */
184 /* compute absolutes paths */
185 #define rp(x) do { char *p = realpath(x, NULL); if (p != NULL) x = p; else { ERROR("realpath failed for %s",x); return 1; } } while(0)
187 for(i = 0 ; i < ncert ; i++)
191 /* set and enter the workdir */
192 if (set_workdir(directory, 0))
200 else if (number == UINT_MAX)
201 for (number = 1; get_signature(number) != NULL ; number++);
203 if (!force && get_signature(number) != NULL) {
204 ERROR("can't overwrite existing signature %s", get_signature(number)->name);
208 NOTICE("-- SIGNING content of directory %s for number %u", directory, number);
210 certfiles[ncert] = NULL;
211 return !!create_digsig(number, keyfile, (const char**)certfiles);