1 /* $OpenBSD: rrdp_util.c,v 1.2 2023/11/24 14:05:47 job Exp $ */
2 /*
3 * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
4 * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include <assert.h>
19 #include <err.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <expat.h>
24 #include <openssl/sha.h>
25
26 #include "extern.h"
27 #include "rrdp.h"
28
29 /*
30 * Both snapshots and deltas use publish_xml to store the publish and
31 * withdraw records. Once all the content is added the request is sent
32 * to the main process where it is processed.
33 */
34 struct publish_xml *
new_publish_xml(enum publish_type type,char * uri,char * hash,size_t hlen)35 new_publish_xml(enum publish_type type, char *uri, char *hash, size_t hlen)
36 {
37 struct publish_xml *pxml;
38
39 if ((pxml = calloc(1, sizeof(*pxml))) == NULL)
40 err(1, "%s", __func__);
41
42 pxml->type = type;
43 pxml->uri = uri;
44 if (hlen > 0) {
45 assert(hlen == sizeof(pxml->hash));
46 memcpy(pxml->hash, hash, hlen);
47 }
48
49 return pxml;
50 }
51
52 void
free_publish_xml(struct publish_xml * pxml)53 free_publish_xml(struct publish_xml *pxml)
54 {
55 if (pxml == NULL)
56 return;
57
58 free(pxml->uri);
59 free(pxml->data);
60 free(pxml);
61 }
62
63 /*
64 * Add buf to the base64 data string, ensure that this remains a proper
65 * string by NUL-terminating the string.
66 */
67 int
publish_add_content(struct publish_xml * pxml,const char * buf,int length)68 publish_add_content(struct publish_xml *pxml, const char *buf, int length)
69 {
70 size_t newlen, outlen;
71
72 /*
73 * optmisiation, this often gets called with '\n' as the
74 * only data... seems wasteful
75 */
76 if (length == 1 && buf[0] == '\n')
77 return 0;
78
79 /* append content to data */
80 if (SIZE_MAX - length - 1 <= pxml->data_length)
81 return -1;
82 newlen = pxml->data_length + length;
83 if (base64_decode_len(newlen, &outlen) == -1 ||
84 outlen > MAX_FILE_SIZE)
85 return -1;
86
87 pxml->data = realloc(pxml->data, newlen + 1);
88 if (pxml->data == NULL)
89 err(1, "%s", __func__);
90
91 memcpy(pxml->data + pxml->data_length, buf, length);
92 pxml->data[newlen] = '\0';
93 pxml->data_length = newlen;
94 return 0;
95 }
96
97 /*
98 * Base64 decode the data blob and send the file to the main process
99 * where the hash is validated and the file stored in the repository.
100 * Increase the file_pending counter to ensure the RRDP process waits
101 * until all files have been processed before moving to the next stage.
102 * Returns 0 on success or -1 on errors (base64 decode failed).
103 */
104 int
publish_done(struct rrdp * s,struct publish_xml * pxml)105 publish_done(struct rrdp *s, struct publish_xml *pxml)
106 {
107 unsigned char *data = NULL;
108 size_t datasz = 0;
109
110 switch (pxml->type) {
111 case PUB_ADD:
112 case PUB_UPD:
113 if (base64_decode_len(pxml->data_length, &datasz) == -1)
114 return -1;
115 if (datasz < MIN_FILE_SIZE)
116 return -1;
117 if ((base64_decode(pxml->data, pxml->data_length,
118 &data, &datasz)) == -1)
119 return -1;
120 break;
121 case PUB_DEL:
122 if (pxml->data_length != 0)
123 return -1;
124 break;
125 }
126
127 rrdp_publish_file(s, pxml, data, datasz);
128
129 free(data);
130 free_publish_xml(pxml);
131 return 0;
132 }
133