1 /**
2 * @file mediator_json.c
3 *
4 * Contains most of the JSON-y functions.
5 *
6 ** ------------------------------------------------------------------------
7 ** Copyright (C) 2012-2017 Carnegie Mellon University. All Rights Reserved.
8 ** ------------------------------------------------------------------------
9 * Authors: Emily Sarneso <netsa-help@cert.org>
10 * ------------------------------------------------------------------------
11 * @OPENSOURCE_HEADER_START@
12 * Use of this (and related) source code is subject to the terms
13 * of the following licenses:
14 *
15 * GNU Public License (GPL) Rights pursuant to Version 2, June 1991
16 * Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
17 *
18 * NO WARRANTY
19 *
20 * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
21 * PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
22 * PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
23 * "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
24 * KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
25 * LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
26 * MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
27 * OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
28 * SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
29 * TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
30 * WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
31 * LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
32 * CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
33 * CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
34 * DELIVERABLES UNDER THIS LICENSE.
35 *
36 * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
37 * Mellon University, its trustees, officers, employees, and agents from
38 * all claims or demands made against them (and any related losses,
39 * expenses, or attorney's fees) arising out of, or relating to Licensee's
40 * and/or its sub licensees' negligent use or willful misuse of or
41 * negligent conduct or willful misconduct regarding the Software,
42 * facilities, or other rights or assistance granted by Carnegie Mellon
43 * University under this License, including, but not limited to, any
44 * claims of product liability, personal injury, death, damage to
45 * property, or violation of any laws or regulations.
46 *
47 * Carnegie Mellon University Software Engineering Institute authored
48 * documents are sponsored by the U.S. Department of Defense under
49 * Contract FA8721-05-C-0003. Carnegie Mellon University retains
50 * copyrights in all material produced under this contract. The U.S.
51 * Government retains a non-exclusive, royalty-free license to publish or
52 * reproduce these documents, or allow othersto do so, for U.S.
53 * Government purposes only pursuant to the copyright license under the
54 * contract clause at 252.227.7013.
55 *
56 *
57 * @OPENSOURCE_HEADER_END@
58 * -----------------------------------------------------------
59 */
60
61 #include <mediator/mediator_ctx.h>
62 #include <mediator/mediator_util.h>
63 #include <mediator/mediator_inf.h>
64 #include "mediator_print.h"
65 #include "mediator_json.h"
66
67 #define FBSTLNEXT(a, b) fbSubTemplateListGetNextPtr(a, b)
68 #define MD_REM_MSG(_buf_) (buf->buflen - (_buf_->cp - _buf_->buf))
69
70 #define MD_WR_BDC(_ret_, _size_) \
71 if (_ret_ < 0) return FALSE; \
72 if ((size_t)_ret_ >= _size_) return FALSE; \
73 _size_ -= _ret_;
74
75 #define MD_CHECK_RET(_buf_, _ret_, _size_) \
76 if (_ret_ < 0) return FALSE; \
77 if ((size_t)_ret_ >= _size_) return FALSE; \
78 _size_ -= _ret_; \
79 _buf_->cp += _ret_;
80
81 #define MD_CHECK_RET0(_buf_, _ret_, _size_) \
82 if (_ret_ < 0) return 0; \
83 if ((size_t)_ret_ >= _size_) return 0; \
84 _size_ -= _ret_; \
85 _buf_->cp += _ret_;
86
87 #define MD_APPEND_CHAR(_buf_, _ch_) \
88 *(_buf_->cp) = _ch_; \
89 ++(_buf_->cp);
90 #define MD_APPEND_CHAR_CHECK(_rem_, _buf_, _ch_) \
91 if (_rem_ > 1) { \
92 MD_APPEND_CHAR(_buf_, _ch_); \
93 _rem_ -= 1; \
94 } else { \
95 return FALSE; \
96 }
97
98
99 /* RFC 4627 -
100 Any character may be escaped. If the character is in the Basic
101 Multilingual Plane (U+0000 through U+FFFF), then it may be
102 represented as a six-character sequence: a reverse solidus, followed
103 by the lowercase letter u, followed by four hexadecimal digits that
104 encode the character's code point. The hexadecimal letters A though
105 F can be upper or lowercase. So, for example, a string containing
106 only a single reverse solidus character may be represented as
107 "\u005C".
108 */
109
mdJsonifyEscapeChars(mdBuf_t * mdbuf,size_t * rem,uint8_t * buf,size_t buflen)110 gboolean mdJsonifyEscapeChars(
111 mdBuf_t *mdbuf,
112 size_t *rem,
113 uint8_t *buf,
114 size_t buflen)
115 {
116 int i, ret;
117 uint8_t ch;
118
119 for (i = 0; i < (int)buflen; i++) {
120 ch = buf[i];
121 if (ch == '\\') {
122 ret = snprintf(mdbuf->cp, *rem, "\\\\");
123 } else if (ch < 32 || ch >= 127) {
124 ret = snprintf(mdbuf->cp, *rem, "\\u%04x", ch);
125 } else if (ch == '"') {
126 ret = snprintf(mdbuf->cp, *rem, "\\%c", ch);
127 } else {
128 ret = snprintf(mdbuf->cp, *rem, "%c", ch);
129 }
130 MD_WR_BDC(ret, *rem);
131 mdbuf->cp += ret;
132 }
133
134 return TRUE;
135
136 }
137
mdJsonifyDNSRRRecord(md_dns_rr_t * rec,mdBuf_t * buf)138 gboolean mdJsonifyDNSRRRecord(
139 md_dns_rr_t *rec,
140 mdBuf_t *buf)
141 {
142 size_t brem = MD_REM_MSG(buf);
143 size_t buftest;
144 uint64_t start_secs = rec->flowStartMilliseconds / 1000;
145 uint32_t start_rem = rec->flowStartMilliseconds % 1000;
146 char sabuf[40];
147 char testsip[16];
148 int ret;
149
150 ret = snprintf(buf->cp, brem, "{\"dns\":{\"flowStartMilliseconds\":\"");
151 MD_CHECK_RET0(buf, ret, brem);
152
153 memset(testsip, 0, sizeof(testsip));
154
155 if (!md_util_time_buf_append(buf, &brem, start_secs, PRINT_TIME_FMT)) {
156 return 0;
157 }
158
159 ret = snprintf(buf->cp, brem, ".%03u\",", start_rem);
160
161 MD_CHECK_RET0(buf, ret, brem);
162
163 if (rec->sourceIPv4Address == 0) {
164 if (memcmp(rec->sourceIPv6Address, testsip, sizeof(rec->sourceIPv6Address))) {
165 md_util_print_ip6_addr(sabuf, rec->sourceIPv6Address);
166 ret = snprintf(buf->cp, brem, "\"sourceIPv6Address\":\"%s\",", sabuf);
167 MD_CHECK_RET0(buf, ret, brem);
168 md_util_print_ip6_addr(sabuf, rec->destinationIPv6Address);
169 ret = snprintf(buf->cp, brem, "\"destinationIPv6Address\":\"%s\",", sabuf);
170 MD_CHECK_RET0(buf, ret, brem);
171 }
172 } else {
173 md_util_print_ip4_addr(sabuf, rec->sourceIPv4Address);
174 ret = snprintf(buf->cp, brem, "\"sourceIPv4Address\":\"%s\",", sabuf);
175 MD_CHECK_RET0(buf, ret, brem);
176 md_util_print_ip4_addr(sabuf, rec->destinationIPv4Address);
177 ret = snprintf(buf->cp, brem, "\"destinationIPv4Address\":\"%s\",", sabuf);
178 MD_CHECK_RET0(buf, ret, brem);
179
180 }
181
182 if (rec->protocolIdentifier) {
183 ret = snprintf(buf->cp, brem, "\"protocolIdentifier\":%d,", rec->protocolIdentifier);
184 MD_CHECK_RET0(buf, ret, brem);
185 }
186
187 if (rec->vlanId) {
188 ret = snprintf(buf->cp, brem, "\"vlanId\":\"%u,", rec->vlanId);
189 MD_CHECK_RET0(buf, ret, brem);
190 }
191
192 if (rec->sourceTransportPort) {
193 ret = snprintf(buf->cp, brem, "\"sourceTransportPort\":%d,", rec->sourceTransportPort);
194 MD_CHECK_RET0(buf, ret, brem);
195 }
196
197 if (rec->destinationTransportPort) {
198 ret = snprintf(buf->cp,brem, "\"destinationTransportPort\":%d,", rec->destinationTransportPort);
199 MD_CHECK_RET0(buf, ret,brem);
200 }
201
202 if (rec->yafFlowKeyHash) {
203 ret = snprintf(buf->cp,brem, "\"yafFlowKeyHash\":%u,", rec->yafFlowKeyHash);
204 MD_CHECK_RET0(buf, ret,brem);
205 }
206
207 if (rec->observationDomainId) {
208 ret = snprintf(buf->cp, brem, "\"observationDomainId\":%u,", rec->observationDomainId);
209 MD_CHECK_RET0(buf, ret, brem);
210 }
211
212 ret = snprintf(buf->cp, brem, "\"dnsRRSection\":%d,\"dnsNXDomain\":%d,",
213 rec->dnsRRSection, rec->dnsNXDomain);
214 MD_CHECK_RET(buf, ret, brem);
215
216 if (rec->dnsAuthoritative) {
217 ret = snprintf(buf->cp, brem, "\"dnsAuthoritative\":\"True\",");
218 } else {
219 ret = snprintf(buf->cp, brem, "\"dnsAuthoritative\":\"False\",");
220 }
221 MD_CHECK_RET(buf, ret, brem);
222
223 ret = snprintf(buf->cp, brem, "\"dnsQRType\":%d, \"dnsTTL\":%u, "
224 "\"dnsID\":%d,",
225 rec->dnsQRType, rec->dnsTTL, rec->dnsID);
226
227 MD_CHECK_RET(buf, ret, brem);
228
229 if (rec->rrname.buf) {
230 ret = snprintf(buf->cp, brem, "\"dnsQName\":\"");
231 MD_CHECK_RET(buf, ret, brem);
232 mdJsonifyEscapeChars(buf, &brem, rec->rrname.buf, rec->rrname.len);
233 ret = snprintf(buf->cp, brem, "\",");
234 MD_CHECK_RET(buf, ret, brem);
235 } /* else - query may be for the root server which is NULL*/
236
237 buftest = MD_REM_MSG(buf);
238
239 if (rec->dnsQueryResponse == 0) {
240 /* query */
241 buf->cp -= 1;
242 brem += 1;
243 MD_APPEND_CHAR_CHECK(brem, buf, '}');
244 MD_APPEND_CHAR_CHECK(brem, buf, '}');
245 MD_APPEND_CHAR_CHECK(brem, buf, '\n');
246
247 return TRUE;
248 }
249
250 if (rec->dnsQRType == 1) {
251 uint32_t sip;
252 if (rec->rrdata.len) {
253 memcpy(&sip, rec->rrdata.buf, sizeof(uint32_t));
254 md_util_print_ip4_addr(sabuf, sip);
255 ret = snprintf(buf->cp, brem, "\"A\":\"%s\"", sabuf);
256 MD_CHECK_RET(buf, ret, brem);
257 }
258 } else if (rec->dnsQRType == 2) {
259 ret = snprintf(buf->cp, brem, "\"dnsNSDName\":\"");
260 MD_CHECK_RET(buf, ret, brem);
261 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
262 rec->rrdata.len);
263 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
264
265 } else if (rec->dnsQRType == 5) {
266 ret = snprintf(buf->cp, brem, "\"dnsCName\":\"");
267 MD_CHECK_RET(buf, ret, brem);
268 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
269 rec->rrdata.len);
270 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
271 } else if (rec->dnsQRType == 12) {
272 ret = snprintf(buf->cp, brem, "\"dnsPTRDName\":\"");
273 MD_CHECK_RET(buf, ret, brem);
274 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
275 rec->rrdata.len);
276 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
277 } else if (rec->dnsQRType == 15) {
278 ret = snprintf(buf->cp, brem, "\"dnsMXExchange\":\"");
279 MD_CHECK_RET(buf, ret, brem);
280 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
281 rec->rrdata.len);
282 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
283 } else if (rec->dnsQRType == 28) {
284 uint8_t sip[16];
285 if (rec->rrdata.len) {
286 memcpy(sip, rec->rrdata.buf, sizeof(sip));
287 md_util_print_ip6_addr(sabuf, sip);
288 ret = snprintf(buf->cp, brem, "\"AAAA\":\"%s\"", sabuf);
289 MD_CHECK_RET(buf, ret, brem);
290 }
291 } else if (rec->dnsQRType == 16) {
292 ret = snprintf(buf->cp, brem, "\"dnsTXTData\":\"");
293 MD_CHECK_RET(buf, ret, brem);
294 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
295 rec->rrdata.len);
296 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
297 } else if (rec->dnsQRType == 33) {
298 ret = snprintf(buf->cp, brem, "\"dnsSRVTarget\":\"");
299 MD_CHECK_RET(buf, ret, brem);
300 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
301 rec->rrdata.len);
302 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
303 } else if (rec->dnsQRType == 6) {
304 ret = snprintf(buf->cp, brem, "\"dnsSOAMName\":\"");
305 MD_CHECK_RET(buf, ret, brem);
306 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
307 rec->rrdata.len);
308 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
309 } else if (rec->dnsQRType == 46) {
310 ret = snprintf(buf->cp, brem, "\"dnsSigner\":\"");
311 MD_CHECK_RET(buf, ret, brem);
312 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
313 rec->rrdata.len);
314 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
315 } else if (rec->dnsQRType == 47) {
316 ret = snprintf(buf->cp, brem, "\"dnsHashData\":\"");
317 MD_CHECK_RET(buf, ret, brem);
318 mdJsonifyEscapeChars(buf, &brem, rec->rrdata.buf,
319 rec->rrdata.len);
320 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
321 }
322
323 brem = MD_REM_MSG(buf);
324
325 /* no rrname/rrdata */
326 if (brem == buftest) {
327 /* remove the comma at the end of dnsQName */
328 buf->cp -= 1;
329 brem += 1;
330 }
331
332 MD_APPEND_CHAR_CHECK(brem, buf, '}');
333 MD_APPEND_CHAR_CHECK(brem, buf, '}');
334 MD_APPEND_CHAR_CHECK(brem, buf, '\n');
335 return TRUE;
336
337 }
338
339
340
mdJsonifyDNSRecord(yaf_dnsQR_t * dns,mdBuf_t * buf)341 gboolean mdJsonifyDNSRecord(
342 yaf_dnsQR_t *dns,
343 mdBuf_t *buf)
344 {
345 size_t brem = MD_REM_MSG(buf);
346 size_t buftest;
347 int ret;
348
349 ret = snprintf(buf->cp, brem, "\"dnsRRSection\":%d,\"dnsNXDomain\":%d,",
350 dns->dnsRRSection, dns->dnsNXDomain);
351 MD_CHECK_RET(buf, ret, brem);
352
353 if (dns->dnsAuthoritative) {
354 ret = snprintf(buf->cp, brem, "\"dnsAuthoritative\":\"True\",");
355 } else {
356 ret = snprintf(buf->cp, brem, "\"dnsAuthoritative\":\"False\",");
357 }
358 MD_CHECK_RET(buf, ret, brem);
359
360 ret = snprintf(buf->cp, brem, "\"dnsQRType\":%d, \"dnsTTL\":%u, \"dnsID\":%d,",
361 dns->dnsQRType, dns->dnsTTL, dns->dnsID);
362
363 MD_CHECK_RET(buf, ret, brem);
364
365 if (dns->dnsQName.buf) {
366 ret = snprintf(buf->cp, brem, "\"dnsQName\":\"");
367 MD_CHECK_RET(buf, ret, brem);
368 mdJsonifyEscapeChars(buf, &brem, dns->dnsQName.buf, dns->dnsQName.len);
369 ret = snprintf(buf->cp, brem, "\",");
370 MD_CHECK_RET(buf, ret, brem);
371 } /* else - query may be for the root server which is NULL*/
372
373 buftest = MD_REM_MSG(buf);
374
375 if (dns->dnsQRType == 1) {
376 yaf_dnsA_t *aflow = NULL;
377 char ipaddr[20];
378 while ((aflow = (yaf_dnsA_t *)FBSTLNEXT(&(dns->dnsRRList), aflow))) {
379 if (aflow->sourceIPv4Address) {
380 md_util_print_ip4_addr(ipaddr, aflow->sourceIPv4Address);
381 ret = snprintf(buf->cp, brem, "\"A\":\"%s\"", ipaddr);
382 MD_CHECK_RET(buf, ret, brem);
383 }
384 }
385 } else if (dns->dnsQRType == 2) {
386 yaf_dnsNS_t *ns = NULL;
387 while ((ns = (yaf_dnsNS_t *)FBSTLNEXT(&(dns->dnsRRList), ns))){
388 ret = snprintf(buf->cp, brem, "\"dnsNSDName\":\"");
389 MD_CHECK_RET(buf, ret, brem);
390 mdJsonifyEscapeChars(buf, &brem, ns->dnsNSDName.buf,
391 ns->dnsNSDName.len);
392 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
393 }
394
395 } else if (dns->dnsQRType == 5) {
396 yaf_dns_CNAME_t *c = NULL;
397 while ((c = (yaf_dns_CNAME_t *)FBSTLNEXT(&(dns->dnsRRList), c)))
398 {
399 ret = snprintf(buf->cp, brem, "\"dnsCName\":\"");
400 MD_CHECK_RET(buf, ret, brem);
401 mdJsonifyEscapeChars(buf, &brem, c->dnsCName.buf,
402 c->dnsCName.len);
403 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
404 }
405 } else if (dns->dnsQRType == 12) {
406 yaf_dnsPTR_t *ptr = NULL;
407 while ((ptr = (yaf_dnsPTR_t *)FBSTLNEXT(&(dns->dnsRRList), ptr)))
408 {
409 ret = snprintf(buf->cp, brem, "\"dnsPTRDName\":\"");
410 MD_CHECK_RET(buf, ret, brem);
411 mdJsonifyEscapeChars(buf, &brem, ptr->dnsPTRDName.buf,
412 ptr->dnsPTRDName.len);
413 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
414 }
415 } else if (dns->dnsQRType == 15) {
416 yaf_dnsMX_t *mx = NULL;
417 while (( mx = (yaf_dnsMX_t *)FBSTLNEXT(&(dns->dnsRRList), mx)))
418 {
419 ret = snprintf(buf->cp, brem, "\"dnsMXExchange\":\"");
420 MD_CHECK_RET(buf, ret, brem);
421 mdJsonifyEscapeChars(buf, &brem, mx->dnsMXExchange.buf,
422 mx->dnsMXExchange.len);
423 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
424 }
425 } else if (dns->dnsQRType == 28) {
426 yaf_dnsAAAA_t *aa = NULL;
427 char ipaddr[40];
428 while ((aa = (yaf_dnsAAAA_t *)FBSTLNEXT(&(dns->dnsRRList), aa)))
429 {
430 md_util_print_ip6_addr(ipaddr,(uint8_t *)&(aa->sourceIPv6Address));
431 ret = snprintf(buf->cp, brem, "\"AAAA\":\"%s\"", ipaddr);
432 MD_CHECK_RET(buf, ret, brem);
433 }
434 } else if (dns->dnsQRType == 16) {
435 yaf_dnsTXT_t *txt = NULL;
436 while ((txt = (yaf_dnsTXT_t *)FBSTLNEXT(&(dns->dnsRRList), txt)))
437 {
438 ret = snprintf(buf->cp, brem, "\"dnsTXTData\":\"");
439 MD_CHECK_RET(buf, ret, brem);
440 mdJsonifyEscapeChars(buf, &brem, txt->dnsTXTData.buf,
441 txt->dnsTXTData.len);
442 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
443 }
444 } else if (dns->dnsQRType == 33) {
445 yaf_dnsSRV_t *srv = NULL;
446 while ((srv = (yaf_dnsSRV_t *)FBSTLNEXT(&(dns->dnsRRList), srv)))
447 {
448 ret = snprintf(buf->cp, brem, "\"dnsSRVTarget\":\"");
449 MD_CHECK_RET(buf, ret, brem);
450 mdJsonifyEscapeChars(buf, &brem,srv->dnsSRVTarget.buf,
451 srv->dnsSRVTarget.len);
452 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
453 }
454 } else if (dns->dnsQRType == 6) {
455 yaf_dnsSOA_t *soa = NULL;
456 while ((soa = (yaf_dnsSOA_t *)FBSTLNEXT(&(dns->dnsRRList), soa))) {
457 ret = snprintf(buf->cp, brem, "\"dnsSOAMName\":\"");
458 MD_CHECK_RET(buf, ret, brem);
459 mdJsonifyEscapeChars(buf, &brem,soa->dnsSOAMName.buf,
460 soa->dnsSOAMName.len);
461 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
462 }
463 } else if (dns->dnsQRType == 46) {
464 yaf_dnsRRSig_t *rr = NULL;
465 while ((rr = (yaf_dnsRRSig_t *)FBSTLNEXT(&(dns->dnsRRList), rr))) {
466 ret = snprintf(buf->cp, brem, "\"dnsSigner\":\"");
467 MD_CHECK_RET(buf, ret, brem);
468 mdJsonifyEscapeChars(buf, &brem, rr->dnsSigner.buf,
469 rr->dnsSigner.len);
470 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
471 }
472 } else if (dns->dnsQRType == 47) {
473 yaf_dnsNSEC_t *nsec = NULL;
474 while ((nsec = (yaf_dnsNSEC_t *)FBSTLNEXT(&(dns->dnsRRList), nsec)))
475 {
476 ret = snprintf(buf->cp, brem, "\"dnsHashData\":\"");
477 MD_CHECK_RET(buf, ret, brem);
478 mdJsonifyEscapeChars(buf, &brem, nsec->dnsHashData.buf,
479 nsec->dnsHashData.len);
480 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
481 }
482 }
483
484 brem = MD_REM_MSG(buf);
485
486 /* no rrname/rrdata */
487 if (brem == buftest) {
488 /* remove the comma at the end of dnsQName */
489 buf->cp -= 1;
490 brem += 1;
491 }
492
493 return TRUE;
494
495 }
496
mdPrintJsonStats(yaf_stats_option_t * stats,char * name,FILE * lfp,GError ** err)497 size_t mdPrintJsonStats(
498 yaf_stats_option_t *stats,
499 char *name,
500 FILE *lfp,
501 GError **err)
502 {
503
504 GString *str = NULL;
505 char ipaddr[20];
506 size_t rc;
507
508 md_util_print_ip4_addr(ipaddr, stats->exporterIPv4Address);
509 str = g_string_new("");
510
511 g_string_append(str, "{\"stats\":{");
512
513 g_string_append_printf(str, "\"exportedFlowTotalCount\":%"PRIu64",",
514 stats->exportedFlowRecordTotalCount);
515 g_string_append_printf(str, "\"packetTotalCount\":%"PRIu64",",
516 stats->packetTotalCount);
517 g_string_append_printf(str, "\"droppedPacketTotalCount\":%"PRIu64",",
518 stats->droppedPacketTotalCount);
519 g_string_append_printf(str, "\"ignoredPacketTotalCount\":%"PRIu64",",
520 stats->ignoredPacketTotalCount);
521 g_string_append_printf(str, "\"expiredFragmentCount\":%u,",
522 stats->expiredFragmentCount);
523 g_string_append_printf(str, "\"assembledFragmentCount\":%u,",
524 stats->assembledFragmentCount);
525 g_string_append_printf(str, "\"flowTableFlushEvents\":%u,",
526 stats->flowTableFlushEvents);
527 g_string_append_printf(str, "\"flowTablePeakCount\":%u,",
528 stats->flowTablePeakCount);
529 g_string_append_printf(str, "\"exporterIPv4Address\":\"%s\",", ipaddr);
530 g_string_append_printf(str, "\"exportingProcessId\":%d,",
531 stats->exportingProcessId);
532 g_string_append_printf(str, "\"meanFlowRate\":%u,",
533 stats->meanFlowRate);
534 g_string_append_printf(str, "\"meanPacketRate\":%u,",
535 stats->meanPacketRate);
536 g_string_append_printf(str, "\"exporterName\":\"%s\"", name);
537
538 g_string_append(str, "}}\n");
539
540 rc = fwrite(str->str, 1, str->len, lfp);
541
542 if (rc != str->len) {
543 g_set_error(err, MD_ERROR_DOMAIN, MD_ERROR_IO,
544 "Error writing %d b ytes to file: %s\n",
545 (unsigned int)str->len, strerror(errno));
546 return 0;
547 }
548
549 g_string_free(str, TRUE);
550
551 return rc;
552 }
553
mdJsonifyDNSDedupRecord(FILE * fp,mdBuf_t * buf,uint8_t * rec,gboolean print_last,gboolean base64,GError ** err)554 int mdJsonifyDNSDedupRecord(
555 FILE *fp,
556 mdBuf_t *buf,
557 uint8_t *rec,
558 gboolean print_last,
559 gboolean base64,
560 GError **err)
561 {
562 size_t rc = 0;
563 char sabuf[40];
564 md_dns_t *record = (md_dns_t *)rec;
565 uint64_t start_secs = record->flowStartMilliseconds / 1000;
566 uint32_t start_rem = record->flowStartMilliseconds % 1000;
567 uint64_t end_secs = record->flowEndMilliseconds / 1000;
568 uint32_t end_rem = record->flowEndMilliseconds % 1000;
569 gchar *base1 = NULL;
570 size_t brem = MD_REM_MSG(buf);
571 gboolean encode = FALSE;
572 int ret;
573
574 ret = snprintf(buf->cp, brem, "{\"dns\":{\"flowStartMilliseconds\":\"");
575 MD_CHECK_RET0(buf, ret, brem);
576
577 if (!md_util_time_buf_append(buf, &brem, start_secs, PRINT_TIME_FMT)) {
578 return 0;
579 }
580
581 ret = snprintf(buf->cp, brem, ".%03u\",", start_rem);
582
583 MD_CHECK_RET0(buf, ret, brem);
584
585 if (print_last) {
586 ret = snprintf(buf->cp, brem, "\"flowEndMilliseconds\":\"");
587 MD_CHECK_RET0(buf, ret, brem);
588
589 if (!md_util_time_buf_append(buf, &brem, end_secs, PRINT_TIME_FMT)) {
590 return 0;
591 }
592
593 ret = snprintf(buf->cp, brem, ".%03u\",", end_rem);
594 MD_CHECK_RET0(buf, ret, brem);
595 }
596
597 ret = snprintf(buf->cp, brem, "\"dnsQRType\":%d,", record->rrtype);
598 MD_CHECK_RET0(buf, ret, brem);
599
600 if (print_last) {
601 ret = snprintf(buf->cp, brem, "\"dnsHitCount\":%d,\"dnsTTL\":%d,",
602 record->dnsHitCount, record->dnsTTL);
603 MD_CHECK_RET0(buf, ret, brem);
604 }
605
606 if (record->rrname.len) {
607
608 if (base64) {
609 base1 = g_base64_encode((const guchar *)record->rrname.buf,
610 record->rrname.len-1);
611 ret = snprintf(buf->cp, brem, "\"dnsQName\":\"%s\",", base1);
612 MD_CHECK_RET0(buf, ret, brem);
613 g_free(base1);
614 } else {
615 ret = snprintf(buf->cp, brem, "\"dnsQName\":\"");
616 MD_CHECK_RET0(buf, ret, brem);
617 if (!mdJsonifyEscapeChars(buf, &brem, (uint8_t *)record->rrname.buf,
618 record->rrname.len-1)) {
619 return 0;
620 }
621 if (brem > 2) {
622 MD_APPEND_CHAR(buf, '\"');
623 MD_APPEND_CHAR(buf, ',');
624 }
625 }
626 }
627
628 if (record->rrtype == 1) {
629 if (record->sourceIPv4Address) {
630 md_util_print_ip4_addr(sabuf, record->sourceIPv4Address);
631 ret = snprintf(buf->cp, brem, "\"A\":\"%s\"", sabuf);
632 MD_CHECK_RET0(buf, ret, brem);
633 }
634 } else if (record->rrtype == 2) {
635 ret = snprintf(buf->cp, brem, "\"dnsNSDName\":\"");
636 MD_CHECK_RET(buf, ret, brem);
637 if (base64) {
638 encode = TRUE;
639 } else {
640 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
641 record->rrdata.len);
642 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
643 }
644
645 } else if (record->rrtype == 5) {
646 ret = snprintf(buf->cp, brem, "\"dnsCName\":\"");
647 MD_CHECK_RET(buf, ret, brem);
648 if (base64) {
649 encode = TRUE;
650 } else {
651 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
652 record->rrdata.len);
653 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
654 }
655 } else if (record->rrtype == 12) {
656 ret = snprintf(buf->cp, brem, "\"dnsPTRDName\":\"");
657 MD_CHECK_RET(buf, ret, brem);
658 if (base64) {
659 encode = TRUE;
660 } else {
661 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
662 record->rrdata.len);
663 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
664 }
665 } else if (record->rrtype == 15) {
666 ret = snprintf(buf->cp, brem, "\"dnsMXExchange\":\"");
667 MD_CHECK_RET(buf, ret, brem);
668 if (base64) {
669 encode = TRUE;
670 } else {
671 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
672 record->rrdata.len);
673 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
674 }
675 } else if (record->rrtype == 28) {
676 md_util_print_ip6_addr(sabuf, record->rrdata.buf);
677 ret = snprintf(buf->cp, brem, "\"AAAA\":\"%s\"", sabuf);
678 MD_CHECK_RET0(buf, ret, brem);
679 } else if (record->rrtype == 16) {
680 ret = snprintf(buf->cp, brem, "\"dnsTXTData\":\"");
681 MD_CHECK_RET(buf, ret, brem);
682 if (base64) {
683 encode = TRUE;
684 } else {
685 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
686 record->rrdata.len);
687 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
688 }
689 } else if (record->rrtype == 33) {
690 ret = snprintf(buf->cp, brem, "\"dnsSRVTarget\":\"");
691 MD_CHECK_RET(buf, ret, brem);
692 if (base64) {
693 encode = TRUE;
694 } else {
695 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
696 record->rrdata.len);
697 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
698 }
699 } else if (record->rrtype == 6) {
700 ret = snprintf(buf->cp, brem, "\"dnsSOAMName\":\"");
701 MD_CHECK_RET(buf, ret, brem);
702 if (base64) {
703 encode = TRUE;
704 } else {
705 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
706 record->rrdata.len);
707 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
708 }
709 } else if (record->rrtype == 46) {
710 ret = snprintf(buf->cp, brem, "\"dnsSigner\":\"");
711 MD_CHECK_RET(buf, ret, brem);
712 if (base64) {
713 encode = TRUE;
714 } else {
715 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
716 record->rrdata.len);
717 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
718 }
719 } else if (record->rrtype == 47) {
720 ret = snprintf(buf->cp, brem, "\"dnsHashData\":\"");
721 MD_CHECK_RET(buf, ret, brem);
722 mdJsonifyEscapeChars(buf, &brem, record->rrdata.buf,
723 record->rrdata.len);
724 if (base64) {
725 encode = TRUE;
726 } else {
727 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
728 }
729 } else {
730 /* if we found no rrData then we need to snip the trailing comma from
731 * the previous field.
732 */
733 buf->cp -= 1;
734 brem += 1;
735 }
736
737 if (base64 && encode) {
738 base1 = g_base64_encode((const guchar *)record->rrdata.buf,
739 record->rrdata.len-1);
740 ret = snprintf(buf->cp, brem, "%s\"", base1);
741 MD_CHECK_RET0(buf, ret, brem);
742 g_free(base1);
743 }
744
745 if (record->mapname.len) {
746 MD_APPEND_CHAR_CHECK(brem, buf, ',');
747 ret = snprintf(buf->cp, brem, "\"observationDomainName\":\"");
748 MD_CHECK_RET0(buf, ret, brem);
749 if (!md_util_append_varfield(buf, &brem, &(record->mapname))) {
750 return 0;
751 }
752 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
753 }
754
755 if (brem > 3) {
756 MD_APPEND_CHAR(buf, '}');
757 MD_APPEND_CHAR(buf, '}');
758 MD_APPEND_CHAR(buf, '\n');
759 } else { return 0; }
760
761 rc = md_util_write_buffer(fp, buf, "", err);
762
763 if (!rc) {
764 return -1;
765 }
766
767 return rc;
768 }
769
mdJsonifySSLDedupRecord(FILE * fp,mdBuf_t * buf,uint8_t * rec,GError ** err)770 int mdJsonifySSLDedupRecord(
771 FILE *fp,
772 mdBuf_t *buf,
773 uint8_t *rec,
774 GError **err)
775 {
776
777 size_t rc = 0;
778 size_t brem = MD_REM_MSG(buf);
779 int ret;
780 md_ssl_t *ssl = (md_ssl_t *)rec;
781 uint64_t start_secs = ssl->flowStartMilliseconds / 1000;
782 uint32_t start_rem = ssl->flowStartMilliseconds % 1000;
783 uint64_t end_secs = ssl->flowEndMilliseconds / 1000;
784 uint32_t end_rem = ssl->flowEndMilliseconds % 1000;
785
786 ret = snprintf(buf->cp, brem, "{\"ssl\":{\"firstSeen\":\"");
787 MD_CHECK_RET0(buf, ret, brem);
788
789 if (!md_util_time_buf_append(buf, &brem, start_secs, PRINT_TIME_FMT)) {
790 return 0;
791 }
792 ret = snprintf(buf->cp, brem, ".%03u\",\"lastSeen\":\"", start_rem);
793 MD_CHECK_RET0(buf, ret, brem);
794
795 if (!md_util_time_buf_append(buf, &brem, end_secs, PRINT_TIME_FMT)) {
796 return 0;
797 }
798
799 ret = snprintf(buf->cp, brem, ".%03u\",\"sslCertSerialNumber\":\"",
800 end_rem);
801 MD_CHECK_RET0(buf, ret, brem);
802
803 ret = md_util_hexdump_append_nospace(buf->cp, &brem,
804 ssl->sslCertSerialNumber.buf, ssl->sslCertSerialNumber.len);
805 if (!ret) {
806 return 0;
807 }
808 buf->cp += ret;
809
810 if (ssl->mapname.len) {
811 ret = snprintf(buf->cp, brem, "\",\"observationDomainName\":\"");
812 MD_CHECK_RET0(buf, ret, brem);
813 if (!md_util_append_varfield(buf, &brem, &(ssl->mapname))) {
814 return 0;
815 }
816 }
817
818 ret = snprintf(buf->cp, brem, "\",\"observedDataTotalCount\":%"PRIu64
819 ",\"sslCertIssuerCommonName\":\"", ssl->observedDataTotalCount);
820 MD_CHECK_RET0(buf, ret, brem);
821
822 if (!md_util_append_varfield(buf, &brem, &(ssl->sslCertIssuerCommonName))) {
823 return 0;
824 }
825
826 ret = snprintf(buf->cp, brem, "\"}}\n");
827
828 MD_CHECK_RET0(buf, ret, brem);
829
830 rc = md_util_write_buffer(fp, buf, "", err);
831
832 if (!rc) {
833 return -1;
834 }
835
836 return rc;
837 }
838
mdJsonifyDedupRecord(FILE * fp,mdBuf_t * buf,char * prefix,md_dedup_t * rec,GError ** err)839 int mdJsonifyDedupRecord(
840 FILE *fp,
841 mdBuf_t *buf,
842 char *prefix,
843 md_dedup_t *rec,
844 GError **err)
845 {
846
847 size_t rc = 0;
848 size_t brem = MD_REM_MSG(buf);
849 uint64_t start_secs = rec->monitoringIntervalStartMilliSeconds / 1000;
850 uint32_t start_rem = rec->monitoringIntervalStartMilliSeconds % 1000;
851 uint64_t end_secs = rec->monitoringIntervalEndMilliSeconds / 1000;
852 uint32_t end_rem = rec->monitoringIntervalEndMilliSeconds % 1000;
853 uint64_t flow_secs = rec->flowStartMilliseconds / 1000;
854 uint32_t flow_rem = rec->flowStartMilliseconds % 1000;
855 char sabuf[40];
856 int ret;
857
858
859
860 ret = snprintf(buf->cp, brem, "{\"dedup\":{\"firstSeen\":\"");
861 MD_CHECK_RET0(buf, ret, brem);
862
863 if (!md_util_time_buf_append(buf, &brem, start_secs, PRINT_TIME_FMT)) {
864 return 0;
865 }
866 ret = snprintf(buf->cp, brem, ".%03u\",\"lastSeen\":\"", start_rem);
867 MD_CHECK_RET0(buf, ret, brem);
868
869 if (!md_util_time_buf_append(buf, &brem, end_secs, PRINT_TIME_FMT)) {
870 return 0;
871 }
872
873 if (rec->sourceIPv4Address != rec->yafFlowKeyHash) {
874 if (rec->sourceIPv4Address == 0) {
875 ret = snprintf(buf->cp, brem, ".%03u\",\"sourceIPv6Address\":\"",
876 end_rem);
877 MD_CHECK_RET0(buf, ret, brem);
878 md_util_print_ip6_addr(sabuf, rec->sourceIPv6Address);
879 } else {
880 ret = snprintf(buf->cp, brem, ".%03u\",\"sourceIPv4Address\":\"",
881 end_rem);
882 MD_CHECK_RET0(buf, ret, brem);
883 md_util_print_ip4_addr(sabuf, rec->sourceIPv4Address);
884 }
885 ret = snprintf(buf->cp, brem, "%s\",\"yafFlowKeyHash\":%u,"
886 "\"observedDataTotalCount\":%"PRIu64",",
887 sabuf, rec->yafFlowKeyHash, rec->observedDataTotalCount);
888 } else {
889 /* deduped on hash, not IP so don't print IP */
890 ret = snprintf(buf->cp, brem, ".%03u\",\"yafFlowKeyHash\":%u,"
891 "\"observedDataTotalCount\":%"PRIu64",",
892 end_rem, rec->yafFlowKeyHash, rec->observedDataTotalCount);
893 }
894
895 MD_CHECK_RET0(buf, ret, brem);
896
897 /* flow's start time */
898 ret = snprintf(buf->cp, brem, "\"flowStartMilliseconds\":\"");
899 MD_CHECK_RET0(buf, ret, brem);
900
901 if (!md_util_time_buf_append(buf, &brem, flow_secs, PRINT_TIME_FMT)) {
902 return 0;
903 }
904
905 ret = snprintf(buf->cp, brem, ".%03u\",", flow_rem);
906 MD_CHECK_RET0(buf, ret, brem);
907
908
909 if (rec->mapname.len) {
910 ret = snprintf(buf->cp, brem, "\"observationDomainName\":\"");
911 MD_CHECK_RET0(buf, ret, brem);
912 if (!md_util_append_varfield(buf, &brem, &(rec->mapname))) {
913 return 0;
914 }
915 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
916 MD_APPEND_CHAR_CHECK(brem, buf, ',');
917 }
918
919
920 if (rec->observedData.len) {
921 ret = snprintf(buf->cp, brem, "\"%s\":\"", prefix);
922 MD_CHECK_RET0(buf, ret, brem);
923 if (!md_util_append_varfield(buf, &brem, &(rec->observedData))) {
924 return 0;
925 }
926 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
927 } else if (rec->sslCertSerialNumber1.len) {
928 ret = snprintf(buf->cp, brem, "\"sslCertificateChain\":[{\""
929 "sslCertSerialNumber\":\"");
930 MD_CHECK_RET0(buf, ret, brem);
931 ret = md_util_hexdump_append_nospace(buf->cp, &brem, rec->sslCertSerialNumber1.buf,
932 rec->sslCertSerialNumber1.len);
933 if (!ret) {
934 return 0;
935 }
936 buf->cp += ret;
937 ret = snprintf(buf->cp, brem, "\", \"sslCertIssuerCommonName\":\"");
938 MD_CHECK_RET0(buf, ret, brem);
939 if (!md_util_append_varfield(buf, &brem, &(rec->sslCertIssuerCommonName1))) {
940 return 0;
941 }
942 MD_APPEND_CHAR_CHECK(brem, buf, '\"');
943 MD_APPEND_CHAR_CHECK(brem, buf, '}');
944 if (rec->sslCertSerialNumber2.len) {
945 ret = snprintf(buf->cp, brem, ",{\"sslCertSerialNumber\":\"");
946 MD_CHECK_RET0(buf, ret, brem);
947 ret = md_util_hexdump_append_nospace(buf->cp, &brem,
948 rec->sslCertSerialNumber2.buf,
949 rec->sslCertSerialNumber2.len);
950 if (!ret) {
951 return 0;
952 }
953 buf->cp += ret;
954 ret = snprintf(buf->cp, brem, "\", \"sslCertIssuerCommonName\":\"");
955 MD_CHECK_RET0(buf, ret, brem);
956 if (!md_util_append_varfield(buf, &brem, &(rec->sslCertIssuerCommonName2))) {
957 return 0;
958 }
959 ret = snprintf(buf->cp, brem, "\"}]");
960 MD_CHECK_RET0(buf, ret, brem);
961 } else {
962 MD_APPEND_CHAR_CHECK(brem, buf, ']');
963 }
964 }
965
966 ret = snprintf(buf->cp, brem, "}}\n");
967 MD_CHECK_RET0(buf, ret, brem);
968
969 rc = md_util_write_buffer(fp, buf, "", err);
970
971 if (!rc) {
972 return -1;
973 }
974
975 return rc;
976 }
977
mdJsonifySSLCertBase64(mdBuf_t * buf,fbVarfield_t * cert)978 gboolean mdJsonifySSLCertBase64(
979 mdBuf_t *buf,
980 fbVarfield_t *cert)
981 {
982 size_t brem = MD_REM_MSG(buf);
983 gchar *base1 = NULL;
984 int ret;
985
986 /* remove '},' */
987 buf->cp -= 2;
988 brem += 2;
989
990 base1 = g_base64_encode((const guchar *)cert->buf,
991 cert->len);
992
993 ret = snprintf(buf->cp, brem, ",\"sslCertificate\":\"%s\"},", base1);
994 MD_CHECK_RET0(buf, ret, brem);
995
996 if (base1) {
997 g_free(base1);
998 }
999
1000 return TRUE;
1001 }
1002