Beispiel #1
0
void
test_base64 (void)
{
  base64_encodestate encode;
  base64_decodestate decode;
  char b64dig[64];
  char buf[64];
  int size1, size2;
  int ret;

  TEST(("test base64 encoding"));
  base64_init_encodestate(&encode);
  size1 = base64_encode_block("foo", 3, b64dig, &encode);
  size2 = base64_encode_blockend(&b64dig[size1], &encode);
  b64dig[size1 + size2 - 1] = '\0';

  printf("b64 encode: %s, expected: Zm9v\n", b64dig);
  ret = strcmp(b64dig, "Zm9v");
  assert(ret == 0);

  TEST(("test base64 decoding"));
  base64_init_decodestate(&decode);
  base64_decode_block ("YmxhaG9uZ2E=", 12, buf, &decode);

  printf("b64 decode: %s, expexted: blahonga\n", buf);
  ret = strcmp(buf, "blahonga");
  assert(ret == 0);
}
Beispiel #2
0
static u2fs_rc
parse_signatureData(const char *signatureData, uint8_t * user_presence,
                    uint32_t * counter, u2fs_ECDSA_t ** signature)
{

  base64_decodestate b64;
  size_t signatureData_len = strlen(signatureData);
  unsigned char *data;
  int data_len;
  u2fs_rc rc;

  data = malloc(signatureData_len + 1);
  if (data == NULL)
    return U2FS_MEMORY_ERROR;

  data[signatureData_len] = '\0';

  base64_init_decodestate(&b64);
  data_len =
      base64_decode_block(signatureData, signatureData_len, (char *) data,
                          &b64);

  if (debug) {
    fprintf(stderr, "signatureData Hex: ");
    dumpHex((unsigned char *) data, 0, data_len);
  }

  rc = parse_signatureData2(data, data_len, user_presence, counter,
                            signature);

  free(data);
  data = NULL;

  return rc;
}
Beispiel #3
0
static u2fs_rc decode_clientData(const char *clientData, char **output)
{
  base64_decodestate b64;
  size_t clientData_len = strlen(clientData);
  char *data;
  u2fs_rc rc = 0;

  if (output == NULL)
    return U2FS_MEMORY_ERROR;

  data = calloc(sizeof(char), clientData_len);
  if (data == NULL)
    return U2FS_MEMORY_ERROR;

  base64_init_decodestate(&b64);
  base64_decode_block(clientData, clientData_len, data, &b64);

  if (debug) {
    fprintf(stderr, "clientData: %s\n", data);
  }

  *output = strndup(data, strlen(data));

  free(data);
  data = NULL;

  if (*output == NULL) {
    fprintf(stderr, "Memory Error\n");
    return U2FS_MEMORY_ERROR;
  }

  return rc;
}
char* decode(const char* input)
{
	/* set up a destination buffer large enough to hold the encoded data */
	char* output = (char*)malloc(SIZE);
	/* keep track of our decoded position */
	char* c = output;
	/* store the number of bytes decoded by a single call */
	int cnt = 0;
	/* we need a decoder state */
	base64_decodestate s;
	
	/*---------- START DECODING ----------*/
	/* initialise the decoder state */
	base64_init_decodestate(&s);
	/* decode the input data */
	cnt = base64_decode_block(input, strlen(input), c, &s);
	c += cnt;
	/* note: there is no base64_decode_blockend! */
	/*---------- STOP DECODING  ----------*/
	
	/* we want to print the decoded data, so null-terminate it: */
	*c = 0;
	
	return output;
}
Beispiel #5
0
//============================================================================
//		NDataEncoder::B64_Decode : Decode from Base64.
//----------------------------------------------------------------------------
NData NDataEncoder::B64_Decode(const NString &theValue)
{	NData					theData, valueData;
	base64_decodestate		theState;
	char					*dataPtr;
	NIndex					dataSize;



	// Get the state we need
	base64_init_decodestate(&theState);

	valueData = theValue.GetData(kNStringEncodingUTF8);
	
	if (!theData.SetSize(valueData.GetSize()))
		return(theData);



	// Decode the value
	dataPtr  = (char *) theData.GetData();
	dataSize = base64_decode_block((const char *) valueData.GetData(), valueData.GetSize(), dataPtr, &theState);

	theData.SetSize(dataSize);

	return(theData);
}
Beispiel #6
0
size_t
b64_decode( const char* in, size_t insize, char* out )
{
  base64_decodestate state;
  base64_init_decodestate( &state );
  return base64_decode_block( in, insize, out, &state );
}
Beispiel #7
0
UA_Int32 UA_base64_decode(UA_String* const base64EncodedData, UA_Byte* target){
	if(target == UA_NULL){
		return UA_ERROR;
	}
	base64_decodestate state;
	base64_init_decodestate(&state);
	base64_decode_block((char*)(base64EncodedData->data), base64EncodedData->length, (char*)target, &state);
	return UA_NO_ERROR;
}
Beispiel #8
0
int
base64_decode(const char *in_base64, int in_len,
	      char *out_bin, int out_len)
{
	struct base64_decodestate state;
	base64_decodestate_init(&state);
	return base64_decode_block(in_base64, in_len,
				   out_bin, out_len, &state);
}
static char* base64_decode_block_decodes_4_chars()
{
    uint8_t output[4] = { 0 };

    base64_decode_block("TWFu", output);
    mu_assert("Decoding", compare_string("Man", (char*) output, 3));

    return 0;
}
Beispiel #10
0
 Buffer fromBase64(const void *input, size_t inputSize)
 {
     size_t outputSize = inputSize / 4 * 3;
     Buffer result = Buffer(outputSize);
     
     if (inputSize >= 4)
     {
         base64_decodestate state;
         base64_init_decodestate(&state);
         int actualSize = base64_decode_block(reinterpret_cast<const char*>(input), inputSize, (char*)result.getData(), &state);
         result.setDataSize(actualSize);
     }
     
     return result;
 }
