/** dump one rrset zonefile line */ static int dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, struct packed_rrset_data* d, uint32_t now, size_t i, uint16_t type) { char* s; ldns_rr* rr = to_rr(k, d, now, i, type); if(!rr) { return ssl_printf(ssl, "BADRR\n"); } s = ldns_rr2str(rr); ldns_rr_free(rr); if(!s) { return ssl_printf(ssl, "BADRR\n"); } if(!ssl_printf(ssl, "%s", s)) { free(s); return 0; } free(s); return 1; }
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results) { char *str = ldns_rr2str(naptr); char *argv[11] = { 0 }; int i, argc; char *pack[4] = { 0 }; int packc; char *p; int order = 10; int preference = 100; char *service = NULL; char *packstr; char *regex, *replace; if (zstr(str)) { if (str != NULL) { /* In this case ldns_rr2str returned a malloc'd null terminated string */ switch_safe_free(str); } return; } for (p = str; p && *p; p++) { if (*p == '\t') *p = ' '; if (*p == ' ' && *(p+1) == '.') *p = '\0'; } argc = switch_split(str, ' ', argv); for (i = 0; i < argc; i++) { if (i > 0) { strip_quotes(argv[i]); } } service = argv[7]; packstr = argv[8]; if (zstr(service) || zstr(packstr)) { goto end; } if (!zstr(argv[4])) { order = atoi(argv[4]); } if (!zstr(argv[5])) { preference = atoi(argv[5]); } if ((packc = switch_split(packstr, '!', pack))) { regex = pack[1]; replace = pack[2]; } else { goto end; } for (p = replace; p && *p; p++) { if (*p == '\\') { *p = '$'; } } if (service && regex && replace) { switch_regex_t *re = NULL, *re2 = NULL; int proceed = 0, ovector[30]; char *substituted = NULL; char *substituted_2 = NULL; char *orig_uri; char *uri_expanded = NULL; enum_route_t *route; int supported = 0; uint32_t len = 0; if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { if (strchr(regex, '(')) { len = (uint32_t) (strlen(number) + strlen(replace) + 10) * proceed; if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_regex_safe_free(re); goto end; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, replace, number, substituted, len, ovector); orig_uri = substituted; } else { orig_uri = replace; } switch_mutex_lock(MUTEX); for (route = globals.route_order; route; route = route->next) { char *uri = orig_uri; if (strcasecmp(service, route->service)) { continue; } if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_event_t *event = NULL; if (strchr(route->regex, '(')) { len = (uint32_t) (strlen(uri) + strlen(route->replace) + 10) * proceed; if (!(substituted_2 = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_safe_free(substituted); switch_regex_safe_free(re); switch_regex_safe_free(re2); switch_mutex_unlock(MUTEX); goto end; } memset(substituted_2, 0, len); switch_perform_substitution(re2, proceed, route->replace, uri, substituted_2, len, ovector); uri = substituted_2; } else { uri = route->replace; } switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS); uri_expanded = switch_event_expand_headers(event, uri); switch_event_destroy(&event); if (uri_expanded == uri) { uri_expanded = NULL; } else { uri = uri_expanded; } supported++; add_result(results, order, preference, service, uri, supported); } switch_safe_free(uri_expanded); switch_safe_free(substituted_2); switch_regex_safe_free(re2); } switch_mutex_unlock(MUTEX); if (!supported) { add_result(results, order, preference, service, orig_uri, 0); } switch_safe_free(substituted); switch_regex_safe_free(re); } } end: switch_safe_free(str); return; }
static uint16_t dnskey_from_id(std::string &dnskey, const char *id, ::ods::keystate::keyrole role, const char *zone, int algorithm, int bDS, uint32_t ttl) { hsm_key_t *key; hsm_sign_params_t *sign_params; ldns_rr *dnskey_rr; ldns_algorithm algo = (ldns_algorithm)algorithm; /* Code to output the DNSKEY record (stolen from hsmutil) */ hsm_ctx_t *hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error("[%s] Could not connect to HSM", module_str); return false; } key = hsm_find_key_by_id(hsm_ctx, id); if (!key) { // printf("Key %s in DB but not repository\n", id); hsm_destroy_context(hsm_ctx); return 0; } /* * Sign params only need to be kept around * for the hsm_get_dnskey() call. */ sign_params = hsm_sign_params_new(); sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone); sign_params->algorithm = algo; sign_params->flags = LDNS_KEY_ZONE_KEY; if (role == ::ods::keystate::KSK) sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/ /* Get the DNSKEY record */ dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params); hsm_sign_params_free(sign_params); /* Calculate the keytag for this key, we return it. */ uint16_t keytag = ldns_calc_keytag(dnskey_rr); /* Override the TTL in the dnskey rr */ if (ttl) ldns_rr_set_ttl(dnskey_rr, ttl); char *rrstr; if (!bDS) { #if 0 ldns_rr_print(stdout, dnskey_rr); #endif rrstr = ldns_rr2str(dnskey_rr); dnskey = rrstr; LDNS_FREE(rrstr); } else { switch (algo) { case LDNS_RSASHA1: // 5 { /* DS record (SHA1) */ ldns_rr *ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1); #if 0 ldns_rr_print(stdout, ds_sha1_rr); #endif rrstr = ldns_rr2str(ds_sha1_rr); dnskey = rrstr; LDNS_FREE(rrstr); ldns_rr_free(ds_sha1_rr); break; } case LDNS_RSASHA256: // 8 - RFC 5702 { /* DS record (SHA256) */ ldns_rr *ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256); #if 0 ldns_rr_print(stdout, ds_sha256_rr); #endif rrstr = ldns_rr2str(ds_sha256_rr); dnskey = rrstr; LDNS_FREE(rrstr); ldns_rr_free(ds_sha256_rr); break; } default: keytag = 0; } } ldns_rr_free(dnskey_rr); hsm_key_free(key); hsm_destroy_context(hsm_ctx); return keytag; }
/** * Read ixfr journal from file. * * */ ods_status backup_read_ixfr(FILE* in, void* zone) { zone_type* z = (zone_type*) zone; ods_status result = ODS_STATUS_OK; ldns_rr* rr = NULL; ldns_rdf* prev = NULL; ldns_rdf* orig = NULL; ldns_rdf* dname = NULL; ldns_status status = LDNS_STATUS_OK; char line[SE_ADFILE_MAXLINE]; uint32_t serial = 0; unsigned l = 0; unsigned first_soa = 1; /* expect soa first */ unsigned del_mode = 0; ods_log_assert(in); ods_log_assert(z); /* $ORIGIN <zone name> */ dname = adapi_get_origin(z); if (!dname) { ods_log_error("[%s] error getting default value for $ORIGIN", backup_str); return ODS_STATUS_ERR; } orig = ldns_rdf_clone(dname); if (!orig) { ods_log_error("[%s] error setting default value for $ORIGIN", backup_str); return ODS_STATUS_ERR; } /* read RRs */ while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l)) != NULL) { /* check status */ if (status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RR #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_ixfr_done; } if (first_soa == 2) { ods_log_error("[%s] bad ixfr journal: trailing RRs after final " "SOA", backup_str); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_ixfr_done; } if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { serial = ldns_rdf2native_int32( ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL)); if (first_soa) { ods_log_debug("[%s] ixfr first SOA: %s", backup_str, ldns_rr2str(rr)); /* first SOA */ ldns_rr_free(rr); rr = NULL; if (z->db->outserial != serial) { ods_log_error("[%s] bad ixfr journal: first SOA wrong " "serial (was %u, expected %u)", backup_str, serial, z->db->outserial); result = ODS_STATUS_ERR; goto backup_ixfr_done; } first_soa = 0; continue; } ods_log_assert(!first_soa); if (!del_mode) { if (z->db->outserial == serial) { /* final SOA */ ods_log_debug("[%s] ixfr final SOA: %s", backup_str, ldns_rr2str(rr)); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_OK; first_soa = 2; continue; } else { ods_log_debug("[%s] new part SOA: %s", backup_str, ldns_rr2str(rr)); lock_basic_lock(&z->ixfr->ixfr_lock); ixfr_purge(z->ixfr); lock_basic_unlock(&z->ixfr->ixfr_lock); } } else { ods_log_debug("[%s] second part SOA: %s", backup_str, ldns_rr2str(rr)); } del_mode = !del_mode; } /* ixfr add or del rr */ if (first_soa) { ods_log_error("[%s] bad ixfr journal: first RR not SOA", backup_str); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_ixfr_done; } ods_log_assert(!first_soa); lock_basic_lock(&z->ixfr->ixfr_lock); if (del_mode) { ods_log_debug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr)); ixfr_del_rr(z->ixfr, rr); } else { ods_log_debug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr)); ixfr_add_rr(z->ixfr, rr); } lock_basic_unlock(&z->ixfr->ixfr_lock); } if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RR #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; } backup_ixfr_done: if (orig) { ldns_rdf_deep_free(orig); orig = NULL; } if (prev) { ldns_rdf_deep_free(prev); prev = NULL; } return result; }
static bool retract_dnskey_by_id(int sockfd, const char *ds_retract_command, const char *id, ::ods::keystate::keyrole role, const char *zone, int algorithm) { /* Code to output the DNSKEY record (stolen from hsmutil) */ hsm_ctx_t *hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error_and_printf(sockfd, module_str, "could not connect to HSM"); return false; } hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id); if (!key) { ods_log_error_and_printf(sockfd, module_str, "key %s not found in any HSM", id); hsm_destroy_context(hsm_ctx); return false; } bool bOK = false; char *dnskey_rr_str; hsm_sign_params_t *sign_params = hsm_sign_params_new(); sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone); sign_params->algorithm = (ldns_algorithm)algorithm; sign_params->flags = LDNS_KEY_ZONE_KEY; sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/ ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params); #if 0 ldns_rr_print(stdout, dnskey_rr); #endif dnskey_rr_str = ldns_rr2str(dnskey_rr); hsm_sign_params_free(sign_params); ldns_rr_free(dnskey_rr); hsm_key_free(key); /* Replace tab with white-space */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == '\t') { dnskey_rr_str[i] = ' '; } } /* We need to strip off trailing comments before we send to any clients that might be listening */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == ';') { dnskey_rr_str[i] = '\n'; dnskey_rr_str[i+1] = '\0'; break; } } // pass the dnskey rr string to a configured // delegation signer retract program. if (ds_retract_command && ds_retract_command[0] != '\0') { /* send records to the configured command */ FILE *fp = popen(ds_retract_command, "w"); if (fp == NULL) { ods_log_error_and_printf(sockfd, module_str, "failed to run command: %s: %s", ds_retract_command, strerror(errno)); } else { int bytes_written = fprintf(fp, "%s", dnskey_rr_str); if (bytes_written < 0) { ods_log_error_and_printf(sockfd, module_str, "[%s] Failed to write to %s: %s", ds_retract_command, strerror(errno)); } else { if (pclose(fp) == -1) { ods_log_error_and_printf(sockfd, module_str, "failed to close %s: %s", ds_retract_command, strerror(errno)); } else { bOK = true; ods_printf(sockfd, "key %s retracted by %s\n", id, ds_retract_command); } } } } else { ods_log_error_and_printf(sockfd, module_str, "no \"DelegationSignerRetractCommand\" binary " "configured in conf.xml."); } LDNS_FREE(dnskey_rr_str); hsm_destroy_context(hsm_ctx); return bOK; }
static bool retract_dnskey_by_id(int sockfd, const char *ds_retract_command, const char *id, ::ods::keystate::keyrole role, const char *zone, int algorithm, bool force) { struct stat stat_ret; /* Code to output the DNSKEY record (stolen from hsmutil) */ hsm_ctx_t *hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error_and_printf(sockfd, module_str, "could not connect to HSM"); return false; } hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id); if (!key) { ods_log_error_and_printf(sockfd, module_str, "key %s not found in any HSM", id); hsm_destroy_context(hsm_ctx); return false; } bool bOK = false; char *dnskey_rr_str; hsm_sign_params_t *sign_params = hsm_sign_params_new(); sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone); sign_params->algorithm = (ldns_algorithm)algorithm; sign_params->flags = LDNS_KEY_ZONE_KEY; sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/ ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params); #if 0 ldns_rr_print(stdout, dnskey_rr); #endif dnskey_rr_str = ldns_rr2str(dnskey_rr); hsm_sign_params_free(sign_params); ldns_rr_free(dnskey_rr); hsm_key_free(key); /* Replace tab with white-space */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == '\t') { dnskey_rr_str[i] = ' '; } } /* We need to strip off trailing comments before we send to any clients that might be listening */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == ';') { dnskey_rr_str[i] = '\n'; dnskey_rr_str[i+1] = '\0'; break; } } // pass the dnskey rr string to a configured // delegation signer retract program. if (!ds_retract_command || ds_retract_command[0] == '\0') { if (!force) { ods_log_error_and_printf(sockfd, module_str, "No \"DelegationSignerRetractCommand\" " "configured. No state changes made. " "Use --force to override."); bOK = false; } /* else: Do nothing, return keytag. */ } else if (stat(ds_retract_command, &stat_ret) != 0) { /* First check that the command exists */ ods_log_error_and_printf(sockfd, module_str, "Cannot stat file %s: %s", ds_retract_command, strerror(errno)); } else if (S_ISREG(stat_ret.st_mode) && !(stat_ret.st_mode & S_IXUSR || stat_ret.st_mode & S_IXGRP || stat_ret.st_mode & S_IXOTH)) { /* Then see if it is a regular file, then if usr, grp or * all have execute set */ ods_log_error_and_printf(sockfd, module_str, "File %s is not executable", ds_retract_command); } else { /* send records to the configured command */ FILE *fp = popen(ds_retract_command, "w"); if (fp == NULL) { ods_log_error_and_printf(sockfd, module_str, "failed to run command: %s: %s", ds_retract_command, strerror(errno)); } else { int bytes_written = fprintf(fp, "%s", dnskey_rr_str); if (bytes_written < 0) { ods_log_error_and_printf(sockfd, module_str, "[%s] Failed to write to %s: %s", ds_retract_command, strerror(errno)); } else if (pclose(fp) == -1) { ods_log_error_and_printf(sockfd, module_str, "failed to close %s: %s", ds_retract_command, strerror(errno)); } else { bOK = true; ods_printf(sockfd, "key %s retracted by %s\n", id, ds_retract_command); } } } LDNS_FREE(dnskey_rr_str); hsm_destroy_context(hsm_ctx); return bOK; }
/* Simple interface to provide DNS MX record resolution. @param Pointer to the c string hostname you would like resolved to an MX record. @param Pointer to the struct you would like the results written out to. @return Return is of type int and is just the mx family type in the variable ohana. Ohana is hawaiian for family. */ int resolve_server(char * hostname, struct sockaddr_storage * result) { pthread_mutex_lock(&dns_lock); res_init(); int error = 0; int ohana = 0; ns_msg msg; ns_rr rr; struct addrinfo * addr_res; int res_length = 0; unsigned char dns_answer[4096] = {0}; char display_buffer[4096] = {0}; //ldns variables ldns_resolver *ldns_resolv; ldns_rdf *ldns_domain; ldns_pkt *ldns_packet; ldns_rr_list *ldns_mx_records; ldns_status s; //Setup ldns to query for the mx record s = ldns_resolver_new_frm_file(&ldns_resolv, NULL); ldns_domain = ldns_dname_new_frm_str(hostname); //Use ldns to query ldns_packet = ldns_resolver_query(ldns_resolv, ldns_domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD); //parse ldns query results ldns_mx_records = ldns_pkt_rr_list_by_type(ldns_packet, LDNS_RR_TYPE_MX, LDNS_SECTION_ANSWER); //Sort and print mx records ldns_rr_list_sort(ldns_mx_records); ldns_rr_list_print(stdout, ldns_mx_records); for (int i = 0; i < ldns_mx_records->_rr_count; i++) { printf("^_^ i= %d\n", i); printf(">_> %s",ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i))); printf(">.> %s\n", last_str_split(ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i)), " ")); } /////////////////Old code below///////////////////// res_length = res_query(hostname, C_IN, T_MX, dns_answer, sizeof(dns_answer)); if (ns_initparse(dns_answer, res_length, &msg)<0) { printf("hostname = %s\n", hostname); printf("res_length = %d\n", res_length); perror("DNS has gone wrong!"); print_to_log("DNS resource query has failed", LOG_ERR); } else { res_length = ns_msg_count(msg, ns_s_an); for (int i = 0; i < res_length; i++) { //printf("DNS loop level = %d\n", i); ns_parserr(&msg, ns_s_an, i, &rr); ns_sprintrr(&msg, &rr, NULL, NULL, display_buffer, sizeof(display_buffer)); if (ns_rr_type(rr) == ns_t_mx) { //String parsing solution for rr. Requires creation of display_buffer above error = getaddrinfo(last_str_split(display_buffer, " "), NULL, NULL, &addr_res); if (error != 0) { printf("error = %d\n", error); printf("display_buffer = %s\n", display_buffer); printf("last_str_split = %s\n", last_str_split(display_buffer, " ")); perror("getaddrinfo"); } if (addr_res->ai_family==AF_INET) { //printf("IPv4 mode is go\n"); struct sockaddr_in* temp_addr = (struct sockaddr_in*)addr_res->ai_addr; memcpy(result, temp_addr, sizeof(*temp_addr)); //printf("ai_addr hostname -> %s\n", inet_ntoa(temp_addr->sin_addr)); ohana = addr_res->ai_family; } else if (addr_res->ai_family==AF_INET6) { //printf("v6 mode engaged\n"); struct sockaddr_in6 * temp_addr = (struct sockaddr_in6 *) addr_res->ai_addr; memcpy(result, temp_addr, sizeof(*temp_addr)); ohana = addr_res->ai_family; } } freeaddrinfo(addr_res); } } pthread_mutex_unlock(&dns_lock); return ohana; }