misc: correctly proceed to thread-deletion in rb79-delete-post
[rb-79.git] / tripcodes.c
blobafc7724f1e7a96f1853a12ef4ed0722a6a89e04a
1 /*
2 * Copyright (c) 2017-2018, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include <sodium.h>
25 #include "macros.h"
26 #include "rb79.h"
28 /* Global configuration */
29 static const struct configuration *conf;
31 /* Characters for Base64 */
32 static const char *base64_elts =
33 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
35 /* This should be a multiple of 3, so that base64 gives no '=' */
36 #define OUT_HASH_LEN (3 * 3)
39 * Initialize any static elements needed for this file
41 * Preconditions:
43 * - setup_tripcodes() was not invoked more recently than
44 * clean_tripcodes().
46 * Postconditions (success):
48 * - Any other function in this file may be safely called.
50 int setup_tripcodes(const struct configuration *in_conf)
52 conf = in_conf;
54 return 0;
58 * Base64 encode in to *out.
60 * Preconditions:
62 * - in is an array of memory of length in_len (it need not be a string).
64 * - in_len is a multiple of 3.
66 * - out and out_len are not 0.
68 * - overwriting *out shall not cause a memory leak.
70 * Postconditions (success):
72 * - *out is a string of length *out_len.
74 * - The contents of *out are the base64 encoding of the first
75 * in_len bytes of in.
77 static int base64_encode(const unsigned char *in, size_t in_len, char **out,
78 size_t *out_len)
80 int ret = -1;
81 size_t built_len = in_len * 4 / 3 + 3;
82 size_t out_idx = 0;
83 char *built = 0;
85 if ((in_len * 4) / in_len != 4 ||
86 (in_len * 4 / 3) + 3 < (in_len * 4 / 3)) {
87 ERROR_MESSAGE("overflow (in_len = %zu)", in_len);
88 goto done;
91 if (!(built = malloc(built_len))) {
92 PERROR_MESSAGE("malloc");
93 goto done;
96 for (size_t in_idx = 0; in_idx + 2 < in_len; in_idx += 3) {
97 unsigned char i1 = in[in_idx + 0];
98 unsigned char i2 = in[in_idx + 1];
99 unsigned char i3 = in[in_idx + 2];
100 size_t j1 = i1 >> 2;
101 size_t j2 = ((i1 & 0x03) << 4) | (i2 >> 4);
102 size_t j3 = ((i2 & 0x0F) << 2) | ((i3 & 0xC0) >> 6);
103 size_t j4 = (i3 & 0x3F);
105 built[out_idx++] = base64_elts[j1];
106 built[out_idx++] = base64_elts[j2];
107 built[out_idx++] = base64_elts[j3];
108 built[out_idx++] = base64_elts[j4];
111 built[out_idx] = '\0';
112 *out = built;
113 *out_len = out_idx;
114 ret = 0;
115 done:
117 return ret;
121 * Calculate (raw) tripcode from (raw) name, if necessary. Name is
122 * truncated to hide the input. This assumes p->raw.tripcode is
123 * empty.
125 * Preconditions:
127 * - p is not 0.
129 * - p->raw.name is either 0, or is a string of length p->raw.name_len.
131 * - Overwriting p->raw.tripcode shall not cause a memory leak.
133 * Postconditions (success):
135 * - If p->raw.name was of the form "foo#bar", it is now of the
136 * form "foo". p->raw.name_len has been adjusted accordingly.
138 * - If p->raw.name was of the form "foo#bar", p->raw.tripcode is
139 * determined by the key "bar". p->raw.tripcode_len is appropriate.
141 int tripcodes_calculate(struct post_cmd *p)
143 int ret = -1;
144 char *trip_phrase_start = 0;
145 unsigned char out_buf[OUT_HASH_LEN];
147 /* do not initialize this - unknown if struct or scalar */
148 crypto_generichash_state cg_state;
150 if (!p->raw.name_len) {
151 goto success;
154 /* XXX: The string length operations could be tightened */
155 trip_phrase_start = strchr(p->raw.name, '#');
157 if (!trip_phrase_start) {
158 goto success;
161 *trip_phrase_start = '\0';
162 p->raw.name_len = strlen(p->raw.name);
163 trip_phrase_start++;
165 if (!*trip_phrase_start) {
166 goto success;
169 if (crypto_generichash_init(&cg_state, 0, 0, OUT_HASH_LEN) < 0) {
170 PERROR_MESSAGE("crypto_generichash_init");
171 goto done;
174 if (crypto_generichash_update(&cg_state, (const unsigned
175 char *) trip_phrase_start,
176 strlen(trip_phrase_start)) < 0) {
177 LOG("Failed to update hash with \"%s\"", trip_phrase_start);
178 PERROR_MESSAGE("crypto_generichash_update");
179 goto done;
182 if (crypto_generichash_update(&cg_state, (const unsigned
183 char *) conf->trip_salt,
184 conf->trip_salt_len) < 0) {
185 LOG("Failed to update hash with \"%s\"", conf->trip_salt);
186 PERROR_MESSAGE("crypto_generichash_update");
187 goto done;
190 if (crypto_generichash_final(&cg_state, out_buf, OUT_HASH_LEN) < 0) {
191 PERROR_MESSAGE("crypto_generichash_final");
192 goto done;
195 if (base64_encode(out_buf, OUT_HASH_LEN, &p->raw.tripcode,
196 &p->raw.tripcode_len) < 0) {
197 goto done;
200 success:
201 ret = 0;
202 done:
204 return ret;
208 * Clean any memory from this file
210 * Postconditions (success):
212 * - Valgrind won't report any memory leaks from this file.
214 * - setup_tripcodes() can be safely called again.
216 int clean_tripcodes(void)
218 conf = 0;
220 return 0;