Beispiel #11
0
char*
_plb64decode(char* idat, unsigned int ilen, unsigned int* olen) {
	unsigned int binsz;
	char* odat;
	base64_decodestate b64state;
	
	if (idat == NULL || ilen == 0) { return NULL; }
	// to simplify, we'll allocate the same size, although smaller size is needed
	odat = _plzalloc(ilen);
	if (odat == NULL) { return NULL; }
	base64_init_decodestate(&b64state);
	binsz = base64_decode_block(idat, (const int)ilen, odat, &b64state);
	if (olen != NULL) { *olen = binsz; }
	return odat;
}
Beispiel #12
0
/**
 * Parse a (possibly base64 encoded) payload and set it on
 * the `req`.
 *
 * It is assumed that the `parser` has just encountered a
 * YAML_SCALAR_EVENT whose value was either "payload" or
 * "payload64", and the next event will be a YAML_SCALAR_EVENT
 * representing the payload itself.
 *
 * Return 1 on error or 0 on success.
 */
int parse_payload(yaml_parser_t* parser, yaml_event_t* event, request* req)
{
    char* payload;
    unsigned long rawlength;
    yaml_event_t payload_event;
    if (!yaml_parser_parse(parser, &payload_event))
        return 1;

    payload = (char *)payload_event.data.scalar.value;
    // printf("raw payload: '%s'\n", payload_event.data.scalar.value);
    rawlength = strlen(payload);

    if (0 == strncmp("payload64", (const char*)event->data.scalar.value, 9)) {
        unsigned long payload_length;

        if (rawlength < 0 || rawlength % 4 != 0) {
            fprintf(stderr, "base64-encoded POST payload length must be a positive multiple of 4 (was %lu)", rawlength);
            yaml_event_delete(&payload_event);
            return 1;
        }

        payload_length = rawlength / 4 * 3;
        if (payload[rawlength - 1] == '=')
            payload_length--;
        if (payload[rawlength - 2] == '=')
            payload_length--;

        if (!(req->payload = malloc(sizeof(char) * (payload_length + 1)))) {
            yaml_event_delete(&payload_event);
            return 1;
        }
        req->payload[payload_length] = '\0';

        base64_decodestate state;
        base64_init_decodestate(&state);
        base64_decode_block((const char*)payload_event.data.scalar.value, rawlength, req->payload, &state);
        req->payload_length = payload_length;
    } else {
        if (!(req->payload = malloc(sizeof(char) * (rawlength + 1)))) {
            yaml_event_delete(&payload_event);
            return 1;
        }
        strcpy(req->payload, (const char*)payload_event.data.scalar.value);
        req->payload_length = rawlength;
    }

    return 0;
}
Beispiel #13
0
int CCCrypto::decodeBase64(const char* input,
                           void* output,
                           int outputBufferLength)
{
    int bufferSize = strlen(input) + 1;
    char* buffer = (char*)malloc(bufferSize);
    memset(buffer, 0, bufferSize);
    base64_decodestate state;
    base64_init_decodestate(&state);
    int r1 = base64_decode_block(input, bufferSize - 1, buffer, &state);
    
    memset(output, 0, outputBufferLength);
    int cp = r1 < outputBufferLength ? r1 : outputBufferLength - 1;
    memcpy(output, buffer, cp);
    free(buffer);
    return cp;
}
Beispiel #14
0
unsigned char *
shotgun_base64_decode(const char *string, int len, size_t *size)
{
   base64_decodestate s;
   unsigned char *ret = NULL;
   int retlen;

   if ((len < 1) || (!string)) return NULL;

   if (!(ret = malloc(sizeof(char) * (int)((double)len / (double)(4 / 3)))))
     return NULL;
   base64_init_decodestate(&s);
   retlen = base64_decode_block((char*)string, len, ret, &s);
   *size = retlen;

   return ret;
}
Beispiel #15
0
static u2fs_rc parse_registrationData(const char *registrationData,
                                      unsigned char **user_public_key,
                                      size_t * keyHandle_len,
                                      char **keyHandle,
                                      u2fs_X509_t **
                                      attestation_certificate,
                                      u2fs_ECDSA_t ** signature)
{
  base64_decodestate b64;
  size_t registrationData_len = strlen(registrationData);
  unsigned char *data;
  int data_len;
  u2fs_rc rc;

  data = malloc(registrationData_len + 1);
  if (data == NULL)
    return U2FS_MEMORY_ERROR;

  data[registrationData_len] = '\0';

  base64_init_decodestate(&b64);
  data_len =
      base64_decode_block(registrationData, registrationData_len,
                          (char *) data, &b64);

  if (debug) {
    fprintf(stderr, "registrationData Hex: ");
    dumpHex((unsigned char *) data, 0, data_len);
  }

  rc = parse_registrationData2(data, data_len,
                               user_public_key, keyHandle_len, keyHandle,
                               attestation_certificate, signature);

  free(data);
  data = NULL;

  return rc;
}
Beispiel #16
0
int zio_json_decode (const char *json_str, void **pp, bool *eofp)
{
    json_t *o = NULL;
    const char *s_data;
    int s_len, len = 0;
    void *data = NULL;
    int eof = 0;

    if (!json_str || !(o = json_loads (json_str, 0, NULL))
                  || json_unpack (o, "{s:b s:s}", "eof", &eof,
                                                  "data", &s_data) < 0) {
        errno = EPROTO;
        goto error;
    }
    if (pp) {
        s_len = strlen (s_data);
        len = base64_decode_length (s_len);
        data = calloc (1, len);
        if (!data) {
            errno = ENOMEM;
            goto error;
        }
        if (base64_decode_block (data, &len, s_data, s_len) < 0) {
            errno = EPROTO;
            goto error;
        }
        *pp = data;
    }
    if (eofp) {
        *eofp = eof;
    }
    json_decref (o);
    return len;
error:
    json_decref (o);
    free (data);
    return -1;
}
Beispiel #17
0
int base64_json_decode (json_object *o, uint8_t **datp, int *lenp)
{
    const char *s;
    int dlen, len;
    void *dst;

    if (!o || json_object_get_type (o) != json_type_string) {
        errno = EINVAL;
        return -1;
    }
    s = json_object_get_string (o);
    len = strlen (s);
    dst = xzmalloc (base64_decode_length (len));
    if (base64_decode_block (dst, &dlen, s, len) < 0) {
        free (dst);
        errno = EINVAL;
        return -1;
    }

    *lenp = dlen;
    *datp = (uint8_t *) dst;
    return 0;
}
Beispiel #18
0
/**
 * u2fh_authenticate:
 * @devs: a device handle, from u2fh_devs_init() and u2fh_devs_discover().
 * @challenge: string with JSON data containing the challenge.
 * @origin: U2F origin URL.
 * @response: pointer to output string with JSON data.
 * @flags: set of ORed #u2fh_cmdflags values.
 *
 * Perform the U2F Authenticate operation.
 *
 * Returns: On success %U2FH_OK (integer 0) is returned, and on errors
 * an #u2fh_rc error code.
 */
