1 /* $OpenBSD: rrdp_util.c,v 1.1 2021/11/24 15:24:16 claudio 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 * 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 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 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 105 publish_done(struct rrdp *s, struct publish_xml *pxml) 106 { 107 unsigned char *data = NULL; 108 size_t datasz = 0; 109 110 if (pxml->data_length > 0) 111 if ((base64_decode(pxml->data, pxml->data_length, 112 &data, &datasz)) == -1) 113 return -1; 114 115 rrdp_publish_file(s, pxml, data, datasz); 116 117 free(data); 118 free_publish_xml(pxml); 119 return 0; 120 } 121