summaryrefslogtreecommitdiff
path: root/usr.sbin/rpki-client/rrdp_util.c
blob: 0565493b8c55ef664bdf8c73ab10ce68521c2f8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*	$OpenBSD: rrdp_util.c,v 1.1 2021/11/24 15:24:16 claudio Exp $ */
/*
 * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
 * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <assert.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>

#include <expat.h>
#include <openssl/sha.h>

#include "extern.h"
#include "rrdp.h"

/*
 * Both snapshots and deltas use publish_xml to store the publish and
 * withdraw records. Once all the content is added the request is sent
 * to the main process where it is processed.
 */
struct publish_xml *
new_publish_xml(enum publish_type type, char *uri, char *hash, size_t hlen)
{
	struct publish_xml *pxml;

	if ((pxml = calloc(1, sizeof(*pxml))) == NULL)
		err(1, "%s", __func__);

	pxml->type = type;
	pxml->uri = uri;
	if (hlen > 0) {
		assert(hlen == sizeof(pxml->hash));
		memcpy(pxml->hash, hash, hlen);
	}

	return pxml;
}

void
free_publish_xml(struct publish_xml *pxml)
{
	if (pxml == NULL)
		return;

	free(pxml->uri);
	free(pxml->data);
	free(pxml);
}

/*
 * Add buf to the base64 data string, ensure that this remains a proper
 * string by NUL-terminating the string.
 */
int
publish_add_content(struct publish_xml *pxml, const char *buf, int length)
{
	size_t newlen, outlen;

	/*
	 * optmisiation, this often gets called with '\n' as the
	 * only data... seems wasteful
	 */
	if (length == 1 && buf[0] == '\n')
		return 0;

	/* append content to data */
	if (SIZE_MAX - length - 1 <= pxml->data_length)
		return -1;
	newlen = pxml->data_length + length;
	if (base64_decode_len(newlen, &outlen) == -1 ||
	    outlen > MAX_FILE_SIZE)
		return -1;

	pxml->data = realloc(pxml->data, newlen + 1);
	if (pxml->data == NULL)
		err(1, "%s", __func__);

	memcpy(pxml->data + pxml->data_length, buf, length);
	pxml->data[newlen] = '\0';
	pxml->data_length = newlen;
	return 0;
}

/*
 * Base64 decode the data blob and send the file to the main process
 * where the hash is validated and the file stored in the repository.
 * Increase the file_pending counter to ensure the RRDP process waits
 * until all files have been processed before moving to the next stage.
 * Returns 0 on success or -1 on errors (base64 decode failed).
 */
int
publish_done(struct rrdp *s, struct publish_xml *pxml)
{
	unsigned char *data = NULL;
	size_t datasz = 0;

	if (pxml->data_length > 0)
		if ((base64_decode(pxml->data, pxml->data_length,
		    &data, &datasz)) == -1)
			return -1;

	rrdp_publish_file(s, pxml, data, datasz);

	free(data);
	free_publish_xml(pxml);
	return 0;
}