u2fh_rc
u2fh_authenticate (u2fh_devs * devs,
		   const char *challenge,
		   const char *origin, char **response, u2fh_cmdflags flags)
{
  unsigned char data[CHALLBINLEN + HOSIZE + MAXKHLEN + 1];
  unsigned char buf[MAXDATASIZE];
  char bd[2048];
  size_t bdlen = sizeof (bd);
  size_t len;
  int rc;
  char chalb64[256];
  size_t challen = sizeof (chalb64);
  char khb64[256];
  size_t kh64len = sizeof (khb64);
  base64_decodestate b64;
  size_t khlen;
  int skip_devices[devs->num_devices];
  int skipped = 0;
  int iterations = 0;

  memset (skip_devices, 0, sizeof (skip_devices));

  rc = get_fixed_json_data (challenge, "challenge", chalb64, &challen);
  if (rc != U2FH_OK)
    return rc;

  rc = prepare_browserdata (chalb64, origin, AUTHENTICATE_TYP, bd, &bdlen);
  if (rc != U2FH_OK)
    return rc;

  sha256_buffer (bd, bdlen, data);

  prepare_origin (challenge, data + CHALLBINLEN);

  /* confusion between key_handle and keyHandle */
  rc = get_fixed_json_data (challenge, "keyHandle", khb64, &kh64len);
  if (rc != U2FH_OK)
    return rc;

  base64_init_decodestate (&b64);
  khlen = base64_decode_block (khb64, kh64len,
			       data + HOSIZE + CHALLBINLEN + 1, &b64);
  data[HOSIZE + CHALLBINLEN] = khlen;

  /* FIXME: Support asynchronous usage, through a new u2fh_cmdflags
     flag. */

  do
    {
      int i;
      if (iterations++ > 15)
	{
	  return U2FH_TIMEOUT_ERROR;
	}
      for (i = 0; i < devs->num_devices; i++)
	{
	  unsigned char tmp_buf[MAXDATASIZE];
	  if (skip_devices[i] != 0)
	    {
	      continue;
	    }
	  if (!devs->devs[i].is_alive)
	    {
	      skipped++;
	      skip_devices[i] = 1;
	      continue;
	    }
	  len = MAXDATASIZE;
	  rc = send_apdu (devs, i, U2F_AUTHENTICATE, data,
			  HOSIZE + CHALLBINLEN + khlen + 1,
			  flags & U2FH_REQUEST_USER_PRESENCE ? 3 : 7, tmp_buf,
			  &len);
	  if (rc != U2FH_OK)
	    {
	      return rc;
	    }
	  else if (len != 2)
	    {
	      memcpy (buf, tmp_buf, len);
	      break;
	    }
	  else if (memcmp (tmp_buf, NOTSATISFIED, 2) != 0)
	    {
	      skipped++;
	      skip_devices[i] = 2;
	      continue;
	    }
	  memcpy (buf, tmp_buf, len);
	}
      if (len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0)
	{
	  Sleep (1000);
	}
    }
  while ((flags & U2FH_REQUEST_USER_PRESENCE)
	 && len == 2 && memcmp (buf, NOTSATISFIED, 2) == 0);

  if (len == 2 && memcmp (buf, NOTSATISFIED, 2) != 0)
    {
      return U2FH_AUTHENTICATOR_ERROR;
    }
  if (len != 2)
    {
      prepare_response (buf, len - 2, bd, challenge, response);
    }

  return U2FH_OK;
}
Beispiel #19
0
int
decode_block (unsigned char *dst, int *dstlen,
              const unsigned char *src, int srclen)
{
    return (base64_decode_block (dst, dstlen, src, srclen));
}
Beispiel #20
0
void decode(const char* buf, char* out, size_t s)
{
	base64_decodestate state;
	base64_init_decodestate(&state);
	base64_decode_block(buf, s, out, &state);
}
STATIC UByte PancakeHTTPBasicAuthenticate(PancakeSocket *sock) {
	// Check whether authentication framework is active
	if(PancakeAuthenticationActiveConfiguration) {
		PancakeHTTPRequest *request = (PancakeHTTPRequest*) sock->data;
		PancakeHTTPHeader *header;

		// Check credentials provided by client
		if(request->authorization.length > 6) {
			UByte *authorization = sock->readBuffer.value + request->authorization.offset;

			if(!memcmp(authorization, "Basic ", 6)) {
				UByte decoded[request->authorization.length - 6], *ptr;
				base64_decodestate state = {0};
				PancakeAuthenticationUserPassword client;
				UInt32 length;

				// Decode base64 user and password
				length = base64_decode_block(authorization + 6, request->authorization.length - 6, decoded, &state);
				ptr = memchr(decoded, ':', length);

				if(ptr != NULL) {
					client.user.value = decoded;
					client.user.length = ptr - decoded;

					if(ptr - decoded < length) {
						client.password.value = ptr + 1;
						client.password.length = decoded + length - (ptr + 1);
					} else {
						client.password.value = "";
						client.password.length = 0;
					}

					// Try authentication
					if(PancakeAuthenticate(PancakeAuthenticationActiveConfiguration, &client)) {
						return 1;
					}
				}
			}
		}

		// Build WWW-Authenticate header
		header = PancakeAllocate(sizeof(PancakeHTTPHeader));
		header->name.value = PancakeAllocate(sizeof("WWW-Authenticate") - 1);
		header->name.length = sizeof("WWW-Authenticate") - 1;
		memcpy(header->name.value, "WWW-Authenticate", sizeof("WWW-Authenticate") - 1);

		if(activeRealm) {
			header->value.length = sizeof("Basic realm=\"\"") - 1 + activeRealm->length;
			header->value.value = PancakeAllocate(header->value.length);
			memcpy(header->value.value + 5, " realm=\"", sizeof(" realm=\"") - 1);
			memcpy(header->value.value + 5 + sizeof(" realm=\"") - 1, activeRealm->value, activeRealm->length);
			header->value.value[header->value.length - 1] = '"';
		} else {
			header->value.length = sizeof("Basic") - 1;
			header->value.value = PancakeAllocate(sizeof("Basic") - 1);
		}

		memcpy(header->value.value, "Basic", 5);

		LL_APPEND(request->answerHeaders, header);

		// Throw 401 Unauthorized
		PancakeHTTPException(sock, 401);
		return 0;
	}

	return 1;
}
Beispiel #22
0
		int decode(const char* code_in, const int length_in, char* plaintext_out)
		{
			return base64_decode_block(code_in, length_in, plaintext_out, &_state);
		}
