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_for(const char *attrname, const char *value)
73 xmlNodePtr iter, next;
77 iter = xmlDocGetRootElement(document);
78 while (iter != NULL) {
79 val = xmlGetProp(iter, attrname);
80 if (val != NULL && !strcmp(val, value)) {
82 syslog(LOG_ERR, "duplicated %s %s", attrname, value);
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 %s '%s' not found", attrname, value);
108 /* search the element node of id. NOTE : not optimized at all */
109 static xmlNodePtr search_id(const char *id)
111 return search_for("Id", id);
115 /* check the digest of one element */
116 static int check_one_reference(xmlNodePtr ref)
121 struct filedesc *fdesc;
127 uri = xmlGetProp(ref, "URI");
129 syslog(LOG_ERR, "attribute URI of element <Reference> not found");
134 u = xmlParseURI(uri);
136 syslog(LOG_ERR, "error while parsing URI %s", uri);
140 if (u->scheme || u->opaque || u->authority || u->server || u->user || u->query) {
141 syslog(LOG_ERR, "unexpected uri component in %s", uri);
145 if (u->path && u->fragment) {
146 syslog(LOG_ERR, "not allowed to sign foreign fragment in %s", uri);
151 fdesc = file_of_name(u->path);
153 syslog(LOG_ERR, "reference to unknown file %s", u->path);
156 if (fdesc->type != type_file) {
157 syslog(LOG_ERR, "reference to directory %s", u->path);
160 if ((fdesc->flags & flag_distributor_signature) != 0) {
161 syslog(LOG_ERR, "reference to signature %s", u->path);
164 fdesc->flags |= flag_referenced;
178 static int check_references(xmlNodePtr sinfo)
182 elem = sinfo->children;
183 while (elem != NULL) {
184 if (is_element(elem, "Reference"))
185 if (check_one_reference(elem))
192 static int get_certificates(xmlNodePtr kinfo)
198 n1 = kinfo->children;
200 if (is_element(n1, "X509Data")) {
203 if (is_element(n2, "X509Certificate")) {
204 b = xmlNodeGetContent(n2);
206 syslog(LOG_ERR, "xmlNodeGetContent of X509Certificate failed");
209 rc = add_certificate_b64(b);
222 static int checkdocument()
225 xmlNodePtr sinfo, svalue, kinfo, objs, rootsig;
229 rootsig = xmlDocGetRootElement(document);
230 if (!is_node(rootsig, "Signature")) {
231 syslog(LOG_ERR, "root element <Signature> not found");
235 sinfo = next_element(rootsig->children);
236 if (!is_node(sinfo, "SignedInfo")) {
237 syslog(LOG_ERR, "element <SignedInfo> not found");
241 svalue = next_element(sinfo->next);
242 if (!is_node(svalue, "SignatureValue")) {
243 syslog(LOG_ERR, "element <SignatureValue> not found");
247 kinfo = next_element(svalue->next);
248 if (is_node(kinfo, "KeyInfo")) {
255 rc = check_references(sinfo);
259 rc = xmlsec_verify(rootsig);
263 rc = get_certificates(kinfo);
269 int verify_digsig(struct filedesc *fdesc)
273 assert ((fdesc->flags & flag_signature) != 0);
274 printf("\n\nchecking file %s\n\n",fdesc->name);
276 /* reset the flags */
278 clear_certificates();
280 /* reads and xml parses the signature file */
281 document = xmlReadFile(fdesc->name, NULL, 0);
282 if (document == NULL) {
283 syslog(LOG_ERR, "xml parse of file %s failed", fdesc->name);
287 res = checkdocument();
289 syslog(LOG_ERR, "previous error was during check of file %s", fdesc->name);
291 xmlFreeDoc(document);
295 int check_all_signatures()
299 struct filedesc *fdesc;
301 n = signature_count();
303 for (i = n ; i-- > 0 ; ) {
304 fdesc = signature_of_index(i);
305 assert ((fdesc->flags & flag_signature) != 0);
306 irc = verify_digsig(fdesc);
314 int create_digsig(int index, const char *key, const char **certs)
316 struct filedesc *fdesc;
321 doc = xmlsec_create(index, key, certs);
325 fdesc = create_signature(index);
329 len = xmlSaveFormatFileEnc(fdesc->name, doc, NULL, 0);
331 syslog(LOG_ERR, "xmlSaveFormatFileEnc to %s failed", fdesc->name);