xref: /openbsd-src/usr.sbin/rpki-client/rrdp_util.c (revision aed5e91bb4b0ec998d6d48853b0ba7596b5eb595)
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