Beispiel #23
0
int decode_armor(const uint8_t *armor_in, uint32_t armor_len, uint8_t **plain_out,
                 uint32_t *plain_len)
{
    int ret = -EINVAL;
    const uint8_t *armor_start, *crc_start;
    uint8_t *pgp_plain, *pgp_realloced;
    uint32_t actual_crc24, expected_crc24, crc_plain;
    uint32_t i, encoded_armor_len, plain_armor_len;
    base64_decodestate state;

    /* (6.2) ASCII armor shall be the concatenation of the following data:
      - armor header line
      - armor headers
      - a blank (zero-length, newline only) line
      - the ascii armored data
      - the armor checksum
      - the armor tail */

    /* find the start of the armor */
    i = 1;
    while(i++ < armor_len-1) {
        /* test for both unix style endings and windows style */
        if(armor_in[i-1] == '\n' && armor_in[i] == '\n')
            break;
        else if(i >= 3) {
            if((armor_in[i-3] == '\r' && armor_in[i-2] == '\n' &&
                armor_in[i-1] == '\r' && armor_in[i] == '\n'))
                break;
        }
    }
    /* did we find it? */
    if(i == armor_len)
        goto exit;

    armor_start = armor_in + i;

    /* find the armor checksum and encrypted packet length */
    i = armor_len;
    while(--i) {
        if(armor_in[i] == '=')
            break;
    }
    /* did we find it? */
    if(!i)
        goto exit;

    crc_start = armor_in + i;
    encoded_armor_len = crc_start - armor_start;

    /* do we have enough data for the CRC too?
       CRC is 5 characters long ('=' and CRC) - 3 octets - 24 bits */
    if(encoded_armor_len + 5 > armor_len)
        goto exit;

    /* allocate buffers for plaintext (this is slightly bigger
       than strictly necessary, but will be realloc'ed) */
    pgp_plain = malloc(encoded_armor_len);
    if(!pgp_plain) {
        ret = -ENOMEM;
        goto exit;
    }

    /* decode the data */
    base64_init_decodestate(&state);
    plain_armor_len = base64_decode_block((char*)armor_start, encoded_armor_len, (char*)pgp_plain, &state);

    /* give back the memory we don't need, note that realloc is not responsible for cleaning up
       the original malloc'ed memory if it fails, so we need to keep the original pointer for cleaning
       purposes in case realloc fails (by returning NULL). */
    pgp_realloced = realloc(pgp_plain, plain_armor_len);
    if(!pgp_realloced)
        goto free_pgp;

    pgp_plain = pgp_realloced;

    actual_crc24 = pgp_crc24(plain_armor_len, pgp_plain);

    /* decode the CRC */
    base64_init_decodestate(&state);
    /* ignore '='... */
    base64_decode_block((char*)crc_start + 1, 4, (char*)&crc_plain, &state);

    expected_crc24 = (crc_plain & 0xff0000) >> 16 |
                       (crc_plain & 0x0000ff) << 16 |
                       (crc_plain & 0x00ff00);

    if(actual_crc24 != expected_crc24)
        goto free_pgp;

    *plain_out = pgp_plain;
    *plain_len = plain_armor_len;

    return 0;

free_pgp:
    free(pgp_plain);
exit:
    return ret;
}
Beispiel #24
0
int
decode_block (char *dst, int *dstlen, const void *src, int srclen)
{
    return (base64_decode_block (dst, dstlen, src, srclen));
}
Beispiel #25
0
wdns_res
_wdns_str_to_rdata_ubuf(ubuf *u, const char *str,
			uint16_t rrtype, uint16_t rrclass) {
	wdns_res res;
	const record_descr *descr = NULL;
	size_t u_orig_size = ubuf_size(u);

	if (rrtype < record_descr_len)
		descr = &record_descr_array[rrtype];

	if (rrtype >= record_descr_len ||
	    (descr != NULL && descr->types[0] == rdf_unknown))
	{
		/* generic encoding */

		if (strncmp(str, "\\#", 2)) {
			res = wdns_res_parse_error;
			goto err;
		}
		str += 2;
		if (!isspace(*str)) {
			res = wdns_res_parse_error;
			goto err;
		}
		while (*str && isspace(*str)) {
			str++;
		}

		const char * ptr = str;
		while (*ptr && !isspace(*ptr)) {
			if (!isdigit(*ptr)) {
				res = wdns_res_parse_error;
				goto err;
			}
			ptr++;
		}

		uint16_t rdlen;
		if (sscanf(str, "%hu", &rdlen) == 0) {
			res = wdns_res_parse_error;
			goto err;
		}
		str = ptr;

		size_t len = 0;
		while (*str) {
			uint8_t c;

			if (isspace(*str)) {
				str++;
				continue;
			}

			if (*(str+1) == 0) {
				res = wdns_res_parse_error;
				goto err;
			}
			if (!sscanf(str, "%02hhx", &c)) {
				res = wdns_res_parse_error;
				goto err;
			}
			ubuf_append(u, &c, 1);
			len++;
			str += 2;
		}
		if (len != rdlen) {
			res = wdns_res_parse_error;
			goto err;
		}

		return (wdns_res_success);
	} else if (descr != NULL && !(descr->record_class == class_un ||
				      descr->record_class == rrclass))
	{
		return (wdns_res_success);
	}

	for (const uint8_t *t = &descr->types[0]; *t != rdf_end; t++) {
		if (str == NULL) {
			break;
		}

		while (isspace(*str)) {
			str++;
		}

		if (*str == 0) {
			break;
		}

		switch (*t) {
		case rdf_name:
		case rdf_uname: {
			wdns_name_t *name;
			char * s;
			const char *end = strpbrk(str, " \t\r\n");

			if (end != NULL) {
				s = strndup(str, end-str);
			} else {
				s = strdup(str);
			}
			name = calloc(1, sizeof(*name));

			res = wdns_str_to_name(s, name);
			if (res != wdns_res_success) {
				free(s);
				free(name);
				goto err;
			}

			ubuf_append(u, name->data, name->len);
			str = end;

			free(s);
			if(name->data) {
				free (name->data);
			}
			free(name);

			break;
		}

		case rdf_bytes:
			while (*str) {
				uint8_t c;
				if (*(str+1) == 0) {
					res = wdns_res_parse_error;
					goto err;
				}
				if (!sscanf(str, "%02hhx", &c)) {
					res = wdns_res_parse_error;
					goto err;
				}
				ubuf_append(u, &c, 1);
				str += 2;
			}
			break;

		case rdf_bytes_b64: {
			base64_decodestate b64;
			char *buf;
			size_t str_len = strlen(str);
			size_t buf_len;

			base64_init_decodestate(&b64);
			buf = malloc(str_len+1);
			buf_len = base64_decode_block((const char *) str, str_len, buf, &b64);
			ubuf_append(u, (uint8_t *) buf, buf_len);
			free(buf);
			str += str_len;
			break;
		}

		case rdf_bytes_str: {
			size_t str_len = strlen(str);

			if (str_len >= 3 && str[0] == '"' && str[str_len - 1] == '"') {
				if (rdata_from_str_string((const uint8_t *)str, u) == 0) {
					res = wdns_res_parse_error;
					goto err;
				}
				str += str_len;
			} else {
				res = wdns_res_parse_error;
				goto err;
			}
			break;
		}

		case rdf_ipv6prefix: {
			uint8_t prefix_len;
			const char *end = strpbrk(str, " \t\r\n");
			const char *ptr = str;

			if (end == NULL) {
				end = str + strlen(str);
			}

			while (ptr < end) {
				if (!isdigit(*ptr++)) {
					res = wdns_res_parse_error;
					goto err;
				}
			}

			if (sscanf(str, "%hhu", &prefix_len) == 0) {
				res = wdns_res_parse_error;
				goto err;
			}

			if (prefix_len > 128) {
				res = wdns_res_parse_error;
				goto err;
			}

			ubuf_append(u, &prefix_len, sizeof(prefix_len));

			str = end;
			if (str) {
				while (isspace(*str)) {
					str++;
				}
			}

			if (prefix_len > 0) {
				if (str == NULL || *str == 0) {
					res = wdns_res_parse_error;
					goto err;
				}

				end = strpbrk(str, " \t\r\n");

				uint8_t oclen = prefix_len / 8;
				if (prefix_len % 8 > 0) {
					oclen++;
				}

				uint8_t addr[16];
				char * pres;

				if (end != NULL) {
					pres = strndup(str, end-str);
				} else {
					pres = strdup(str);
				}

				int pton_res = inet_pton(AF_INET6, pres, addr);
				free(pres);

				if (pton_res == 1) {
					ubuf_append(u, addr, oclen);
				} else {
					res = wdns_res_parse_error;
					goto err;
				}

				str = end;
			}

			break;
		}

		case rdf_salt: {
			const char *end = strpbrk(str, " \t\r\n");
			if (end == NULL) {
				end = str + strlen(str);
			}

			if (*str == '-' && (end-str) == 1) {
				uint8_t c = 0;
				ubuf_append(u, &c, 1);
				str++;
			} else {
				if (end-str > (2*UINT8_MAX) || (end-str) % 2 == 1) {
					res = wdns_res_parse_error;
					goto err;
				}
				uint8_t oclen = (uint8_t)(end-str)/2;
				ubuf_append(u, &oclen, 1);

				while (oclen > 0) {
					uint8_t c;
					if (!sscanf(str, "%02hhx", &c)) {
						res = wdns_res_parse_error;
						goto err;
					}
					ubuf_append(u, &c, 1);
					str += 2;
					oclen--;
				}
			}
			break;
		}

		case rdf_hash: {
			char *buf;
			size_t buf_len;
			const char *end = strpbrk(str, " \t\r\n");

			if (end == NULL) {
				end = str + strlen(str);
			}

			size_t str_len = end-str;
			buf = malloc(str_len);
			buf_len = base32_decode(buf, str_len, str, str_len);

			uint8_t oclen = (uint8_t)buf_len;
			if (oclen != buf_len) {
				free(buf);
				res = wdns_res_parse_error;
				goto err;
			}
			ubuf_append(u, &oclen, 1);
			ubuf_append(u, (uint8_t *) buf, oclen);
			free(buf);
			str = end;
			break;
		}

		case rdf_int8: {
			uint64_t s_val;
			uint8_t val;
			const char *ptr = str;
			const char *end = strpbrk(str, " \t\r\n");

			if (end == NULL) {
				end = str + strlen(str);
			}

			while (ptr < end) {
				if (!isdigit(*ptr++)) {
					res = wdns_res_parse_error;
					goto err;
				}
			}

			if (sscanf(str, "%" PRIu64, &s_val)) {
				val = (uint8_t)s_val;
				if (val != s_val) {
					res = wdns_res_parse_error;
					goto err;
				}
				ubuf_append(u, &val, sizeof(val));
			}
			str = end;
			break;
		}

		case rdf_int16: {
			uint64_t s_val;
			uint16_t val;
			const char *ptr = str;
			const char *end = strpbrk(str, " \t\r\n");

			if (end == NULL) {
				end = str + strlen(str);
			}

			while (ptr < end) {
				if (!isdigit(*ptr++)) {
					res = wdns_res_parse_error;
					goto err;
				}
			}

			if (sscanf(str, "%" PRIu64, &s_val)) {
				val = (uint16_t)s_val;
				if (val != s_val) {
					res = wdns_res_parse_error;
					goto err;
				}
				val = htons(val);
				ubuf_append(u, (uint8_t*)&val, sizeof(val));
			}
			str = end;
			break;
		}

		case rdf_int32: {
			uint64_t s_val;
			uint32_t val;
			const char *ptr = str;
			const char *end = strpbrk(str, " \t\r\n");

			if (end == NULL) {
				end = str + strlen(str);
			}

			while (ptr < end) {
				if (!isdigit(*ptr++)) {
					res = wdns_res_parse_error;
					goto err;
				}
			}

			if (sscanf(str, "%" PRIu64, &s_val)) {
				val = (uint32_t)s_val;
				if (val != s_val) {
					res = wdns_res_parse_error;
					goto err;
				}
				val = htonl(val);
				ubuf_append(u, (uint8_t*)&val, sizeof(val));
			}
			str = end;
			break;
		}

		case rdf_ipv4: {
			uint8_t addr[4];
			char * pres;
			int pton_res;
			const char *end = strpbrk(str, " \t\r\n");

			if (end == NULL) {
				end = str + strlen(str);
			}

			pres = strdup(str);
			pres[end-str] = 0;
			pton_res = inet_pton(AF_INET, pres, addr);
			free(pres);

			if (pton_res == 1) {
				ubuf_append(u, addr, sizeof(addr));
			} else {
				res = wdns_res_parse_error;
				goto err;
			}

			str = end;
			break;
		}

		case rdf_ipv6: {
			uint8_t addr[16];
			char * pres;
			int pton_res;
			const char *end = strpbrk(str, " \t\r\n");

			if (end != NULL) {
				pres = strndup(str, end-str);
			} else {
				pres = strdup(str);
			}
			pton_res = inet_pton(AF_INET6, pres, addr);
			free(pres);

			if (pton_res == 1) {
				ubuf_append(u, addr, sizeof(addr));
			} else {
				res = wdns_res_parse_error;
				goto err;
			}

			str = end;
			break;
		}

		case rdf_eui48: {
			uint8_t a[6] = {0};
			int ret;

			if (strlen(str) != strlen("01-02-03-04-05-06")) {
				res = wdns_res_parse_error;
				goto err;
			}
			for (int i = 0; i < 6; i++) {
				if (!isxdigit(str[3*i]) ||
				    !isxdigit(str[3*i + 1]) ||
				    (i < 5 && str[3*i + 2] != '-'))
				{
					res = wdns_res_parse_error;
					goto err;
				}
			}
			ret = sscanf(str, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
			             &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]);
			if (ret != 6) {
				res = wdns_res_parse_error;
				goto err;
			}
			ubuf_append(u, a, 6);
			str += strlen(str);
			break;
		}

		case rdf_eui64: {
			uint8_t a[8] = {0};
			int ret;

			if (strlen(str) != strlen("01-02-03-04-05-06-07-08")) {
				res = wdns_res_parse_error;
				goto err;
			}
			for (int i = 0; i < 8; i++) {
				if (!isxdigit(str[3*i]) ||
				    !isxdigit(str[3*i + 1]) ||
				    (i < 7 && str[3*i + 2] != '-'))
					{
						res = wdns_res_parse_error;
						goto err;
					}
			}
			ret = sscanf(str, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
			             &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7]);
			if (ret != 8) {
				res = wdns_res_parse_error;
				goto err;
			}
			ubuf_append(u, a, 8);
			str += strlen(str);
			break;
		}

		case rdf_string: {
			const char * end = str;
			size_t u_oclen_offset;
			size_t str_len;
			uint8_t oclen = 0;

			u_oclen_offset = ubuf_size(u);
			ubuf_append(u, &oclen, sizeof(oclen));

			end += rdata_from_str_string((const uint8_t*)str, u);
			if (end == str) {
				res = wdns_res_parse_error;
				goto err;
			}
			str_len = ubuf_size(u) - u_oclen_offset - 1;

			oclen = (uint8_t)str_len;
			if (oclen != str_len) {
				res = wdns_res_parse_error;
				goto err;
			}
			ubuf_data(u)[u_oclen_offset] = oclen;

			str = end;
			break;
		}

		case rdf_repstring: {
			const char * end;
			size_t u_oclen_offset;
			size_t str_len;
			uint8_t oclen = 0;

			while (*str) {
				if (isspace(*str)) {
					str++;
					continue;
				}

				end = str;
				oclen = 0;

				u_oclen_offset = ubuf_size(u);
				ubuf_append(u, &oclen, sizeof(oclen));

				end += rdata_from_str_string((const uint8_t*)str, u);
				if (end == str) {
					res = wdns_res_parse_error;
					goto err;
				}
				str_len = ubuf_size(u) - u_oclen_offset - 1;

				oclen = (uint8_t)str_len;
				if (oclen != str_len) {
					res = wdns_res_parse_error;
					goto err;
				}
				ubuf_data(u)[u_oclen_offset] = oclen;

				str = end;
			}

			break;
		}

		case rdf_rrtype: {
			char * s_rrtype;
			uint16_t my_rrtype;
			const char *end = strpbrk(str, " \t\r\n");

			if (end != NULL) {
				s_rrtype = strndup(str, end-str);
			} else {
				s_rrtype = strdup(str);
			}
			my_rrtype = htons(wdns_str_to_rrtype(s_rrtype));
			free(s_rrtype);

			if (my_rrtype > 0) {
				ubuf_append(u, (const uint8_t*)&my_rrtype, sizeof(my_rrtype));
			} else {
				res = wdns_res_parse_error;
				goto err;
			}

			str = end;
			break;
		}

		case rdf_type_bitmap: {
			const char *end;
			char *s_rrtype;
			u16buf *rrtypes;
			uint16_t my_rrtype, last_rrtype;
			size_t n;
			uint8_t window_block, bitmap_len;
			uint8_t bitmap[32];

			rrtypes = u16buf_init(16);
			if (! rrtypes) {
				res = wdns_res_malloc;
				goto err;
			}

			while (str != NULL && *str) {
				if (isspace(*str)) {
					str++;
					continue;
				}

				end = strpbrk(str, " \t\r\n");
				if (end != NULL) {
					s_rrtype = strndup(str, end-str);
				} else {
					s_rrtype = strdup(str);
				}

				my_rrtype = wdns_str_to_rrtype(s_rrtype);
				free(s_rrtype);

				if (my_rrtype == 0 || (rrtype >= 128 && rrtype < 256) || rrtype == 65535) {
					u16buf_destroy(&rrtypes);
					res = wdns_res_parse_error;
					goto err;
				}

				u16buf_add(rrtypes, my_rrtype);
				str = end;
			}
			qsort(u16buf_ptr(rrtypes), u16buf_size(rrtypes), sizeof(uint16_t), cmp_u16);

			memset(bitmap, 0, sizeof(bitmap));
			window_block = 0;
			bitmap_len = 0;
			last_rrtype = 0;

			for (n = 0; n < u16buf_size(rrtypes); n++) {
				my_rrtype = u16buf_value(rrtypes, n);
				if (my_rrtype == last_rrtype) {
					continue;
				}
				last_rrtype = my_rrtype;

				uint8_t cur_window = my_rrtype / 256;

				if (cur_window != window_block) {
					ubuf_append(u, (const uint8_t*)&window_block, sizeof(window_block));
					ubuf_append(u, (const uint8_t*)&bitmap_len, sizeof(bitmap_len));
					ubuf_append(u, (const uint8_t*)bitmap, bitmap_len);
					memset(bitmap, 0, sizeof(bitmap));
					window_block = cur_window;
				}

				uint8_t offset = my_rrtype % 256;
				uint8_t byte = offset / 8;
				uint8_t bit = offset % 8;

				bitmap[byte] |= 0x80 >> bit;
				bitmap_len = 1 + byte;
			}
			ubuf_append(u, (const uint8_t*)&window_block, sizeof(window_block));
			ubuf_append(u, (const uint8_t*)&bitmap_len, sizeof(bitmap_len));
			ubuf_append(u, (const uint8_t*)bitmap, bitmap_len);

			u16buf_destroy(&rrtypes);
			break;
		}
		default: {
			res = wdns_res_failure;
			goto err;
		}
		} /* switch */
	}

	return wdns_res_success;

err:
	ubuf_clip(u, u_orig_size);
	return res;
}