230 lines
6.5 KiB
C
230 lines
6.5 KiB
C
/* tvbuff_base64.c
|
|
* Base-64 tvbuff implementation (based on real tvb)
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/tvbuff.h>
|
|
#include "proto.h"
|
|
|
|
/* Copy of glib function modified for base64uri */
|
|
|
|
static const unsigned char mime_base64uri_rank[256] = {
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255, 255,255,63,255,255,
|
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
|
|
255, 0, 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,255,255,255,255, 63,
|
|
255, 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,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
};
|
|
/**
|
|
* Copy of glib function modified for base64uri
|
|
* g_base64uri_decode_step: (skip)
|
|
* @in: (array length=len) (element-type guint8): binary input data
|
|
* @len: max length of @in data to decode
|
|
* @out: (out caller-allocates) (array) (element-type guint8): output buffer
|
|
* @state: (inout): Saved state between steps, initialize to 0
|
|
* @save: (inout): Saved state between steps, initialize to 0
|
|
*
|
|
* Incrementally decode a sequence of binary data from its Base-64 stringified
|
|
* representation. By calling this function multiple times you can convert
|
|
* data in chunks to avoid having to have the full encoded data in memory.
|
|
*
|
|
* The output buffer must be large enough to fit all the data that will
|
|
* be written to it. Since base64 encodes 3 bytes in 4 chars you need
|
|
* at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
|
|
* state).
|
|
*
|
|
* Returns: The number of bytes of output that was written
|
|
*
|
|
* Since: 2.12
|
|
**/
|
|
static gsize
|
|
g_base64uri_decode_step(const gchar* in,
|
|
gsize len,
|
|
guchar* out,
|
|
gint* state,
|
|
guint* save)
|
|
{
|
|
const guchar* inptr;
|
|
guchar* outptr;
|
|
const guchar* inend;
|
|
guchar c, rank;
|
|
guchar last[2];
|
|
unsigned int v;
|
|
int i;
|
|
|
|
g_return_val_if_fail(in != NULL || len == 0, 0);
|
|
g_return_val_if_fail(out != NULL, 0);
|
|
g_return_val_if_fail(state != NULL, 0);
|
|
g_return_val_if_fail(save != NULL, 0);
|
|
|
|
if (len == 0)
|
|
return 0;
|
|
|
|
inend = (const guchar*)in + len;
|
|
outptr = out;
|
|
|
|
/* convert 4 base64 bytes to 3 normal bytes */
|
|
v = *save;
|
|
i = *state;
|
|
|
|
last[0] = last[1] = 0;
|
|
|
|
/* we use the sign in the state to determine if we got a padding character
|
|
in the previous sequence */
|
|
if (i < 0)
|
|
{
|
|
i = -i;
|
|
last[0] = '=';
|
|
}
|
|
|
|
inptr = (const guchar*)in;
|
|
while (inptr < inend)
|
|
{
|
|
c = *inptr++;
|
|
rank = mime_base64uri_rank[c];
|
|
if (rank != 0xff)
|
|
{
|
|
last[1] = last[0];
|
|
last[0] = c;
|
|
v = (v << 6) | rank;
|
|
i++;
|
|
if (i == 4)
|
|
{
|
|
*outptr++ = v >> 16;
|
|
if (last[1] != '=')
|
|
*outptr++ = v >> 8;
|
|
if (last[0] != '=')
|
|
*outptr++ = v;
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
*save = v;
|
|
*state = last[0] == '=' ? -i : i;
|
|
|
|
return outptr - out;
|
|
}
|
|
/**
|
|
* Copy of glib function modified for base64uri
|
|
* g_base64uri_decode:
|
|
* @text: (not nullable): zero-terminated string with base64 text to decode
|
|
* @out_len: (out): The length of the decoded data is written here
|
|
*
|
|
* Decode a sequence of Base-64 encoded text into binary data. Note
|
|
* that the returned binary data is not necessarily zero-terminated,
|
|
* so it should not be used as a character string.
|
|
*
|
|
* Returns: (transfer full) (array length=out_len) (element-type guint8):
|
|
* newly allocated buffer containing the binary data
|
|
* that @text represents. The returned buffer must
|
|
* be freed with g_free().
|
|
*
|
|
* Since: 2.12
|
|
*/
|
|
static guchar*
|
|
g_base64uri_decode(const gchar* text,
|
|
gsize* out_len)
|
|
{
|
|
guchar* ret;
|
|
gsize input_length;
|
|
gint state = 0;
|
|
guint save = 0;
|
|
|
|
g_return_val_if_fail(text != NULL, NULL);
|
|
g_return_val_if_fail(out_len != NULL, NULL);
|
|
|
|
input_length = strlen(text);
|
|
|
|
/* We can use a smaller limit here, since we know the saved state is 0,
|
|
+1 used to avoid calling g_malloc0(0), and hence returning NULL */
|
|
ret = (guchar * )g_malloc0((input_length / 4) * 3 + 1);
|
|
|
|
*out_len = g_base64uri_decode_step(text, input_length, ret, &state, &save);
|
|
|
|
return ret;
|
|
}
|
|
|
|
tvbuff_t *
|
|
base64_to_tvb(tvbuff_t *parent, const char *base64)
|
|
{
|
|
tvbuff_t *tvb;
|
|
char *data;
|
|
gsize len;
|
|
|
|
data = g_base64_decode(base64, &len);
|
|
tvb = tvb_new_child_real_data(parent, (const guint8 *)data, (gint)len, (gint)len);
|
|
|
|
tvb_set_free_cb(tvb, g_free);
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t*
|
|
base64_tvb_to_new_tvb(tvbuff_t* parent, int offset, int length)
|
|
{
|
|
tvbuff_t* tvb;
|
|
char* data, *tmp;
|
|
gsize len;
|
|
|
|
tmp = tvb_get_string_enc(NULL, parent, offset, length, ENC_ASCII);
|
|
data = g_base64_decode(tmp, &len);
|
|
wmem_free(NULL, tmp);
|
|
|
|
tvb = tvb_new_child_real_data(parent, (const guint8*)data, (gint)len, (gint)len);
|
|
|
|
tvb_set_free_cb(tvb, g_free);
|
|
|
|
return tvb;
|
|
}
|
|
|
|
tvbuff_t*
|
|
base64uri_tvb_to_new_tvb(tvbuff_t* parent, int offset, int length)
|
|
{
|
|
tvbuff_t* tvb;
|
|
char* data, *tmp;
|
|
gsize len = 0;
|
|
|
|
tmp = tvb_get_string_enc(NULL, parent, offset, length, ENC_ASCII);
|
|
data = g_base64uri_decode(tmp, &len);
|
|
wmem_free(NULL, tmp);
|
|
|
|
tvb = tvb_new_child_real_data(parent, (const guint8*)data, (gint)len, (gint)len);
|
|
|
|
tvb_set_free_cb(tvb, g_free);
|
|
|
|
return tvb;
|
|
}
|
|
/*
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local Variables:
|
|
* c-basic-offset: 2
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* ex: set shiftwidth=2 tabstop=8 expandtab:
|
|
* :indentSize=2:tabSize=8:noTabs=true:
|
|
*/
|