X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-digsig.c;h=d190d23258307ea70dbd463881c7c547f11a2d62;hb=7ea1070ee471141f58e9e4c03df5c95bbcef907d;hp=6e66e38b6de25b5e0b6ae634c3109462a7a67335;hpb=f3d64b7c741677cd28e2a11deed67196cd02b46a;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-digsig.c b/src/wgtpkg-digsig.c index 6e66e38..d190d23 100644 --- a/src/wgtpkg-digsig.c +++ b/src/wgtpkg-digsig.c @@ -1,5 +1,7 @@ /* - Copyright 2015 IoT.bzh + Copyright (C) 2015-2020 IoT.bzh + + author: José Bollo Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,16 +18,22 @@ #include -#include #include +#include +#include #include #include #include +#include #include "verbose.h" -#include "wgtpkg.h" +#include "wgtpkg-files.h" +#include "wgtpkg-workdir.h" +#include "wgtpkg-certs.h" +#include "wgtpkg-xmlsec.h" +#include "wgtpkg-digsig.h" @@ -80,7 +88,7 @@ static xmlNodePtr search_for(const char *attrname, const char *value) val = xmlGetProp(iter, attrname); if (val != NULL && !strcmp(val, value)) { if (result != NULL) { - syslog(LOG_ERR, "duplicated %s %s", attrname, value); + ERROR("duplicated %s %s", attrname, value); free(val); return NULL; } @@ -102,7 +110,7 @@ static xmlNodePtr search_for(const char *attrname, const char *value) iter = next; } if (result == NULL) - syslog(LOG_ERR, "node of %s '%s' not found", attrname, value); + ERROR("node of %s '%s' not found", attrname, value); return result; } @@ -127,30 +135,30 @@ static int check_one_reference(xmlNodePtr ref) /* get the uri */ uri = xmlGetProp(ref, "URI"); if (uri == NULL) { - syslog(LOG_ERR, "attribute URI of element not found"); + ERROR("attribute URI of element not found"); goto error; } /* parse the uri */ u = xmlParseURI(uri); if (!u) { - syslog(LOG_ERR, "error while parsing URI %s", uri); + ERROR("error while parsing URI %s", uri); goto error2; } /* check that unexpected parts are not there */ if (u->scheme || u->opaque || u->authority || u->server || u->user || u->query) { - syslog(LOG_ERR, "unexpected uri component in %s", uri); + ERROR("unexpected uri component in %s", uri); goto error3; } /* check path and fragment */ if (!u->path && !u->fragment) { - syslog(LOG_ERR, "invalid uri %s", uri); + ERROR("invalid uri %s", uri); goto error3; } if (u->path && u->fragment) { - syslog(LOG_ERR, "not allowed to sign foreign fragment in %s", uri); + ERROR("not allowed to sign foreign fragment in %s", uri); goto error3; } @@ -158,15 +166,15 @@ static int check_one_reference(xmlNodePtr ref) /* check that the path is valid */ fdesc = file_of_name(u->path); if (fdesc == NULL) { - syslog(LOG_ERR, "reference to unknown file %s", u->path); + ERROR("reference to unknown file %s", u->path); goto error3; } if (fdesc->type != type_file) { - syslog(LOG_ERR, "reference to directory %s", u->path); + ERROR("reference to directory %s", u->path); goto error3; } if ((fdesc->flags & flag_distributor_signature) != 0) { - syslog(LOG_ERR, "reference to signature %s", u->path); + ERROR("reference to signature %s", u->path); goto error3; } fdesc->flags |= flag_referenced; @@ -185,18 +193,37 @@ error: static int check_references(xmlNodePtr sinfo) { + unsigned int i, n, flags; + struct filedesc *f; + int result; xmlNodePtr elem; + result = 0; elem = sinfo->children; while (elem != NULL) { if (is_element(elem, "Reference")) if (check_one_reference(elem)) - return -1; + result = -1; elem = elem->next; } - return 0; + + n = file_count(); + i = 0; + while(i < n) { + f = file_of_index(i++); + if (f->type == type_file) { + flags = f->flags; + if (!(flags & (flag_signature | flag_referenced))) { + ERROR("file not referenced in signature: %s", f->name); + result = -1; + } + } + } + + return result; } + static int get_certificates(xmlNodePtr kinfo) { xmlNodePtr n1, n2; @@ -211,7 +238,7 @@ static int get_certificates(xmlNodePtr kinfo) if (is_element(n2, "X509Certificate")) { b = xmlNodeGetContent(n2); if (b == NULL) { - syslog(LOG_ERR, "xmlNodeGetContent of X509Certificate failed"); + ERROR("xmlNodeGetContent of X509Certificate failed"); return -1; } rc = add_certificate_b64(b); @@ -237,19 +264,19 @@ static int checkdocument() rootsig = xmlDocGetRootElement(document); if (!is_node(rootsig, "Signature")) { - syslog(LOG_ERR, "root element not found"); + ERROR("root element not found"); goto error; } sinfo = next_element(rootsig->children); if (!is_node(sinfo, "SignedInfo")) { - syslog(LOG_ERR, "element not found"); + ERROR("element not found"); goto error; } svalue = next_element(sinfo->next); if (!is_node(svalue, "SignatureValue")) { - syslog(LOG_ERR, "element not found"); + ERROR("element not found"); goto error; } @@ -278,43 +305,63 @@ error: /* verify the digital signature of the file described by 'fdesc' */ int verify_digsig(struct filedesc *fdesc) { - int res; + int res, fd; assert ((fdesc->flags & flag_signature) != 0); - debug("-- checking file %s",fdesc->name); + DEBUG("-- checking file %s", fdesc->name); /* reset the flags */ file_clear_flags(); clear_certificates(); /* reads and xml parses the signature file */ - document = xmlReadFile(fdesc->name, NULL, 0); + fd = openat(workdirfd, fdesc->name, O_RDONLY); + if (fd < 0) { + ERROR("cant't open file %s", fdesc->name); + return -1; + } + document = xmlReadFd(fd, fdesc->name, NULL, 0); + close(fd); if (document == NULL) { - syslog(LOG_ERR, "xml parse of file %s failed", fdesc->name); + ERROR("xml parse of file %s failed", fdesc->name); return -1; } res = checkdocument(); if (res) - syslog(LOG_ERR, "previous error was during check of file %s", fdesc->name); + ERROR("previous error was during check of file %s", fdesc->name); xmlFreeDoc(document); return res; } /* check all the signature files */ -int check_all_signatures() +int check_all_signatures(int allow_none) { int rc, irc; unsigned int i, n; struct filedesc *fdesc; n = signature_count(); + if (n == 0) { + if (!allow_none) { + ERROR("no signature found"); + return -1; + } + return 0; + } + + rc = xmlsec_init(); + if (rc < 0) { + ERROR("can't check signature"); + return rc; + } + rc = 0; - for (i = n ; i-- > 0 ; ) { - fdesc = signature_of_index(i); + for (i = n ; i ; ) { + fdesc = signature_of_index(--i); irc = verify_digsig(fdesc); - if (!irc) + if (irc < 0) rc = irc; } @@ -324,11 +371,13 @@ int check_all_signatures() /* create a signature of 'index' (0 for author, other values for distributors) using the private 'key' (filename) and the certificates 'certs' (filenames) as trusted chain */ -int create_digsig(int index, const char *key, const char **certs) +int create_digsig(unsigned int index, const char *key, const char **certs) { struct filedesc *fdesc; xmlDocPtr doc; - int rc, len; + int rc, fd; + long len; + xmlSaveCtxtPtr ctx; rc = -1; @@ -343,13 +392,27 @@ int create_digsig(int index, const char *key, const char **certs) goto error2; /* save the doc as file */ - len = xmlSaveFormatFileEnc(fdesc->name, doc, NULL, 0); - if (len < 0) { - syslog(LOG_ERR, "xmlSaveFormatFileEnc to %s failed", fdesc->name); + fd = openat(workdirfd, fdesc->name, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0) { + ERROR("cant open %s for write", fdesc->name); goto error2; } + ctx = xmlSaveToFd(fd, NULL, XML_SAVE_FORMAT); + if (!ctx) { + ERROR("xmlSaveToFd failed for %s", fdesc->name); + goto error3; + } + len = xmlSaveDoc(ctx, doc); + if (len < 0) { + ERROR("xmlSaveDoc to %s failed", fdesc->name); + goto error4; + } rc = 0; +error4: + xmlSaveClose(ctx); +error3: + close(fd); error2: xmlFreeDoc(doc); error: