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