• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/libubox/tests/test-blob-parse.c

  1 /*
  2  * Based on certificate dump functionality from ucert.c:
  3  *
  4  *  Copyright (C) 2018 Daniel Golle <daniel@makrotopia.org>
  5  *  SPDX-License-Identifier: GPL-3.0
  6  *
  7  */
  8 
  9 #include <stdio.h>
 10 #include <stdint.h>
 11 #include <stddef.h>
 12 #include <libgen.h>
 13 
 14 #include "blob.h"
 15 #include "list.h"
 16 #include "blobmsg_json.h"
 17 
 18 #define CERT_BUF_LEN 4096
 19 
 20 /*
 21  * ucert structure
 22  * |               BLOB                    |
 23  * |    SIGNATURE    |       PAYLOAD       |
 24  * |                 |[ BLOBMSG CONTAINER ]|
 25  * |                 |[[T,i,v,e,f,pubkey ]]|
 26  */
 27 enum cert_attr {
 28         CERT_ATTR_SIGNATURE,
 29         CERT_ATTR_PAYLOAD,
 30         CERT_ATTR_MAX
 31 };
 32 
 33 static const struct blob_attr_info cert_policy[CERT_ATTR_MAX] = {
 34         [CERT_ATTR_SIGNATURE] = { .type = BLOB_ATTR_BINARY },
 35         [CERT_ATTR_PAYLOAD] = { .type = BLOB_ATTR_NESTED },
 36 };
 37 
 38 enum cert_cont_attr {
 39         CERT_CT_ATTR_PAYLOAD,
 40         CERT_CT_ATTR_MAX
 41 };
 42 
 43 enum cert_payload_attr {
 44         CERT_PL_ATTR_CERTTYPE,
 45         CERT_PL_ATTR_CERTID,
 46         CERT_PL_ATTR_VALIDFROMTIME,
 47         CERT_PL_ATTR_EXPIRETIME,
 48         CERT_PL_ATTR_PUBKEY,
 49         CERT_PL_ATTR_KEY_FINGERPRINT,
 50         CERT_PL_ATTR_MAX
 51 };
 52 
 53 enum certtype_id {
 54         CERTTYPE_UNSPEC,
 55         CERTTYPE_AUTH,
 56         CERTTYPE_REVOKE
 57 };
 58 
 59 /* list to store certificate chain at runtime */
 60 struct cert_object {
 61         struct list_head list;
 62         struct blob_attr *cert[CERT_ATTR_MAX];
 63 };
 64 
 65 static int cert_load(const char *certfile, struct list_head *chain)
 66 {
 67         FILE *f;
 68         struct blob_attr *certtb[CERT_ATTR_MAX];
 69         struct blob_attr *bufpt;
 70         struct cert_object *cobj;
 71         char *filebuf = NULL;
 72         int ret = 0, pret = 0;
 73         size_t len, pos = 0;
 74 
 75         f = fopen(certfile, "r");
 76         if (!f)
 77                 return 1;
 78 
 79         filebuf = malloc(CERT_BUF_LEN+1);
 80         if (!filebuf)
 81                 return 1;
 82 
 83         len = fread(filebuf, 1, CERT_BUF_LEN, f);
 84         if (len < 64) {
 85                 free(filebuf);
 86                 return 1;
 87         }
 88 
 89         ret = ferror(f) || !feof(f);
 90         fclose(f);
 91         if (ret) {
 92                 free(filebuf);
 93                 return 1;
 94         }
 95 
 96         bufpt = (struct blob_attr *)filebuf;
 97         do {
 98                 pret = blob_parse_untrusted(bufpt, len, certtb, cert_policy, CERT_ATTR_MAX);
 99                 if (pret <= 0)
100                         /* no attributes found */
101                         break;
102 
103                 if (pos + blob_pad_len(bufpt) > len)
104                         /* blob exceeds filebuffer */
105                         break;
106                 else
107                         pos += blob_pad_len(bufpt);
108 
109                 if (!certtb[CERT_ATTR_SIGNATURE])
110                         /* no signature -> drop */
111                         break;
112 
113                 cobj = calloc(1, sizeof(*cobj));
114                 cobj->cert[CERT_ATTR_SIGNATURE] = blob_memdup(certtb[CERT_ATTR_SIGNATURE]);
115                 if (certtb[CERT_ATTR_PAYLOAD])
116                         cobj->cert[CERT_ATTR_PAYLOAD] = blob_memdup(certtb[CERT_ATTR_PAYLOAD]);
117 
118                 list_add_tail(&cobj->list, chain);
119                 ret += pret;
120         /* repeat parsing while there is still enough remaining data in buffer */
121         } while(len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt)));
122 
123         free(filebuf);
124         return (ret <= 0);
125 }
126 
127 /* dump single chain element to console */
128 static void cert_dump_blob(struct blob_attr *cert[CERT_ATTR_MAX])
129 {
130         int i;
131         char *json = NULL;
132 
133         for (i = 0; i < CERT_ATTR_MAX; i++) {
134                 struct blob_attr *v = cert[i];
135 
136                 if (!v)
137                         continue;
138 
139                 switch(cert_policy[i].type) {
140                 case BLOB_ATTR_BINARY:
141                         fprintf(stdout, "signature:\n---\n%s---\n", (char *) blob_data(v));
142                         break;
143                 case BLOB_ATTR_NESTED:
144                         json = blobmsg_format_json_indent(blob_data(v), false, 0);
145                         if (!json)
146                                 continue;
147 
148                         fprintf(stdout, "payload:\n---\n%s\n---\n", json);
149                         free(json);
150                         break;
151                 }
152         }
153 }
154 
155 static int cert_dump(const char *certfile)
156 {
157         struct cert_object *cobj;
158         static LIST_HEAD(certchain);
159         unsigned int count = 0;
160 
161         if (cert_load(certfile, &certchain)) {
162                 fprintf(stderr, "cannot parse cert %s\n", basename((char *) certfile));
163                 return 1;
164         }
165 
166         list_for_each_entry(cobj, &certchain, list) {
167                 fprintf(stdout, "=== CHAIN ELEMENT %02u ===\n", ++count);
168                 cert_dump_blob(cobj->cert);
169         }
170 
171         return 0;
172 }
173 
174 int main(int argc, char *argv[])
175 {
176         if (argc != 2) {
177                 fprintf(stderr, "Usage: %s <cert.ucert>\n", argv[0]);
178                 return 3;
179         }
180 
181         cert_dump(argv[1]);
182 
183         return 0;
184 }
185 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt