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