4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
22 #include <libxml/parser.h>
23 #include <libxml/tree.h>
24 #include <libxml/uri.h>
31 static const char uri_role_author[] = "http://www.w3.org/ns/widgets-digsig#role-author";
32 static const char uri_role_distributor[] = "http://www.w3.org/ns/widgets-digsig#role-distributor";
33 static const char uri_profile[] = "http://www.w3.org/ns/widgets-digsig#profile";
37 static xmlDocPtr document; /* the document */
39 /* facility to get the first element node (skip text nodes) starting with 'node' */
40 static xmlNodePtr next_element(xmlNodePtr node)
42 while (node && node->type != XML_ELEMENT_NODE)
47 /* is the 'node' an element node of 'name'? */
48 static int is_element(xmlNodePtr node, const char *name)
50 return node->type == XML_ELEMENT_NODE
51 && !strcmp(name, node->name);
54 /* is the 'node' an element node of 'name'? */
55 static int is_node(xmlNodePtr node, const char *name)
57 return node != NULL && is_element(node, name);
61 /* facility to get the first element node (skip text nodes) starting with 'node' */
62 static xmlNodePtr next_element_type(xmlNodePtr node, const char *name)
64 while (node && node->type != XML_ELEMENT_NODE && strcmp(name, node->name))
69 /* search the element node of id. NOTE : not optimized at all */
70 static xmlNodePtr search_id(const char *id)
73 xmlNodePtr iter, next;
77 iter = xmlDocGetRootElement(document);
78 while (iter != NULL) {
79 val = xmlGetProp(iter, "Id");
80 if (val != NULL && !strcmp(val, id)) {
82 syslog(LOG_ERR, "duplicated Id %s", id);
89 next = next_element(iter->children);
91 /* no child, try sibling */
92 next = next_element(iter->next);
95 while (iter != NULL && next == NULL) {
96 next = next_element(iter->next);
104 syslog(LOG_ERR, "node of Id '%s' not found", id);
109 /* check the digest of one element */
110 static int check_one_reference(xmlNodePtr ref)
115 struct filedesc *fdesc;
121 uri = xmlGetProp(ref, "URI");
123 syslog(LOG_ERR, "attribute URI of element <Reference> not found");
128 u = xmlParseURI(uri);
130 syslog(LOG_ERR, "error while parsing URI %s", uri);
134 if (u->scheme || u->opaque || u->authority || u->server || u->user || u->query) {
135 syslog(LOG_ERR, "unexpected uri component in %s", uri);
139 if (u->path && u->fragment) {
140 syslog(LOG_ERR, "not allowed to sign foreign fragment in %s", uri);
145 fdesc = file_of_name(u->path);
147 syslog(LOG_ERR, "reference to unknown file %s", u->path);
150 if (fdesc->type != type_file) {
151 syslog(LOG_ERR, "reference to directory %s", u->path);
154 if ((fdesc->flags & flag_distributor_signature) != 0) {
155 syslog(LOG_ERR, "reference to signature %s", u->path);
158 fdesc->flags |= flag_referenced;
172 static int check_references(xmlNodePtr sinfo)
176 elem = sinfo->children;
177 while (elem != NULL) {
178 if (is_element(elem, "Reference"))
179 if (check_one_reference(elem))
186 static int get_certificates(xmlNodePtr kinfo)
192 n1 = kinfo->children;
194 if (is_element(n1, "X509Data")) {
197 if (is_element(n2, "X509Certificate")) {
198 b = xmlNodeGetContent(n2);
200 syslog(LOG_ERR, "xmlNodeGetContent of X509Certificate failed");
203 rc = add_certificate_b64(b);
216 static int checkdocument()
219 xmlNodePtr sinfo, svalue, kinfo, objs, rootsig;
223 rootsig = xmlDocGetRootElement(document);
224 if (!is_node(rootsig, "Signature")) {
225 syslog(LOG_ERR, "root element <Signature> not found");
229 sinfo = next_element(rootsig->children);
230 if (!is_node(sinfo, "SignedInfo")) {
231 syslog(LOG_ERR, "element <SignedInfo> not found");
235 svalue = next_element(sinfo->next);
236 if (!is_node(svalue, "SignatureValue")) {
237 syslog(LOG_ERR, "element <SignatureValue> not found");
241 kinfo = next_element(svalue->next);
242 if (is_node(kinfo, "KeyInfo")) {
249 rc = check_references(sinfo);
253 rc = xmlsec_verify(rootsig);
257 rc = get_certificates(kinfo);
263 int verify_digsig(struct filedesc *fdesc)
267 assert ((fdesc->flags & flag_signature) != 0);
268 printf("\n\nchecking file %s\n\n",fdesc->name);
270 /* reset the flags */
272 clear_certificates();
274 /* reads and xml parses the signature file */
275 document = xmlReadFile(fdesc->name, NULL, 0);
276 if (document == NULL) {
277 syslog(LOG_ERR, "xml parse of file %s failed", fdesc->name);
281 res = checkdocument();
283 syslog(LOG_ERR, "previous error was during check of file %s", fdesc->name);
285 xmlFreeDoc(document);
289 int check_all_signatures()
293 struct filedesc *fdesc;
295 n = signature_count();
297 for (i = n ; i-- > 0 ; ) {
298 fdesc = signature_of_index(i);
299 assert ((fdesc->flags & flag_signature) != 0);
300 irc = verify_digsig(fdesc);
308 int create_digsig(int index, const char *key, const char **certs)
310 struct filedesc *fdesc;
315 doc = xmlsec_create(index, key, certs);
319 fdesc = create_signature(index);
323 len = xmlSaveFormatFileEnc(fdesc->name, doc, NULL, 0);
325 syslog(LOG_ERR, "xmlSaveFormatFileEnc to %s failed", fdesc->name);