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;
67 " %s version="AFM_VERSION"\n"
69 " Copyright (C) 2015, 2016, 2017 \"IoT.bzh\"\n"
70 " AFB comes with ABSOLUTELY NO WARRANTY.\n"
80 "usage: %s [-f] [-k keyfile] [-c certfile]... [-d number | -a] directory\n"
82 " -k keyfile the private key to use for author signing\n"
83 " -c certfile the certificate(s) to use for author signing\n"
84 " -d number the number of the distributor signature (zero for automatic)\n"
85 " -a the author signature\n"
86 " -f force overwriting\n"
95 static struct option options[] = {
96 { "key", required_argument, NULL, 'k' },
97 { "certificate", required_argument, NULL, 'c' },
98 { "distributor", required_argument, NULL, 'd' },
99 { "author", no_argument, NULL, 'a' },
100 { "force", no_argument, NULL, 'f' },
101 { "help", no_argument, NULL, 'h' },
102 { "quiet", no_argument, NULL, 'q' },
103 { "verbose", no_argument, NULL, 'v' },
104 { "version", no_argument, NULL, 'V' },
108 /* install the widgets of the list */
109 int main(int ac, char **av)
111 int i, force, ncert, author;
113 char *keyfile, *certfiles[MAXCERT+1], *directory, **x;
118 force = ncert = author = 0;
120 keyfile = directory = NULL;
122 i = getopt_long(ac, av, "hfqvVak:c:d:", options, NULL);
127 if (ncert == MAXCERT) {
128 ERROR("maximum count of certificates reached");
131 certfiles[ncert++] = optarg;
133 case 'k': x = &keyfile; break;
134 case 'd': number = get_number(optarg); continue;
135 case 'f': force = 1; continue;
136 case 'a': author = 1; continue;
137 case 'h': usage(); return 0;
138 case 'V': version(); return 0;
147 ERROR("missing argument");
150 ERROR("unrecognized option");
154 ERROR("option set twice");
160 /* remaining arguments and final checks */
162 ERROR("no directory set");
165 directory = av[optind++];
167 ERROR("extra parameters found");
171 /* set default values */
173 keyfile = DEFAULT_KEY_FILE;
175 certfiles[ncert++] = DEFAULT_CERT_FILE;
178 if (stat(directory, &s)) {
179 ERROR("can't find directory %s", directory);
182 if (!S_ISDIR(s.st_mode)) {
183 ERROR("%s isn't a directory", directory);
186 if (access(keyfile, R_OK) != 0) {
187 ERROR("can't access private key %s", keyfile);
190 for(i = 0 ; i < ncert ; i++)
191 if (access(certfiles[i], R_OK) != 0) {
192 ERROR("can't access certificate %s", certfiles[i]);
196 /* init xmlsec module */
201 /* compute absolutes paths */
202 #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)
204 for(i = 0 ; i < ncert ; i++)
208 /* set and enter the workdir */
209 if (set_workdir(directory, 0))
217 else if (number == UINT_MAX)
218 for (number = 1; get_signature(number) != NULL ; number++);
220 if (!force && get_signature(number) != NULL) {
221 ERROR("can't overwrite existing signature %s", get_signature(number)->name);
225 NOTICE("-- SIGNING content of directory %s for number %u", directory, number);
227 certfiles[ncert] = NULL;
228 return !!create_digsig(number, keyfile, (const char**)certfiles);