/* convert an HPKP-style pin description to an appropriate getdns data structure. An example string is: (with the quotes, without any leading or trailing whitespace): pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" getdns_build_pin_from_string returns a dict created from ctx, or NULL if the string did not match. If ctx is NULL, the dict is created via getdns_dict_create(). It is the caller's responsibility to call getdns_dict_destroy when it is no longer needed. */ getdns_dict* getdns_pubkey_pin_create_from_string( getdns_context* context, const char* str) { BIO *bio = NULL; int i; uint8_t buf[SHA256_DIGEST_LENGTH]; char inbuf[B64_ENCODED_SHA256_LENGTH + 1]; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_dict* out = NULL; /* we only do sha256 right now, make sure this is well-formed */ if (strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH)) return NULL; for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++) if (!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') || (str[i] == '+') || (str[i] == '/'))) return NULL; if (str[i++] != '=') return NULL; if (str[i++] != '"') return NULL; if (str[i++] != '\0') return NULL; /* openssl needs a trailing newline to base64 decode */ memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH); inbuf[B64_ENCODED_SHA256_LENGTH] = '\n'; bio = BIO_push(BIO_new(BIO_f_base64()), BIO_new_mem_buf(inbuf, sizeof(inbuf))); if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf)) goto fail; if (context) out = getdns_dict_create_with_context(context); else out = getdns_dict_create(); if (out == NULL) goto fail; if (getdns_dict_set_bindata(out, "digest", &sha256)) goto fail; if (getdns_dict_set_bindata(out, "value", &value)) goto fail; return out; fail: BIO_free_all(bio); getdns_dict_destroy(out); return NULL; }
/* convert an HPKP-style pin description to an appropriate getdns data structure. An example string is: (with the quotes, without any leading or trailing whitespace): pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" getdns_build_pin_from_string returns a dict created from ctx, or NULL if the string did not match. If ctx is NULL, the dict is created via getdns_dict_create(). It is the caller's responsibility to call getdns_dict_destroy when it is no longer needed. */ getdns_dict *getdns_pubkey_pin_create_from_string( const getdns_context *context, const char *str) { size_t i; uint8_t buf[SHA256_DIGEST_LENGTH]; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_dict *out = NULL; /* we only do sha256 right now, make sure this is well-formed */ if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH)) return NULL; for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++) if (!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') || (str[i] == '+') || (str[i] == '/'))) return NULL; if (str[i++] != '=') return NULL; if (str[i++] != '"') return NULL; if (str[i++] != '\0') return NULL; if (_getdns_decode_base64(str + PIN_PREFIX_LENGTH, buf, sizeof(buf)) != GETDNS_RETURN_GOOD) goto fail; if (context) out = getdns_dict_create_with_context(context); else out = getdns_dict_create(); if (out == NULL) goto fail; if (getdns_dict_set_bindata(out, "digest", &sha256)) goto fail; if (getdns_dict_set_bindata(out, "value", &value)) goto fail; return out; fail: getdns_dict_destroy(out); return NULL; }
getdns_return_t _getdns_get_pubkey_pinset_list(getdns_context *ctx, const sha256_pin_t *pinset_in, getdns_list **pinset_list) { getdns_list *out = getdns_list_create_with_context(ctx); getdns_return_t r; uint8_t buf[SHA256_DIGEST_LENGTH]; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_dict *pin = NULL; size_t idx = 0; if (out == NULL) return GETDNS_RETURN_MEMORY_ERROR; while (pinset_in) { pin = getdns_dict_create_with_context(ctx); if (pin == NULL) { r = GETDNS_RETURN_MEMORY_ERROR; goto fail; } if (r = getdns_dict_set_bindata(pin, "digest", &sha256), r) goto fail; memcpy(buf, pinset_in->pin, sizeof(buf)); if (r = getdns_dict_set_bindata(pin, "value", &value), r) goto fail; if (r = getdns_list_set_dict(out, idx++, pin), r) goto fail; getdns_dict_destroy(pin); pin = NULL; pinset_in = pinset_in->next; } *pinset_list = out; return GETDNS_RETURN_GOOD; fail: getdns_dict_destroy(pin); getdns_list_destroy(out); return r; }
static getdns_return_t set_cookie(getdns_dict *exts, char *cookie) { uint8_t data[40]; size_t i; getdns_return_t r = GETDNS_RETURN_GENERIC_ERROR; getdns_bindata bindata; getdns_dict *opt_parameters = getdns_dict_create(); getdns_list *options = getdns_list_create(); getdns_dict *option = getdns_dict_create(); if (*cookie == '=') cookie++; for (i = 0; i < 40 && *cookie; i++) { if (*cookie >= '0' && *cookie <= '9') data[i] = (uint8_t)(*cookie - '0') << 4; else if (*cookie >= 'a' && *cookie <= 'f') data[i] = (uint8_t)(*cookie - 'a' + 10) << 4; else if (*cookie >= 'A' && *cookie <= 'F') data[i] = (uint8_t)(*cookie - 'A' + 10) << 4; else goto done; cookie++; if (*cookie >= '0' && *cookie <= '9') data[i] |= (uint8_t)(*cookie - '0'); else if (*cookie >= 'a' && *cookie <= 'f') data[i] |= (uint8_t)(*cookie - 'a' + 10); else if (*cookie >= 'A' && *cookie <= 'F') data[i] |= (uint8_t)(*cookie - 'A' + 10); else goto done; cookie++;; } bindata.data = data; bindata.size = i; if ((r = getdns_dict_set_int(option, "option_code", 65001))) goto done; if ((r = getdns_dict_set_bindata(option, "option_data", &bindata))) goto done; if ((r = getdns_list_set_dict(options, 0, option))) goto done; if ((r = getdns_dict_set_list(opt_parameters, "options", options))) goto done; r = getdns_dict_set_dict(exts, "add_opt_parameters", opt_parameters); done: getdns_dict_destroy(option); getdns_list_destroy(options); getdns_dict_destroy(opt_parameters); return r; }
getdns_dict * ipaddr_dict(getdns_context *context, char *ipstr) { getdns_dict *r = getdns_dict_create_with_context(context); char *s = strchr(ipstr, '%'), *scope_id_str = ""; char *p = strchr(ipstr, '@'), *portstr = ""; char *t = strchr(ipstr, '#'), *tls_portstr = ""; uint8_t buf[sizeof(struct in6_addr)]; getdns_bindata addr; addr.data = buf; if (!r) return NULL; if (s) { *s = 0; scope_id_str = s + 1; } if (p) { *p = 0; portstr = p + 1; } if (t) { *t = 0; tls_portstr = t + 1; } if (strchr(ipstr, ':')) { getdns_dict_util_set_string(r, "address_type", "IPv6"); addr.size = 16; if (inet_pton(AF_INET6, ipstr, buf) <= 0) { getdns_dict_destroy(r); return NULL; } } else { getdns_dict_util_set_string(r, "address_type", "IPv4"); addr.size = 4; if (inet_pton(AF_INET, ipstr, buf) <= 0) { getdns_dict_destroy(r); return NULL; } } getdns_dict_set_bindata(r, "address_data", &addr); if (*portstr) getdns_dict_set_int(r, "port", (int32_t)atoi(portstr)); if (*tls_portstr) getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr)); if (*scope_id_str) getdns_dict_util_set_string(r, "scope_id", scope_id_str); return r; }
int main() { getdns_return_t r = GETDNS_RETURN_MEMORY_ERROR; getdns_dict *dict = NULL; unsigned char bladiebla_str[] = "bla die bla"; getdns_bindata bladiebla = { sizeof(bladiebla_str), bladiebla_str }; if (!(dict = getdns_dict_create())) fprintf(stderr, "Could not create dict"); else if ((r = getdns_dict_set_int(dict, "/bla/bloe/blie", 53280)) || (r = getdns_dict_set_int(dict, "/bla/hola", 53281)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 1)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 2)) || (r = getdns_dict_set_int(dict, "/bla/cola/-/drie", 3)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 4)) || (r = getdns_dict_set_int(dict, "/bla/cola/1", 5)) || (r = getdns_dict_set_int(dict, "/bla/cola/2/zes", 6)) || (r = getdns_dict_set_bindata(dict, "/die/bla", &bladiebla)) ) fprintf(stderr, "Error setting dict data"); else { char *dict_str = getdns_pretty_print_dict(dict); if (!dict_str) { fprintf(stderr, "Could not convert dict to string"); r = GETDNS_RETURN_MEMORY_ERROR; } else { printf("%s\n", dict_str); free(dict_str); } } if (r) fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r)); if (dict) getdns_dict_destroy(dict); if (r) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); }
getdns_dict* GNUtil::convertToDict(Local<Object> obj) { if (obj->IsRegExp() || obj->IsDate() || obj->IsFunction() || obj->IsUndefined() || obj->IsNull() || obj->IsArray()) { return NULL; } Local<Array> names = obj->GetOwnPropertyNames(); getdns_dict* result = getdns_dict_create(); for(unsigned int i = 0; i < names->Length(); i++) { Local<Value> nameVal = names->Get(i); Nan::Utf8String name(nameVal); Local<Value> val = obj->Get(nameVal); GetdnsType type = getGetdnsType(val); switch (type) { case IntType: getdns_dict_set_int(result, *name, val->ToUint32()->Value()); break; case BoolType: if (val->IsTrue()) { getdns_dict_set_int(result, *name, GETDNS_EXTENSION_TRUE); } else { getdns_dict_set_int(result, *name, GETDNS_EXTENSION_FALSE); } break; case StringType: { struct getdns_bindata strdata; String::Utf8Value utf8Str(val->ToString()); int len = utf8Str.length(); strdata.data = (uint8_t*) *utf8Str; strdata.size = len; getdns_dict_set_bindata(result, *name, &strdata); } break; case BinDataType: { struct getdns_bindata bdata; bdata.data = (uint8_t*) node::Buffer::Data(val); bdata.size = node::Buffer::Length(val); getdns_dict_set_bindata(result, *name, &bdata); } break; case ListType: { Local<Array> subArray = Local<Array>::Cast(val); struct getdns_list* sublist = GNUtil::convertToList(subArray); getdns_dict_set_list(result, *name, sublist); getdns_list_destroy(sublist); } break; case DictType: { Local<Object> subObj = val->ToObject(); struct getdns_dict* subdict = GNUtil::convertToDict(subObj); if (subdict) { getdns_dict_set_dict(result, *name, subdict); getdns_dict_destroy(subdict); } } break; default: break; } } return result; }
/** * test the bindata get and set routines */ void tst_bindatasetget(void) { char msg[TSTMSGBUF]; char key[20]; getdns_return_t retval; struct getdns_dict *dict = NULL; struct getdns_bindata *ans_bdata; struct getdns_bindata *bindata; tstmsg_case_begin("tst_bindatasetget"); dict = getdns_dict_create(); /* test int get function against empty dict and with bogus params */ strcpy(key, "foo"); tstmsg_case_msg("getdns_dict_get_bindata() empty dict"); retval = getdns_dict_get_bindata(NULL, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 1: getdns_dict_get_bindata(NULL, key, &ans_bdata),retval = %d", retval); tstmsg_case_msg(msg); retval = getdns_dict_get_bindata(dict, key, NULL); snprintf(msg, sizeof(msg), "test 2: getdns_dict_get_bindata(dict, key, NULL),retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, NULL, &ans_bindata)"); retval = getdns_dict_get_bindata(dict, NULL, &ans_bdata); snprintf(msg, sizeof(msg), "test 3: getdns_dict_get_bindata,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, key, &ans_bdata)"); retval = getdns_dict_get_bindata(dict, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 4: getdns_list_get_bindata,retval = %d", retval); tstmsg_case_msg(msg); getdns_dict_destroy(dict); /* TODO: test getdns_dict_set functions with bogus params */ /* test set and get legitimate use case */ dict = getdns_dict_create(); strcpy(key, "foo"); bindata = (struct getdns_bindata *) malloc(sizeof(struct getdns_bindata)); bindata->size = strlen("foobar") + 1; bindata->data = (void *) strdup("foobar"); tstmsg_case_msg("getdns_dict_set_bindata(dict, key, bindata)"); retval = getdns_dict_set_bindata(dict, key, bindata); snprintf(msg, sizeof(msg), "test 5: getdns_dict_set_bindata,retval=%d,key=%s", retval, key); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, key, &ans_bdata)"); retval = getdns_dict_get_bindata(dict, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 6: getdns_dict_get_bindata,retval=%d,key=%s,data=%s", retval, key, ans_bdata->data); tstmsg_case_msg(msg); getdns_dict_destroy(dict); free(bindata->data); free(bindata); tstmsg_case_end(); return; } /* tst_bindatasetget */
int main(int argc, char const * const argv[]) { getdns_return_t r; getdns_dict *rr_dict; getdns_bindata *dns_name; getdns_bindata address = { 4, "\xb9\x31\x8d\x25" }; getdns_bindata fourth = { 11, "last string" }; size_t length; char *str; uint8_t *wire, *prev_wire; size_t wire_len; getdns_list *rr_list; FILE *in; uint8_t wire_buf[8200]; size_t i; size_t uavailable; int available; char str_buf[10000]; int str_len = sizeof(str_buf); /* Convert string to rr_dict */ if ((r = getdns_str2rr_dict( "some.domain.tld. 60 IN TXT \"first string\" second \"and third\"", &rr_dict, NULL, 3600))) FAIL_r("getdns_str2rr_dict"); /* Add a fourth text element. */ if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/txt_strings/-", &fourth))) FAIL_r("getdns_list_set_bindata"); print_dict(rr_dict); /* Convert to wireformat from rdata_raw. * Added fourth list element should NOT show. */ wire = NULL; if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Convert to wireformat from parsing rdata fields. * Added fourth list element should show. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\nremoved \"/rdata/rdata_raw\":\n\n"); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Remove second and third string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s", str); free(str); /* Remove all string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); /* Construct rr_dict and convert to string */ if (!(rr_dict = getdns_dict_create())) FAIL("getdns_dict_create returned NULL"); if ((r = getdns_convert_fqdn_to_dns_name("www.getdnsapi.net", &dns_name))) FAIL_r("getdns_convert_fqdn_to_dns_name"); r = getdns_dict_set_bindata(rr_dict, "name", dns_name); free(dns_name->data); free(dns_name); if (r) FAIL_r("getdns_dict_set_bindata"); if ((r = getdns_dict_set_int(rr_dict, "type", GETDNS_RRTYPE_A))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/ipv4_address", &address))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s\n", str); free(str); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); getdns_dict_destroy(rr_dict); print_wire(wire, wire_len); free(wire); /* Convert RR with special rdata fields and repeating last element * from string to rr_dict */ if ((r = getdns_str2rr_dict( "hip2 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com.", &rr_dict, "nlnetlabs.nl", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\n"); print_dict(rr_dict); /* Convert RR with special rdata fields and repeating last element * back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); /* Convert RR with special rdata fields without repeating last element * to string. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rendezvous_servers"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_get_bindata(rr_dict, "name", &dns_name))) FAIL_r("getdns_dict_get_bindata"); dns_name->data[4] = '0'; if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s\n", str); free(str); getdns_dict_destroy(rr_dict); /* Convert RR with repeat block from string to rr_dict */ if ((r = getdns_str2rr_dict( "apl APL 1:192.168.42.0/26 1:192.168.42.64/26 !1:192.168.42.128/25 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8", &rr_dict, "net-dns.org", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); print_dict(rr_dict); /* Convert repeat block from rr_dict back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); if (!(in = fopen(argv[1], "r"))) FAIL("Could not fopen %s\n", argv[1]); if ((r = getdns_fp2rr_list(in, &rr_list, NULL, 0))) FAIL_r("getdns_fp2rr_list"); fclose(in); print_list(rr_list); print_json_list(rr_list, 1); /* Fill the wire_buf with wireformat RR's in rr_list * wire_buf is too small for last two rr's. */ wire = wire_buf; available = sizeof(wire_buf); for (i = 0; !(r = getdns_list_get_dict(rr_list, i, &rr_dict)); i++) { prev_wire = wire; if ((r = getdns_rr_dict2wire_scan(rr_dict,&wire,&available))) { if (r == GETDNS_RETURN_NEED_MORE_SPACE) { printf("record %.3zu, available buffer space: " "%d\n", i, available); /* The buffer was too small to fit the wire- * format representation. available now holds * a negative number. the wire pointer is this * much beyond the end of the buffer space. * * If we would add available to wire, wire * would be positioned at the end of the buffer * but would not be positioned at a clean RR * border. Therefore we have to remember the * previous position of wire, so we can reset * it at the end of the wireformat representa- * tion of the previously converted rr_dict. */ wire = prev_wire; break; } else FAIL_r("getdns_rr_dict2wire_scan"); } printf("record %3zu, available buffer space: " "%d\n", i, available); fflush(stdout); } if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) r = GETDNS_RETURN_GOOD; getdns_list_destroy(rr_list); /* Now scan over the wireformat buffer and convert to rr_dicts again. * Then fill a string buffer with those rr_dicts. */ available = wire - wire_buf; if (available < 0) { fprintf(stderr, "Negative sized buffer!\n"); exit(EXIT_FAILURE); } uavailable = available; wire = wire_buf; str = str_buf; str_len = sizeof(str_buf); while (uavailable > 0 && str_len > 0) { rr_dict = NULL; if ((r = getdns_wire2rr_dict_scan( (const uint8_t **)&wire, &uavailable, &rr_dict))) FAIL_r("getdns_wire2rr_dict_scan"); if ((r = getdns_rr_dict2str_scan(rr_dict, &str, &str_len))) FAIL_r("getdns_rr_dict2str_scan"); getdns_dict_destroy(rr_dict); } *str = 0; /* Print the entire buffer */ printf("%s", str_buf); exit(EXIT_SUCCESS); }