/** parse args into delegpt */ static struct delegpt* parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root) { /* parse args and add in */ char* p = args; char* todo; struct delegpt* dp = delegpt_create(region); struct sockaddr_storage addr; socklen_t addrlen; if(!dp || !delegpt_set_name(dp, region, root)) { (void)ssl_printf(ssl, "error out of memory\n"); return NULL; } while(p) { todo = p; p = strchr(p, ' '); /* find next spot, if any */ if(p) { *p++ = 0; /* end this spot */ p = skipwhite(p); /* position at next spot */ } /* parse address */ if(!extstrtoaddr(todo, &addr, &addrlen)) { (void)ssl_printf(ssl, "error cannot parse" " IP address '%s'\n", todo); return NULL; } /* add address */ if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0, 1)) { (void)ssl_printf(ssl, "error out of memory\n"); return NULL; } } return dp; }
/** print main dp info */ static void print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg) { size_t i, n_ns, n_miss, n_addr, n_res, n_avail; /* print the dp */ if(msg) for(i=0; i<msg->rep->rrset_count; i++) { struct ub_packed_rrset_key* k = msg->rep->rrsets[i]; struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; if(d->security == sec_status_bogus) { if(!ssl_printf(ssl, "Address is BOGUS:\n")) return; } if(!dump_rrset(ssl, k, d, 0)) return; } delegpt_count_ns(dp, &n_ns, &n_miss); delegpt_count_addr(dp, &n_addr, &n_res, &n_avail); /* since dp has not been used by iterator, all are available*/ if(!ssl_printf(ssl, "Delegation with %d names, of which %d " "can be examined to query further addresses.\n" "%sIt provides %d IP addresses.\n", (int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""), (int)n_addr)) return; }
/** printout a delegation point info */ static int ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass, struct delegpt* dp) { char buf[257]; struct delegpt_ns* ns; struct delegpt_addr* a; int f = 0; if(str) { /* print header for forward, stub */ char* c = ldns_rr_class2str(dclass); dname_str(nm, buf); if(!ssl_printf(ssl, "%s %s %s: ", buf, c, str)) { free(c); return 0; } free(c); } for(ns = dp->nslist; ns; ns = ns->next) { dname_str(ns->name, buf); if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) return 0; f = 1; } for(a = dp->target_list; a; a = a->next_target) { addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) return 0; f = 1; } return ssl_printf(ssl, "\n"); }
/** dump message to rrset reference */ static int dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k) { char* nm, *tp, *cl; nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len); tp = sldns_wire2str_type(ntohs(k->rk.type)); cl = sldns_wire2str_class(ntohs(k->rk.rrset_class)); if(!nm || !cl || !tp) { free(nm); free(tp); free(cl); return ssl_printf(ssl, "BADREF\n"); } if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) { free(nm); free(tp); free(cl); return 0; } free(nm); free(tp); free(cl); return 1; }
/** dump message to rrset reference */ static int dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k) { ldns_rdf* rdf; ldns_status status; size_t pos; char* nm, *tp, *cl; pos = 0; status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos); if(status != LDNS_STATUS_OK) { return ssl_printf(ssl, "BADREF\n"); } nm = ldns_rdf2str(rdf); ldns_rdf_deep_free(rdf); tp = ldns_rr_type2str(ntohs(k->rk.type)); cl = ldns_rr_class2str(ntohs(k->rk.rrset_class)); if(!nm || !cl || !tp) { free(nm); free(tp); free(cl); return ssl_printf(ssl, "BADREF\n"); } if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) { free(nm); free(tp); free(cl); return 0; } free(nm); free(tp); free(cl); return 1; }
/** do the status command */ static void do_forward(SSL* ssl, struct worker* worker, char* args) { struct iter_forwards* fwd = worker->env.fwds; uint8_t* root = (uint8_t*)"\000"; if(!fwd) { (void)ssl_printf(ssl, "error: structure not allocated\n"); return; } if(args == NULL || args[0] == 0) { (void)print_root_fwds(ssl, fwd, root); return; } /* set root forwards for this thread. since we are in remote control * the actual mesh is not running, so we can freely edit it. */ /* delete all the existing queries first */ mesh_delete_all(worker->env.mesh); /* reset the fwd structure ; the cfg is unchanged (shared by threads)*/ /* this reset frees up memory */ forwards_apply_cfg(fwd, worker->env.cfg); if(strcmp(args, "off") == 0) { forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root); } else { struct delegpt* dp; if(!(dp = parse_delegpt(ssl, fwd->region, args, root))) return; if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) { (void)ssl_printf(ssl, "error out of memory\n"); return; } } send_ok(ssl); }
/** dump one rrset zonefile line */ static int dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i) { char s[65535]; if(!packed_rr_to_string(k, i, now, s, sizeof(s))) { return ssl_printf(ssl, "BADRR\n"); } return ssl_printf(ssl, "%s", s); }
/** * Used for diagnostics. */ void RSA_print(const RSA_CTX *rsa_ctx) { if (rsa_ctx == NULL) return; ssl_printf("----------------- RSA DEBUG ----------------\n"); ssl_printf("Size:\t%d\n", rsa_ctx->num_octets); bi_print("Modulus", rsa_ctx->m); bi_print("Public Key", rsa_ctx->e); bi_print("Private Key", rsa_ctx->d); }
/* * Perform a sanity check on bi. */ static void ICACHE_FLASH_ATTR check(const bigint *bi) { if (bi->refs <= 0) { ssl_printf("check: zero or negative refs in bigint\n"); return; /* wujg : org ----> abort(); */ } if (bi->next != NULL) { ssl_printf("check: attempt to use a bigint from " "the free list\n"); return; /* wujg : org ----> abort(); */ } }
/** print long number */ static int print_longnum(SSL* ssl, char* desc, size_t x) { if(x > 1024*1024*1024) { /* more than a Gb */ size_t front = x / (size_t)1000000; size_t back = x % (size_t)1000000; return ssl_printf(ssl, "%s%u%6.6u\n", desc, (unsigned)front, (unsigned)back); } else { return ssl_printf(ssl, "%s%u\n", desc, (unsigned)x); } }
/** do the status command */ static void do_status(SSL* ssl, struct worker* worker) { int i; time_t uptime; if(!ssl_printf(ssl, "version: %s\n", PACKAGE_VERSION)) return; if(!ssl_printf(ssl, "verbosity: %d\n", verbosity)) return; if(!ssl_printf(ssl, "threads: %d\n", worker->daemon->num)) return; if(!ssl_printf(ssl, "modules: %d [", worker->daemon->mods.num)) return; for(i=0; i<worker->daemon->mods.num; i++) { if(!ssl_printf(ssl, " %s", worker->daemon->mods.mod[i]->name)) return; } if(!ssl_printf(ssl, " ]\n")) return; uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec; if(!ssl_printf(ssl, "uptime: %u seconds\n", (unsigned)uptime)) return; if(!ssl_printf(ssl, "unbound (pid %d) is running...\n", (int)getpid())) return; }
/** * @brief Free a bigint object so it can be used again. * * The memory itself it not actually freed, just tagged as being available * @param ctx [in] The bigint session context. * @param bi [in] The bigint to be freed. */ void ICACHE_FLASH_ATTR bi_free(BI_CTX *ctx, bigint *bi) { check(bi); if (bi->refs == PERMANENT) { return; } if (--bi->refs > 0) { return; } bi->next = ctx->free_list; ctx->free_list = bi; ctx->free_count++; if (--ctx->active_count < 0) { #ifdef CONFIG_SSL_FULL_MODE ssl_printf("bi_free: active_count went negative " "- double-freed bigint?\n"); #endif return; /* wujg : org ----> abort(); */ } }
/* * Make a new empty bigint. It may just use an old one if one is available. * Otherwise get one off the heap. */ static bigint * ICACHE_FLASH_ATTR alloc(BI_CTX *ctx, int size) { bigint *biR; /* Can we recycle an old bigint? */ if (ctx->free_list != NULL) { biR = ctx->free_list; ctx->free_list = biR->next; ctx->free_count--; if (biR->refs != 0) { #ifdef CONFIG_SSL_FULL_MODE ssl_printf("alloc: refs was not 0\n"); #endif return biR; /* wujg : org ----> abort(); */ } more_comps(biR, size); } else { /* No free bigints available - create a new one. */ biR = (bigint *)SSL_MALLOC(sizeof(bigint)); biR->comps = (comp*)SSL_MALLOC(size * COMP_BYTE_SIZE); biR->max_comps = size; /* give some space to spare */ } biR->size = size; biR->refs = 1; biR->next = NULL; ctx->active_count++; return biR; }
/* * Do the handshaking from the beginning. */ int ICACHE_FLASH_ATTR do_client_connect(SSL *ssl) { int ret = SSL_OK; send_client_hello(ssl); /* send the client hello */ ssl->bm_read_index = 0; ssl->next_state = HS_SERVER_HELLO; ssl->hs_status = SSL_NOT_OK; /* not connected */ /* sit in a loop until it all looks good */ if (!IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS)) { while (ssl->hs_status != SSL_OK) { // esp_ssl_sleep(100); ret = ssl_read(ssl, NULL); ssl_printf("%s %d %d\n", __func__, __LINE__,ret); if (ret < SSL_OK) break; } ssl->hs_status = ret; /* connected? */ } return ret; }
/** dump rrset key and data info */ static int dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k, struct packed_rrset_data* d, uint32_t now) { size_t i; /* rd lock held by caller */ if(!k || !d) return 1; if(d->ttl < now) return 1; /* expired */ /* meta line */ if(!ssl_printf(ssl, ";rrset%s %u %u %u %d %d\n", (k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"", (unsigned)(d->ttl - now), (unsigned)d->count, (unsigned)d->rrsig_count, (int)d->trust, (int)d->security )) return 0; for(i=0; i<d->count; i++) { if(!dump_rrset_line(ssl, k, d, now, i, ntohs(k->rk.type))) return 0; } for(i=0; i<d->rrsig_count; i++) { if(!dump_rrset_line(ssl, k, d, now, i+d->count, LDNS_RR_TYPE_RRSIG)) return 0; } return 1; }
/** dump msg cache */ static int dump_msg_cache(SSL* ssl, struct worker* worker) { struct slabhash* sh = worker->env.msg_cache; size_t slab; if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0; for(slab=0; slab<sh->size; slab++) { lock_quick_lock(&sh->array[slab]->lock); if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) { lock_quick_unlock(&sh->array[slab]->lock); return 0; } lock_quick_unlock(&sh->array[slab]->lock); } return ssl_printf(ssl, "END_MSG_CACHE\n"); }
/** print uptime stats */ static int print_uptime(SSL* ssl, struct worker* worker) { struct timeval now = *worker->env.now_tv; struct timeval up, dt; timeval_subtract(&up, &now, &worker->daemon->time_boot); timeval_subtract(&dt, &now, &worker->daemon->time_last_stat); worker->daemon->time_last_stat = now; if(!ssl_printf(ssl, "time.now"SQ"%d.%6.6d\n", (unsigned)now.tv_sec, (unsigned)now.tv_usec)) return 0; if(!ssl_printf(ssl, "time.up"SQ"%d.%6.6d\n", (unsigned)up.tv_sec, (unsigned)up.tv_usec)) return 0; if(!ssl_printf(ssl, "time.elapsed"SQ"%d.%6.6d\n", (unsigned)dt.tv_sec, (unsigned)dt.tv_usec)) return 0; return 1; }
/** print extended histogram */ static int print_hist(SSL* ssl, struct stats_info* s) { struct timehist* hist; size_t i; hist = timehist_setup(); if(!hist) { log_err("out of memory"); return 0; } timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST); for(i=0; i<hist->num; i++) { if(!ssl_printf(ssl, "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%u\n", (int)hist->buckets[i].lower.tv_sec, (int)hist->buckets[i].lower.tv_usec, (int)hist->buckets[i].upper.tv_sec, (int)hist->buckets[i].upper.tv_usec, (unsigned)hist->buckets[i].count)) { timehist_delete(hist); return 0; } } timehist_delete(hist); return 1; }
/** dump rrset cache */ static int dump_rrset_cache(SSL* ssl, struct worker* worker) { struct rrset_cache* r = worker->env.rrset_cache; size_t slab; if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0; for(slab=0; slab<r->table.size; slab++) { lock_quick_lock(&r->table.array[slab]->lock); if(!dump_rrset_lruhash(ssl, r->table.array[slab], *worker->env.now)) { lock_quick_unlock(&r->table.array[slab]->lock); return 0; } lock_quick_unlock(&r->table.array[slab]->lock); } return ssl_printf(ssl, "END_RRSET_CACHE\n"); }
/** * Get all the RSA private key specifics from an ASN.1 encoded file */ int ICACHE_FLASH_ATTR asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx) { int offset = 7; uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL; int mod_len, priv_len, pub_len; #ifdef CONFIG_BIGINT_CRT uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL; int p_len, q_len, dP_len, dQ_len, qInv_len; #endif /* not in der format */ if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */ { #ifdef CONFIG_SSL_FULL_MODE ssl_printf("Error: This is not a valid ASN.1 file\n"); #endif return X509_INVALID_PRIV_KEY; } /* Use the private key to mix up the RNG if possible. */ RNG_custom_init(buf, len); mod_len = asn1_get_int(buf, &offset, &modulus); pub_len = asn1_get_int(buf, &offset, &pub_exp); priv_len = asn1_get_int(buf, &offset, &priv_exp); if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0) return X509_INVALID_PRIV_KEY; #ifdef CONFIG_BIGINT_CRT p_len = asn1_get_int(buf, &offset, &p); q_len = asn1_get_int(buf, &offset, &q); dP_len = asn1_get_int(buf, &offset, &dP); dQ_len = asn1_get_int(buf, &offset, &dQ); qInv_len = asn1_get_int(buf, &offset, &qInv); if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0) return X509_INVALID_PRIV_KEY; RSA_priv_key_new(rsa_ctx, modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len, p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len); free(p); free(q); free(dP); free(dQ); free(qInv); #else RSA_priv_key_new(rsa_ctx, modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len); #endif free(modulus); free(priv_exp); free(pub_exp); return X509_OK; }
int dump_cache(SSL* ssl, struct worker* worker) { if(!dump_rrset_cache(ssl, worker)) return 0; if(!dump_msg_cache(ssl, worker)) return 0; return ssl_printf(ssl, "EOF\n"); }
void ICACHE_FLASH_ATTR bi_print(const char *label, bigint *x) { int i, j; if (x == NULL) { ssl_printf("%s: (null)\n", label); return; } ssl_printf("%s: (size %d)\n", label, x->size); for (i = x->size - 1; i >= 0; i--) { for (j = COMP_NUM_NIBBLES - 1; j >= 0; j--) { comp mask = 0x0f << (j * 4); comp num = (x->comps[i] & mask) >> (j * 4); os_putc((num <= 9) ? (num + '0') : (num + 'A' - 10)); } } ssl_printf("\n"); }
/** Add new RR data */ static void do_data_add(SSL* ssl, struct worker* worker, char* arg) { if(!local_zones_add_RR(worker->daemon->local_zones, arg, worker->env.scratch_buffer)) { ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg); return; } send_ok(ssl); }
/** * @brief Take a permanent object and make it eligible for freedom. * @param bi [in] The bigint to be made back to temporary. */ void ICACHE_FLASH_ATTR bi_depermanent(bigint *bi) { check(bi); if (bi->refs != PERMANENT) { #ifdef CONFIG_SSL_FULL_MODE ssl_printf("bi_depermanent: bigint was not permanent\n"); #endif return; /* wujg : org ----> abort(); */ } bi->refs = 1; }
/** dump message entry */ static int dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, time_t now) { size_t i; char* nm, *tp, *cl; if(!k || !d) return 1; if(d->ttl < now) return 1; /* expired */ nm = sldns_wire2str_dname(k->qname, k->qname_len); tp = sldns_wire2str_type(k->qtype); cl = sldns_wire2str_class(k->qclass); if(!nm || !tp || !cl) { free(nm); free(tp); free(cl); return 1; /* skip this entry */ } if(!rrset_array_lock(d->ref, d->rrset_count, now)) { /* rrsets have timed out or do not exist */ free(nm); free(tp); free(cl); return 1; /* skip this entry */ } /* meta line */ if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u\n", nm, cl, tp, (int)d->flags, (int)d->qdcount, (long long)(d->ttl-now), (int)d->security, (unsigned)d->an_numrrsets, (unsigned)d->ns_numrrsets, (unsigned)d->ar_numrrsets)) { free(nm); free(tp); free(cl); rrset_array_unlock(d->ref, d->rrset_count); return 0; } free(nm); free(tp); free(cl); for(i=0; i<d->rrset_count; i++) { if(!dump_msg_ref(ssl, d->rrsets[i])) { rrset_array_unlock(d->ref, d->rrset_count); return 0; } } rrset_array_unlock(d->ref, d->rrset_count); return 1; }
/** do the verbosity command */ static void do_verbosity(SSL* ssl, char* str) { int val = atoi(str); if(val == 0 && strcmp(str, "0") != 0) { ssl_printf(ssl, "error in verbosity number syntax: %s\n", str); return; } verbosity = val; send_ok(ssl); }
/** print root forwards */ static int print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root) { struct delegpt* dp; dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN); if(!dp) return ssl_printf(ssl, "off (using root hints)\n"); /* if dp is returned it must be the root */ log_assert(query_dname_compare(dp->name, root)==0); return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp); }
/** 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; }
/** parse commandline argument domain name */ static int parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs) { ldns_rdf* rdf; *res = NULL; *len = 0; *labs = 0; rdf = ldns_dname_new_frm_str(str); if(!rdf) { ssl_printf(ssl, "error cannot parse name %s\n", str); return 0; } *res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); ldns_rdf_deep_free(rdf); if(!*res) { ssl_printf(ssl, "error out of memory\n"); return 0; } *labs = dname_count_size_labels(*res, len); return 1; }
/* * Establish a new SSL connection to an SSL client.(raw api)add by ives 12.19.2013 */ EXP_FUNC SSL *STDCALL ICACHE_FLASH_ATTR sslserver_new(SSL_CTX *ssl_ctx, struct tcp_pcb *client_pcb) { SSL *ssl; ssl = ssl_new_context(ssl_ctx, client_pcb); ssl->next_state = HS_CLIENT_HELLO; #ifdef CONFIG_SSL_FULL_MODE if (ssl_ctx->chain_length == 0) { ssl_printf("Warning - no server certificate defined\n"); } //TTY_FLUSH(); #endif return ssl; }