ap_json.c (7602B)
1 #include "ap_json.h" 2 #include "inbox.h" 3 #include "sha256/sha256.h" 4 #include "base64.h" 5 6 #include <time.h> 7 #include <strings.h> 8 9 10 static int handle_ap_string(struct json_handlers *h, struct json_strtok *str) 11 { 12 struct ap_json *apjson = (struct ap_json*)h->data; 13 if (str->is_key && str->size == 8 14 && !memcmp(str->text, "@context", str->size)) { 15 apjson->flags |= AP_IS_CONTEXT; 16 } else if (apjson->flags & AP_IS_CONTEXT) { 17 apjson->flags &= ~AP_IS_CONTEXT; 18 } 19 20 return handle_string(&apjson->compact_handler, str); 21 } 22 23 static int handle_key(struct ap_json *a, char *key) 24 { 25 struct json_strtok str; 26 unsigned int *nop; 27 init_json_strtok(&str); 28 29 str.text = (unsigned char *)key; 30 str.size = strlen(key); 31 str.is_key = 1; 32 if (!handle_string(&a->compact_handler, &str)) { 33 note_error(&a->errs, "push @wsheaders oob"); 34 return 0; 35 } 36 37 if (!handle_token(&a->compact_handler, ':', &nop)) { 38 return 0; 39 } 40 41 return 1; 42 } 43 44 static int handle_kv(struct ap_json *a, char *key, char *val, int escape_val) 45 { 46 struct json_strtok str; 47 init_json_strtok(&str); 48 49 if (!handle_key(a, key)) { 50 return 0; 51 } 52 53 str.text = (unsigned char *)val; 54 str.size = strlen(val); 55 str.is_key = 0; 56 str.needs_escape = escape_val; 57 if (!handle_string(&a->compact_handler, &str)) { 58 note_error(&a->errs, "push @wsheaders oob"); 59 return 0; 60 } 61 62 return 1; 63 } 64 65 static int handle_wssig(struct ap_json *a) 66 { 67 struct json_strtok sig; 68 init_json_strtok(&sig); 69 unsigned int *nop; 70 71 if (!handle_key(a, "@wssig")) { 72 return 0; 73 } 74 75 sig.text = (unsigned char*)a->sig->b64_sig; 76 sig.size = a->sig->b64_len; 77 sig.is_key = 0; 78 if (!handle_string(&a->compact_handler, &sig)) { 79 note_error(&a->errs, "push @wssig val oob"); 80 return 0; 81 } 82 83 if (!handle_token(&a->compact_handler, ',', &nop)) { 84 note_error(&a->errs, "push @ws_sig : tok oob"); 85 return 0; 86 } 87 88 return 1; 89 } 90 91 static int handle_wsstamp(struct ap_json *a) 92 { 93 unsigned int *nop; 94 struct json_strtok str; 95 init_json_strtok(&str); 96 97 if (!handle_key(a, "@wsstamp")) { 98 return 0; 99 } 100 101 if (!handle_number(&a->compact_handler, time(NULL))) { 102 note_error(&a->errs, "push @wsstamp oob number"); 103 return 0; 104 } 105 106 if (!handle_token(&a->compact_handler, ',', &nop)) { 107 note_error(&a->errs, "push @ws_sig : tok oob"); 108 return 0; 109 } 110 111 return 1; 112 } 113 114 static int handle_wskeyid(struct ap_json *a) 115 { 116 unsigned int *nop; 117 struct json_strtok str; 118 init_json_strtok(&str); 119 120 if (!handle_kv(a, "@wskeyid", (char*)a->sig->key_id, 0)) { 121 return 0; 122 } 123 124 if (!handle_token(&a->compact_handler, ',', &nop)) { 125 note_error(&a->errs, "push @wskeyid , tok oob"); 126 return 0; 127 } 128 129 return 1; 130 } 131 132 static inline int handle_header(struct ap_json *a, struct http_header *header) 133 { 134 return handle_kv(a, header->name, header->value, 1); 135 } 136 137 struct sized_str { 138 unsigned char *text; 139 int size; 140 }; 141 142 static int split_headers(unsigned char *headers, int header_len, 143 struct sized_str *strs, int max_strs, int *out) 144 { 145 int n_strs = 0; 146 struct sized_str *str; 147 unsigned char *p, *pstart; 148 149 pstart = p = headers; 150 for (;; p++) { 151 if (n_strs == max_strs) 152 return 0; 153 154 if (*p == ' ' || *p == 0) { 155 str = &strs[n_strs++]; 156 str->text = pstart; 157 str->size = p - pstart; 158 pstart = p+1; 159 } 160 161 if (*p == 0) 162 break; 163 } 164 165 *out = n_strs; 166 return 1; 167 } 168 169 static inline struct http_header *find_header(struct http_header *headers, 170 unsigned char *name, int name_len) 171 { 172 struct http_header *header; 173 174 for (header = headers; header; header = header->next) { 175 if (name_len == strlen(header->name) && 176 !strncasecmp((const char *)name, header->name, name_len)) { 177 return header; 178 } 179 } 180 181 return NULL; 182 } 183 184 static int handle_wssigbuf(struct ap_json *a) 185 { 186 struct sized_str strs[16] = {0}; 187 int n_headers = 0, i; 188 struct http_header *header; 189 struct cursor *c = &((struct json_pusher *)a->compact_handler.data)->cur; 190 struct sized_str *str; 191 192 if (!handle_key(a, "@wssigbuf")) { 193 return 0; 194 } 195 196 if (!push_byte(c, '"')) { 197 return 0; 198 } 199 200 fprintf(stderr, "headers: %s\n", a->sig->headers); 201 202 if (!split_headers((unsigned char*)a->sig->headers, 203 strlen(a->sig->headers), strs, 204 sizeof(strs)/sizeof(strs[0]), &n_headers)) { 205 note_error(&a->errs, "split_headers overflow"); 206 return 0; 207 } 208 209 static const char request_target[] = "(request-target)"; 210 211 for (i = 0; i < n_headers; i++) { 212 str = &strs[i]; 213 if (!push_escaped(c, str->text, str->size)) { 214 return 0; 215 } 216 if (!push_str(c, ": ")) { 217 return 0; 218 } 219 220 if (str->size == (sizeof(request_target)-1) && 221 !memcmp(request_target, str->text, str->size)) { 222 if (!push_str(c, "post /inbox")) { 223 return 0; 224 } 225 } else if ((header = find_header(a->req->headers, str->text, str->size))) { 226 if (!push_escaped(c, (unsigned char*)header->value, 227 strlen(header->value))) { 228 return 0; 229 } 230 } else { 231 note_error(&a->errs, "could not find header %.*s", 232 str->size, str->text); 233 return 0; 234 } 235 236 if (i != n_headers-1) { 237 push_str(c, "\\n"); 238 } 239 } 240 241 if (!push_str(c, "\",")) { 242 return 0; 243 } 244 245 return 1; 246 } 247 248 static int handle_wsdigest(struct ap_json *a) 249 { 250 struct json_pusher *p = (struct json_pusher *)a->compact_handler.data; 251 struct cursor *c = &p->cur; 252 size_t b64_len; 253 unsigned char hash[32]; 254 unsigned char b64[128]; 255 unsigned char *pos; 256 257 if (!handle_key(a, "@wsdigest")) { 258 note_error(&a->errs, "wsdigest key oob"); 259 return 0; 260 } 261 262 if (!push_byte(c, '"')) { 263 return 0; 264 } 265 266 sha256_hash(hash, a->req->body, a->req->body_len); 267 // TODO: this might be broken... 268 base64_encode(hash, 32, b64, sizeof(b64), &b64_len); 269 270 pos = c->p; 271 272 if (!(push_str(c, "SHA-256=") && push_data(c, b64, b64_len) )) { 273 return 0; 274 } 275 276 // quick sanity check 277 if ((b64_len+8) != (c->p - pos) || !memcmp(pos, b64, b64_len)) { 278 note_error(&a->errs, "bad digest"); 279 return 0; 280 } 281 282 return push_str(c, "\","); 283 } 284 285 static int handle_ap_token(struct json_handlers *h, char token, 286 unsigned int **len) 287 { 288 struct ap_json *a = (struct ap_json*)h->data; 289 unsigned int *nop; 290 291 /* push some extra data after the start of the initial object */ 292 if (token == '{' && !(a->flags & AP_HAD_START)) { 293 a->flags |= AP_HAD_START | AP_IS_START; 294 295 if (!handle_token(&a->compact_handler, '{', &nop)) { 296 note_error(&a->errs, "push @ws_sig { tok oob"); 297 return 0; 298 } 299 300 if (!handle_wssig(a)) { 301 note_error(&a->errs, "push wssig"); 302 return 0; 303 } 304 305 if (!handle_wsstamp(a)) { 306 note_error(&a->errs, "push wsstamp"); 307 return 0; 308 } 309 310 if (!handle_wsdigest(a)) { 311 note_error(&a->errs, "push wsdigest"); 312 return 0; 313 } 314 315 if (!handle_wskeyid(a)) { 316 note_error(&a->errs, "push wskeyid"); 317 return 0; 318 } 319 320 if (!handle_wssigbuf(a)) { 321 note_error(&a->errs, "push wssigbuf"); 322 return 0; 323 } 324 325 return 1; 326 } 327 328 return handle_token(&a->compact_handler, token, len); 329 } 330 331 void init_ap_json(struct ap_json *a, struct json_handlers *inner) 332 { 333 memset(a, 0, sizeof(*a)); 334 init_errors(&a->errs); 335 copy_json_handlers(inner, &a->compact_handler); 336 } 337 338 static int handle_ap_bool(struct json_handlers *h, int val) 339 { 340 struct ap_json *a = (struct ap_json*)h->data; 341 return handle_bool(&a->compact_handler, val); 342 } 343 344 static int handle_ap_null(struct json_handlers *h) 345 { 346 struct ap_json *a = (struct ap_json*)h->data; 347 return handle_null(&a->compact_handler); 348 } 349 350 static int handle_ap_number(struct json_handlers *h, unsigned int number) 351 { 352 struct ap_json *a = (struct ap_json*)h->data; 353 return handle_number(&a->compact_handler, number); 354 } 355 356 void make_ap_json_pusher(struct json_handlers *h, struct ap_json *out) 357 { 358 h->data = out; 359 h->string = handle_ap_string; 360 h->boolean = handle_ap_bool; 361 h->null = handle_ap_null; 362 h->number = handle_ap_number; 363 h->token = handle_ap_token; 364 } 365