static isc_result_t pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; pk11_object_t *dsa = NULL; CK_ATTRIBUTE *attr; isc_mem_t *mctx = key->mctx; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); if (key->external) { if (priv.nelements != 0) DST_RET(DST_R_INVALIDPRIVATEKEY); if (pub == NULL) DST_RET(DST_R_INVALIDPRIVATEKEY); key->keydata.pkey = pub->keydata.pkey; pub->keydata.pkey = NULL; key->key_size = pub->key_size; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); } dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa)); if (dsa == NULL) DST_RET(ISC_R_NOMEMORY); memset(dsa, 0, sizeof(*dsa)); key->keydata.pkey = dsa; dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5); if (dsa->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(dsa->repr, 0, sizeof(*attr) * 5); dsa->attrcnt = 5; attr = dsa->repr; attr[0].type = CKA_PRIME; attr[1].type = CKA_SUBPRIME; attr[2].type = CKA_BASE; attr[3].type = CKA_VALUE; attr[4].type = CKA_VALUE2; for (i = 0; i < priv.nelements; i++) { CK_BYTE *bn; bn = isc_mem_get(key->mctx, priv.elements[i].length); if (bn == NULL) DST_RET(ISC_R_NOMEMORY); memmove(bn, priv.elements[i].data, priv.elements[i].length); switch (priv.elements[i].tag) { case TAG_DSA_PRIME: attr = pk11_attribute_bytype(dsa, CKA_PRIME); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_SUBPRIME: attr = pk11_attribute_bytype(dsa, CKA_SUBPRIME); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_BASE: attr = pk11_attribute_bytype(dsa, CKA_BASE); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_PRIVATE: attr = pk11_attribute_bytype(dsa, CKA_VALUE2); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_PUBLIC: attr = pk11_attribute_bytype(dsa, CKA_VALUE); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; } } dst__privstruct_free(&priv, mctx); attr = pk11_attribute_bytype(dsa, CKA_PRIME); INSIST(attr != NULL); key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); return (ISC_R_SUCCESS); err: pkcs11dsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static void register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist, controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) { controlkey_t *keyid, *next; const cfg_obj_t *keydef; char secret[1024]; isc_buffer_t b; isc_result_t result; /* * Find the keys corresponding to the keyids used by this listener. */ for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) { next = ISC_LIST_NEXT(keyid, link); result = cfgkeylist_find(keylist, keyid->keyname, &keydef); if (result != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't find key '%s' for use with " "command channel %s", keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); } else { const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; (void)cfg_map_get(keydef, "algorithm", &algobj); (void)cfg_map_get(keydef, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm(algstr, NULL, NULL) != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel %s", algstr, keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on " "command channel %s: %s", keyid->keyname, socktext, isc_result_totext(result)); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); break; } memcpy(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); } } }
isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { isc_interfaceiter_t *iter; isc_result_t result; size_t bufsize; size_t bufused; char strbuf[ISC_STRERRORSIZE]; REQUIRE(mctx != NULL); REQUIRE(iterp != NULL); REQUIRE(*iterp == NULL); iter = isc_mem_get(mctx, sizeof(*iter)); if (iter == NULL) return (ISC_R_NOMEMORY); iter->mctx = mctx; iter->buf = 0; /* * Determine the amount of memory needed. */ bufsize = 0; if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL, ISC_MSG_GETIFLISTSIZE, "getting interface " "list size: sysctl: %s"), strbuf); result = ISC_R_UNEXPECTED; goto failure; } iter->bufsize = bufsize; iter->buf = isc_mem_get(iter->mctx, iter->bufsize); if (iter->buf == NULL) { result = ISC_R_NOMEMORY; goto failure; } bufused = bufsize; if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL, ISC_MSG_GETIFLIST, "getting interface list: " "sysctl: %s"), strbuf); result = ISC_R_UNEXPECTED; goto failure; } iter->bufused = bufused; INSIST(iter->bufused <= iter->bufsize); /* * A newly created iterator has an undefined position * until isc_interfaceiter_first() is called. */ iter->pos = (unsigned int) -1; iter->result = ISC_R_FAILURE; iter->magic = IFITER_MAGIC; *iterp = iter; return (ISC_R_SUCCESS); failure: if (iter->buf != NULL) isc_mem_put(mctx, iter->buf, iter->bufsize); isc_mem_put(mctx, iter, sizeof(*iter)); return (result); }
static isc_result_t opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { #if USE_EVP EVP_MD_CTX *evp_md_ctx; const EVP_MD *type = NULL; #endif UNUSED(key); REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || dctx->key->key_alg == DST_ALG_RSASHA256 || dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP evp_md_ctx = EVP_MD_CTX_create(); if (evp_md_ctx == NULL) return (ISC_R_NOMEMORY); switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: type = EVP_md5(); /* MD5 + RSA */ break; case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: type = EVP_sha1(); /* SHA1 + RSA */ break; #ifdef HAVE_EVP_SHA256 case DST_ALG_RSASHA256: type = EVP_sha256(); /* SHA256 + RSA */ break; #endif #ifdef HAVE_EVP_SHA512 case DST_ALG_RSASHA512: type = EVP_sha512(); break; #endif default: INSIST(0); } if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { EVP_MD_CTX_destroy(evp_md_ctx); return (dst__openssl_toresult2("EVP_DigestInit_ex", ISC_R_FAILURE)); } dctx->ctxdata.evp_md_ctx = evp_md_ctx; #else switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: { isc_md5_t *md5ctx; md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t)); if (md5ctx == NULL) return (ISC_R_NOMEMORY); isc_md5_init(md5ctx); dctx->ctxdata.md5ctx = md5ctx; } break; case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: { isc_sha1_t *sha1ctx; sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t)); if (sha1ctx == NULL) return (ISC_R_NOMEMORY); isc_sha1_init(sha1ctx); dctx->ctxdata.sha1ctx = sha1ctx; } break; case DST_ALG_RSASHA256: { isc_sha256_t *sha256ctx; sha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha256_t)); if (sha256ctx == NULL) return (ISC_R_NOMEMORY); isc_sha256_init(sha256ctx); dctx->ctxdata.sha256ctx = sha256ctx; } break; case DST_ALG_RSASHA512: { isc_sha512_t *sha512ctx; sha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha512_t)); if (sha512ctx == NULL) return (ISC_R_NOMEMORY); isc_sha512_init(sha512ctx); dctx->ctxdata.sha512ctx = sha512ctx; } break; default: INSIST(0); } #endif return (ISC_R_SUCCESS); }
static void add_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { isc_mem_t *mctx = cp->server->mctx; controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; listener = isc_mem_get(mctx, sizeof(*listener)); if (listener == NULL) result = ISC_R_NOMEMORY; if (result == ISC_R_SUCCESS) { listener->controls = cp; listener->mctx = mctx; listener->task = cp->server->task; listener->address = *addr; listener->sock = NULL; listener->listening = ISC_FALSE; listener->exiting = ISC_FALSE; listener->acl = NULL; listener->type = type; listener->perm = 0; listener->owner = 0; listener->group = 0; ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->keys); ISC_LIST_INIT(listener->connections); /* * Make the acl. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, mctx, 0, &new_acl); } else { result = dns_acl_any(mctx, &new_acl); } } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); if (config != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { result = controlkeylist_fromcfg(control_keylist, listener->mctx, &listener->keys); if (result == ISC_R_SUCCESS) register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } else result = get_rndckey(mctx, &listener->keys); if (result != ISC_R_SUCCESS && control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } if (result == ISC_R_SUCCESS) { int pf = isc_sockaddr_pf(&listener->address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || #ifdef ISC_PLATFORM_HAVESYSUNH (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) || #endif (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) result = ISC_R_FAMILYNOSUPPORT; } if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) isc_socket_cleanunix(&listener->address, ISC_FALSE); if (result == ISC_R_SUCCESS) result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(&listener->address), type, &listener->sock); if (result == ISC_R_SUCCESS) isc_socket_setname(listener->sock, "control", NULL); if (result == ISC_R_SUCCESS) result = isc_socket_bind(listener->sock, &listener->address, ISC_SOCKET_REUSEADDRESS); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { listener->perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); listener->owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); listener->group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = isc_socket_permunix(&listener->address, listener->perm, listener->owner, listener->group); } if (result == ISC_R_SUCCESS) result = control_listen(listener); if (result == ISC_R_SUCCESS) result = control_accept(listener); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "command channel listening on %s", socktext); *listenerp = listener; } else { if (listener != NULL) { listener->exiting = ISC_TRUE; free_listener(listener); } if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); *listenerp = NULL; } /* XXXDCL return error results? fail hard? */ }
int dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv) { int n = 0, major, minor; isc_buffer_t b; isc_token_t token; unsigned char *data = NULL; unsigned int opt = ISC_LEXOPT_EOL; isc_result_t ret; REQUIRE(priv != NULL); priv->nelements = 0; memset(priv->elements, 0, sizeof(priv->elements)); #define NEXTTOKEN(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret != ISC_R_SUCCESS) \ goto fail; \ } while (0) #define READLINE(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret == ISC_R_EOF) \ break; \ else if (ret != ISC_R_SUCCESS) \ goto fail; \ } while ((*token).type != isc_tokentype_eol) /* * Read the description line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || (DST_AS_STR(token))[0] != 'v') { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (major > MAJOR_VERSION || (major == MAJOR_VERSION && minor > MINOR_VERSION)) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } READLINE(lex, opt, &token); /* * Read the algorithm line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); if (token.type != isc_tokentype_number || token.value.as_ulong != (unsigned long) dst_key_alg(key)) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } READLINE(lex, opt, &token); /* * Read the key data. */ for (n = 0; n < MAXFIELDS; n++) { int tag; isc_region_t r; do { ret = isc_lex_gettoken(lex, opt, &token); if (ret == ISC_R_EOF) goto done; if (ret != ISC_R_SUCCESS) goto fail; } while (token.type == isc_tokentype_eol); if (token.type != isc_tokentype_string) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } tag = find_value(DST_AS_STR(token), alg); if (tag < 0 || TAG_ALG(tag) != alg) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); if (data == NULL) goto fail; isc_buffer_init(&b, data, MAXFIELDSIZE); ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; READLINE(lex, opt, &token); data = NULL; } done: priv->nelements = n; if (check_data(priv, alg, ISC_TRUE) < 0) goto fail; return (ISC_R_SUCCESS); fail: priv->nelements = n; dst__privstruct_free(priv, mctx); if (data != NULL) isc_mem_put(mctx, data, MAXFIELDSIZE); return (ret); }
isc_result_t isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { int fd; struct stat _stat; isc_boolean_t is_usocket = ISC_FALSE; isc_boolean_t is_connected = ISC_FALSE; isc_result_t ret; isc_entropysource_t *source; REQUIRE(VALID_ENTROPY(ent)); REQUIRE(fname != NULL); LOCK(&ent->lock); if (stat(fname, &_stat) < 0) { ret = isc__errno2result(errno); goto errout; } /* * Solaris 2.5.1 does not have support for sockets (S_IFSOCK), * but it does return type S_IFIFO (the OS believes that * the socket is a fifo). This may be an issue if we tell * the program to look at an actual FIFO as its source of * entropy. */ #if defined(S_ISSOCK) if (S_ISSOCK(_stat.st_mode)) is_usocket = ISC_TRUE; #endif #if defined(S_ISFIFO) && defined(sun) if (S_ISFIFO(_stat.st_mode)) is_usocket = ISC_TRUE; #endif if (is_usocket) fd = socket(PF_UNIX, SOCK_STREAM, 0); else fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0); if (fd < 0) { ret = isc__errno2result(errno); goto errout; } ret = make_nonblock(fd); if (ret != ISC_R_SUCCESS) goto closefd; if (is_usocket) { struct sockaddr_un sname; memset(&sname, 0, sizeof(sname)); sname.sun_family = AF_UNIX; strlcpy(sname.sun_path, fname, sizeof(sname.sun_path)); #ifdef ISC_PLATFORM_HAVESALEN #if !defined(SUN_LEN) #define SUN_LEN(su) \ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) #endif sname.sun_len = SUN_LEN(&sname); #endif if (connect(fd, (struct sockaddr *) &sname, sizeof(struct sockaddr_un)) < 0) { if (errno != EINPROGRESS) { ret = isc__errno2result(errno); goto closefd; } } else is_connected = ISC_TRUE; } source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); if (source == NULL) { ret = ISC_R_NOMEMORY; goto closefd; } /* * From here down, no failures can occur. */ source->magic = SOURCE_MAGIC; source->ent = ent; source->total = 0; source->bad = ISC_FALSE; memset(source->name, 0, sizeof(source->name)); ISC_LINK_INIT(source, link); if (is_usocket) { source->sources.usocket.handle = fd; if (is_connected) source->sources.usocket.status = isc_usocketsource_connected; else source->sources.usocket.status = isc_usocketsource_connecting; source->sources.usocket.sz_to_recv = 0; source->type = ENTROPY_SOURCETYPE_USOCKET; } else { source->sources.file.handle = fd; source->type = ENTROPY_SOURCETYPE_FILE; } /* * Hook it into the entropy system. */ ISC_LIST_APPEND(ent->sources, source, link); ent->nsources++; UNLOCK(&ent->lock); return (ISC_R_SUCCESS); closefd: (void)close(fd); errout: UNLOCK(&ent->lock); return (ret); }
isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { isc_interfaceiter_t *iter; isc_result_t result; char strbuf[ISC_STRERRORSIZE]; REQUIRE(mctx != NULL); REQUIRE(iterp != NULL); REQUIRE(*iterp == NULL); iter = isc_mem_get(mctx, sizeof(*iter)); if (iter == NULL) return (ISC_R_NOMEMORY); iter->mctx = mctx; iter->mode = 4; iter->buf = NULL; iter->pos = (unsigned int) -1; #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) iter->buf6 = NULL; iter->pos6 = (unsigned int) -1; iter->result6 = ISC_R_NOMORE; iter->socket6 = -1; iter->first6 = ISC_FALSE; #endif /* * Get the interface configuration, allocating more memory if * necessary. */ #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) result = isc_net_probeipv6(); if (result == ISC_R_SUCCESS) { /* * Create an unbound datagram socket to do the SIOCGLIFCONF * ioctl on. HP/UX requires an AF_INET6 socket for * SIOCGLIFCONF to get IPv6 addresses. */ if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_MAKESCANSOCKET, "making interface " "scan socket: %s"), strbuf); result = ISC_R_UNEXPECTED; goto socket6_failure; } result = iter->result6 = getbuf6(iter); if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS) goto ioctl6_failure; } #endif if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_MAKESCANSOCKET, "making interface " "scan socket: %s"), strbuf); result = ISC_R_UNEXPECTED; goto socket_failure; } result = getbuf4(iter); if (result != ISC_R_SUCCESS) goto ioctl_failure; /* * A newly created iterator has an undefined position * until isc_interfaceiter_first() is called. */ #ifdef HAVE_TRUCLUSTER iter->clua_context = -1; iter->clua_done = ISC_TRUE; #endif #ifdef __linux iter->proc = fopen("/proc/net/if_inet6", "r"); iter->valid = ISC_R_FAILURE; #endif iter->result = ISC_R_FAILURE; iter->magic = IFITER_MAGIC; *iterp = iter; return (ISC_R_SUCCESS); ioctl_failure: if (iter->buf != NULL) isc_mem_put(mctx, iter->buf, iter->bufsize); (void) close(iter->socket); socket_failure: #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) if (iter->buf6 != NULL) isc_mem_put(mctx, iter->buf6, iter->bufsize6); ioctl6_failure: if (iter->socket6 != -1) (void) close(iter->socket6); socket6_failure: #endif isc_mem_put(mctx, iter, sizeof(*iter)); return (result); }
static isc_result_t xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig, unsigned int maxtime, unsigned int idletime, isc_boolean_t many_answers, xfrout_ctx_t **xfrp) { xfrout_ctx_t *xfr; isc_result_t result; unsigned int len; void *mem; INSIST(xfrp != NULL && *xfrp == NULL); xfr = isc_mem_get(mctx, sizeof(*xfr)); if (xfr == NULL) return (ISC_R_NOMEMORY); xfr->mctx = NULL; isc_mem_attach(mctx, &xfr->mctx); xfr->client = NULL; ns_client_attach(client, &xfr->client); xfr->id = id; xfr->qname = qname; xfr->qtype = qtype; xfr->qclass = qclass; xfr->zone = NULL; xfr->db = NULL; xfr->ver = NULL; if (zone != NULL) /* zone will be NULL if it's DLZ */ dns_zone_attach(zone, &xfr->zone); dns_db_attach(db, &xfr->db); dns_db_attachversion(db, ver, &xfr->ver); xfr->end_of_stream = ISC_FALSE; xfr->tsigkey = tsigkey; xfr->lasttsig = lasttsig; xfr->txmem = NULL; xfr->txmemlen = 0; xfr->nmsg = 0; xfr->many_answers = many_answers, xfr->sends = 0; xfr->shuttingdown = ISC_FALSE; xfr->mnemonic = NULL; xfr->buf.base = NULL; xfr->buf.length = 0; xfr->txmem = NULL; xfr->txmemlen = 0; xfr->stream = NULL; xfr->quota = NULL; /* * Allocate a temporary buffer for the uncompressed response * message data. The size should be no more than 65535 bytes * so that the compressed data will fit in a TCP message, * and no less than 65535 bytes so that an almost maximum-sized * RR will fit. Note that although 65535-byte RRs are allowed * in principle, they cannot be zone-transferred (at least not * if uncompressible), because the message and RR headers would * push the size of the TCP message over the 65536 byte limit. */ len = 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { result = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&xfr->buf, mem, len); /* * Allocate another temporary buffer for the compressed * response message and its TCP length prefix. */ len = 2 + 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { result = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&xfr->txlenbuf, mem, 2); isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2); xfr->txmem = mem; xfr->txmemlen = len; CHECK(dns_timer_setidle(xfr->client->timer, maxtime, idletime, ISC_FALSE)); /* * Register a shutdown callback with the client, so that we * can stop the transfer immediately when the client task * gets a shutdown event. */ xfr->client->shutdown = xfrout_client_shutdown; xfr->client->shutdown_arg = xfr; /* * These MUST be after the last "goto failure;" / CHECK to * prevent a double free by the caller. */ xfr->quota = quota; xfr->stream = stream; *xfrp = xfr; return (ISC_R_SUCCESS); failure: xfrout_ctx_destroy(&xfr); return (result); }
static isc_result_t getbuf4(isc_interfaceiter_t *iter) { char strbuf[ISC_STRERRORSIZE]; iter->bufsize = IFCONF_BUFSIZE_INITIAL; for (;;) { iter->buf = isc_mem_get(iter->mctx, iter->bufsize); if (iter->buf == NULL) return (ISC_R_NOMEMORY); memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); iter->ifc.ifc_len = iter->bufsize; iter->ifc.ifc_buf = iter->buf; /* * Ignore the HP/UX warning about "integer overflow during * conversion". It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) == -1) { if (errno != EINVAL) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_GETIFCONFIG, "get interface " "configuration: %s"), strbuf); goto unexpected; } /* * EINVAL. Retry with a bigger buffer. */ } else { /* * The ioctl succeeded. * Some OS's just return what will fit rather * than set EINVAL if the buffer is too small * to fit all the interfaces in. If * ifc.lifc_len is too near to the end of the * buffer we will grow it just in case and * retry. */ if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) < iter->bufsize) break; } if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_BUFFERMAX, "get interface " "configuration: " "maximum buffer " "size exceeded")); goto unexpected; } isc_mem_put(iter->mctx, iter->buf, iter->bufsize); iter->bufsize *= 2; } return (ISC_R_SUCCESS); unexpected: isc_mem_put(iter->mctx, iter->buf, iter->bufsize); iter->buf = NULL; return (ISC_R_UNEXPECTED); }
static isc_result_t getbuf6(isc_interfaceiter_t *iter) { char strbuf[ISC_STRERRORSIZE]; isc_result_t result; iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; for (;;) { iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); if (iter->buf6 == NULL) return (ISC_R_NOMEMORY); memset(&iter->lifc, 0, sizeof(iter->lifc)); #ifdef ISC_HAVE_LIFC_FAMILY iter->lifc.lifc_family = AF_INET6; #endif #ifdef ISC_HAVE_LIFC_FLAGS iter->lifc.lifc_flags = 0; #endif iter->lifc.lifc_len = iter->bufsize6; iter->lifc.lifc_buf = iter->buf6; /* * Ignore the HP/UX warning about "integer overflow during * conversion". It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) == -1) { #ifdef __hpux /* * IPv6 interface scanning is not available on all * kernels w/ IPv6 sockets. */ if (errno == ENOENT) { isc__strerror(errno, strbuf, sizeof(strbuf)); isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_INTERFACE, ISC_LOG_DEBUG(1), isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_GETIFCONFIG, "get interface " "configuration: %s"), strbuf); result = ISC_R_FAILURE; goto cleanup; } #endif if (errno != EINVAL) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_GETIFCONFIG, "get interface " "configuration: %s"), strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } /* * EINVAL. Retry with a bigger buffer. */ } else { /* * The ioctl succeeded. * Some OS's just return what will fit rather * than set EINVAL if the buffer is too small * to fit all the interfaces in. If * ifc.ifc_len is too near to the end of the * buffer we will grow it just in case and * retry. */ if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) < iter->bufsize6) break; } if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERIOCTL, ISC_MSG_BUFFERMAX, "get interface " "configuration: " "maximum buffer " "size exceeded")); result = ISC_R_UNEXPECTED; goto cleanup; } isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); iter->bufsize6 *= 2; } if (iter->lifc.lifc_len != 0) iter->mode = 6; return (ISC_R_SUCCESS); cleanup: isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); iter->buf6 = NULL; return (result); }
static isc_result_t opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { #if USE_EVP EVP_MD_CTX *evp_md_ctx; const EVP_MD *type = NULL; #endif UNUSED(key); #ifndef PK11_MD5_DISABLE REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || dctx->key->key_alg == DST_ALG_RSASHA256 || dctx->key->key_alg == DST_ALG_RSASHA512); #else REQUIRE(dctx->key->key_alg == DST_ALG_RSASHA1 || dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || dctx->key->key_alg == DST_ALG_RSASHA256 || dctx->key->key_alg == DST_ALG_RSASHA512); #endif /* * Reject incorrect RSA key lengths. */ switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: /* From RFC 3110 */ if (dctx->key->key_size > 4096) return (ISC_R_FAILURE); break; case DST_ALG_RSASHA256: /* From RFC 5702 */ if ((dctx->key->key_size < 512) || (dctx->key->key_size > 4096)) return (ISC_R_FAILURE); break; case DST_ALG_RSASHA512: /* From RFC 5702 */ if ((dctx->key->key_size < 1024) || (dctx->key->key_size > 4096)) return (ISC_R_FAILURE); break; default: INSIST(0); } #if USE_EVP evp_md_ctx = EVP_MD_CTX_create(); if (evp_md_ctx == NULL) return (ISC_R_NOMEMORY); switch (dctx->key->key_alg) { #ifndef PK11_MD5_DISABLE case DST_ALG_RSAMD5: type = EVP_md5(); /* MD5 + RSA */ break; #endif case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: type = EVP_sha1(); /* SHA1 + RSA */ break; #ifdef HAVE_EVP_SHA256 case DST_ALG_RSASHA256: type = EVP_sha256(); /* SHA256 + RSA */ break; #endif #ifdef HAVE_EVP_SHA512 case DST_ALG_RSASHA512: type = EVP_sha512(); break; #endif default: INSIST(0); } if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { EVP_MD_CTX_destroy(evp_md_ctx); return (dst__openssl_toresult3(dctx->category, "EVP_DigestInit_ex", ISC_R_FAILURE)); } dctx->ctxdata.evp_md_ctx = evp_md_ctx; #else switch (dctx->key->key_alg) { #ifndef PK11_MD5_DISABLE case DST_ALG_RSAMD5: { isc_md5_t *md5ctx; md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t)); if (md5ctx == NULL) return (ISC_R_NOMEMORY); isc_md5_init(md5ctx); dctx->ctxdata.md5ctx = md5ctx; } break; #endif case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: { isc_sha1_t *sha1ctx; sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t)); if (sha1ctx == NULL) return (ISC_R_NOMEMORY); isc_sha1_init(sha1ctx); dctx->ctxdata.sha1ctx = sha1ctx; } break; case DST_ALG_RSASHA256: { isc_sha256_t *sha256ctx; sha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha256_t)); if (sha256ctx == NULL) return (ISC_R_NOMEMORY); isc_sha256_init(sha256ctx); dctx->ctxdata.sha256ctx = sha256ctx; } break; case DST_ALG_RSASHA512: { isc_sha512_t *sha512ctx; sha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha512_t)); if (sha512ctx == NULL) return (ISC_R_NOMEMORY); isc_sha512_init(sha512ctx); dctx->ctxdata.sha512ctx = sha512ctx; } break; default: INSIST(0); } #endif return (ISC_R_SUCCESS); }
static isc_result_t opensslrsa_tofile(const dst_key_t *key, const char *directory) { int i; RSA *rsa; dst_private_t priv; unsigned char *bufs[8]; isc_result_t result; const BIGNUM *n = NULL, *e = NULL, *d = NULL; const BIGNUM *p = NULL, *q = NULL; const BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; #if USE_EVP if (key->keydata.pkey == NULL) return (DST_R_NULLKEY); rsa = EVP_PKEY_get1_RSA(key->keydata.pkey); if (rsa == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); #else if (key->keydata.rsa == NULL) return (DST_R_NULLKEY); rsa = key->keydata.rsa; #endif memset(bufs, 0, sizeof(bufs)); RSA_get0_key(rsa, &n, &e, &d); RSA_get0_factors(rsa, &p, &q); RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); if (key->external) { priv.nelements = 0; result = dst__privstruct_writefile(key, &priv, directory); goto fail; } for (i = 0; i < 8; i++) { bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(n)); if (bufs[i] == NULL) { result = ISC_R_NOMEMORY; goto fail; } } i = 0; priv.elements[i].tag = TAG_RSA_MODULUS; priv.elements[i].length = BN_num_bytes(n); BN_bn2bin(n, bufs[i]); priv.elements[i].data = bufs[i]; i++; priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT; priv.elements[i].length = BN_num_bytes(e); BN_bn2bin(e, bufs[i]); priv.elements[i].data = bufs[i]; i++; if (d != NULL) { priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT; priv.elements[i].length = BN_num_bytes(d); BN_bn2bin(d, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (p != NULL) { priv.elements[i].tag = TAG_RSA_PRIME1; priv.elements[i].length = BN_num_bytes(p); BN_bn2bin(p, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (q != NULL) { priv.elements[i].tag = TAG_RSA_PRIME2; priv.elements[i].length = BN_num_bytes(q); BN_bn2bin(q, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (dmp1 != NULL) { priv.elements[i].tag = TAG_RSA_EXPONENT1; priv.elements[i].length = BN_num_bytes(dmp1); BN_bn2bin(dmp1, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (dmq1 != NULL) { priv.elements[i].tag = TAG_RSA_EXPONENT2; priv.elements[i].length = BN_num_bytes(dmq1); BN_bn2bin(dmq1, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (iqmp != NULL) { priv.elements[i].tag = TAG_RSA_COEFFICIENT; priv.elements[i].length = BN_num_bytes(iqmp); BN_bn2bin(iqmp, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (key->engine != NULL) { priv.elements[i].tag = TAG_RSA_ENGINE; priv.elements[i].length = (unsigned short)strlen(key->engine) + 1; priv.elements[i].data = (unsigned char *)key->engine; i++; } if (key->label != NULL) { priv.elements[i].tag = TAG_RSA_LABEL; priv.elements[i].length = (unsigned short)strlen(key->label) + 1; priv.elements[i].data = (unsigned char *)key->label; i++; } priv.nelements = i; result = dst__privstruct_writefile(key, &priv, directory); fail: #if USE_EVP RSA_free(rsa); #endif for (i = 0; i < 8; i++) { if (bufs[i] == NULL) break; isc_mem_put(key->mctx, bufs[i], BN_num_bytes(n)); } return (result); }
isc_result_t dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant, dns_name_t *identity, unsigned int matchtype, dns_name_t *name, unsigned int ntypes, dns_rdatatype_t *types) { dns_ssurule_t *rule; isc_mem_t *mctx; isc_result_t result; REQUIRE(VALID_SSUTABLE(table)); REQUIRE(dns_name_isabsolute(identity)); REQUIRE(dns_name_isabsolute(name)); REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX); if (matchtype == DNS_SSUMATCHTYPE_WILDCARD) REQUIRE(dns_name_iswildcard(name)); if (ntypes > 0) REQUIRE(types != NULL); mctx = table->mctx; rule = isc_mem_get(mctx, sizeof(dns_ssurule_t)); if (rule == NULL) return (ISC_R_NOMEMORY); rule->identity = NULL; rule->name = NULL; rule->types = NULL; rule->grant = grant; rule->identity = isc_mem_get(mctx, sizeof(dns_name_t)); if (rule->identity == NULL) { result = ISC_R_NOMEMORY; goto failure; } dns_name_init(rule->identity, NULL); result = dns_name_dup(identity, mctx, rule->identity); if (result != ISC_R_SUCCESS) goto failure; rule->name = isc_mem_get(mctx, sizeof(dns_name_t)); if (rule->name == NULL) { result = ISC_R_NOMEMORY; goto failure; } dns_name_init(rule->name, NULL); result = dns_name_dup(name, mctx, rule->name); if (result != ISC_R_SUCCESS) goto failure; rule->matchtype = matchtype; rule->ntypes = ntypes; if (ntypes > 0) { rule->types = isc_mem_get(mctx, ntypes * sizeof(dns_rdatatype_t)); if (rule->types == NULL) { result = ISC_R_NOMEMORY; goto failure; } memcpy(rule->types, types, ntypes * sizeof(dns_rdatatype_t)); } else rule->types = NULL; rule->magic = SSURULEMAGIC; ISC_LIST_INITANDAPPEND(table->rules, rule, link); return (ISC_R_SUCCESS); failure: if (rule->identity != NULL) { if (dns_name_dynamic(rule->identity)) dns_name_free(rule->identity, mctx); isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); } if (rule->name != NULL) { if (dns_name_dynamic(rule->name)) dns_name_free(rule->name, mctx); isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); } if (rule->types != NULL) isc_mem_put(mctx, rule->types, ntypes * sizeof(dns_rdatatype_t)); isc_mem_put(mctx, rule, sizeof(dns_ssurule_t)); return (result); }
isc_result_t dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, unsigned int reservelen, isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_rdatatype_t type, unsigned int flags, unsigned char **tslabp) { unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data; unsigned int ocount, ncount, count, olength, tlength, tcount, length; dns_rdata_t ordata = DNS_RDATA_INIT; dns_rdata_t nrdata = DNS_RDATA_INIT; isc_boolean_t added_something = ISC_FALSE; unsigned int oadded = 0; unsigned int nadded = 0; unsigned int nncount = 0; #if DNS_RDATASET_FIXED unsigned int oncount; unsigned int norder = 0; unsigned int oorder = 0; unsigned char *offsetbase; unsigned int *offsettable; #endif /* * XXX Need parameter to allow "delete rdatasets in nslab" merge, * or perhaps another merge routine for this purpose. */ REQUIRE(tslabp != NULL && *tslabp == NULL); REQUIRE(oslab != NULL && nslab != NULL); ocurrent = oslab + reservelen; ocount = *ocurrent++ * 256; ocount += *ocurrent++; #if DNS_RDATASET_FIXED ocurrent += (4 * ocount); #endif ostart = ocurrent; ncurrent = nslab + reservelen; ncount = *ncurrent++ * 256; ncount += *ncurrent++; #if DNS_RDATASET_FIXED ncurrent += (4 * ncount); #endif INSIST(ocount > 0 && ncount > 0); #if DNS_RDATASET_FIXED oncount = ncount; #endif /* * Yes, this is inefficient! */ /* * Figure out the length of the old slab's data. */ olength = 0; for (count = 0; count < ocount; count++) { length = *ocurrent++ * 256; length += *ocurrent++; #if DNS_RDATASET_FIXED olength += length + 8; ocurrent += length + 2; #else olength += length + 2; ocurrent += length; #endif } /* * Start figuring out the target length and count. */ tlength = reservelen + 2 + olength; tcount = ocount; /* * Add in the length of rdata in the new slab that aren't in * the old slab. */ do { dns_rdata_init(&nrdata); rdata_from_slab(&ncurrent, rdclass, type, &nrdata); if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)) { /* * This rdata isn't in the old slab. */ #if DNS_RDATASET_FIXED tlength += nrdata.length + 8; #else tlength += nrdata.length + 2; #endif if (type == dns_rdatatype_rrsig) tlength++; tcount++; nncount++; added_something = ISC_TRUE; } ncount--; } while (ncount > 0); ncount = nncount; if (((flags & DNS_RDATASLAB_EXACT) != 0) && (tcount != ncount + ocount)) return (DNS_R_NOTEXACT); if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0) return (DNS_R_UNCHANGED); /* * Ensure that singleton types are actually singletons. */ if (tcount > 1 && dns_rdatatype_issingleton(type)) { /* * We have a singleton type, but there's more than one * RR in the rdataset. */ return (DNS_R_SINGLETON); } if (tcount > 0xffff) return (ISC_R_NOSPACE); /* * Copy the reserved area from the new slab. */ tstart = isc_mem_get(mctx, tlength); if (tstart == NULL) return (ISC_R_NOMEMORY); memcpy(tstart, nslab, reservelen); tcurrent = tstart + reservelen; #if DNS_RDATASET_FIXED offsetbase = tcurrent; #endif /* * Write the new count. */ *tcurrent++ = (tcount & 0xff00) >> 8; *tcurrent++ = (tcount & 0x00ff); #if DNS_RDATASET_FIXED /* * Skip offset table. */ tcurrent += (tcount * 4); offsettable = isc_mem_get(mctx, (ocount + oncount) * sizeof(unsigned int)); if (offsettable == NULL) { isc_mem_put(mctx, tstart, tlength); return (ISC_R_NOMEMORY); } memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int)); #endif /* * Merge the two slabs. */ ocurrent = ostart; INSIST(ocount != 0); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); ncurrent = nslab + reservelen + 2; #if DNS_RDATASET_FIXED ncurrent += (4 * oncount); #endif if (ncount > 0) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } while (oadded < ocount || nadded < ncount) { isc_boolean_t fromold; if (oadded == ocount) fromold = ISC_FALSE; else if (nadded == ncount) fromold = ISC_TRUE; else fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0); if (fromold) { #if DNS_RDATASET_FIXED offsettable[oorder] = tcurrent - offsetbase; #endif length = ordata.length; data = ordata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memcpy(tcurrent, data, length); tcurrent += length; oadded++; if (oadded < ocount) { dns_rdata_reset(&ordata); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); } } else { #if DNS_RDATASET_FIXED offsettable[ocount + norder] = tcurrent - offsetbase; #endif length = nrdata.length; data = nrdata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memcpy(tcurrent, data, length); tcurrent += length; nadded++; if (nadded < ncount) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } } }
static isc_result_t process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring, dns_namelist_t *namelist) { isc_result_t result = ISC_R_SUCCESS; dns_name_t *keyname, ourname; dns_rdataset_t *keyset = NULL; dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT; isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE; dst_key_t *pubkey = NULL; isc_buffer_t ourkeybuf, *shared = NULL; isc_region_t r, r2, ourkeyr; unsigned char keydata[DST_KEY_MAXSIZE]; unsigned int sharedsize; isc_buffer_t secret; unsigned char *randomdata = NULL, secretdata[256]; dns_ttl_t ttl = 0; if (tctx->dhkey == NULL) { tkey_log("process_dhtkey: tkey-dhkey not defined"); tkeyout->error = dns_tsigerror_badalg; return (DNS_R_REFUSED); } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey_log("process_dhtkey: algorithms other than " "hmac-md5 are not supported"); tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } /* * Look for a DH KEY record that will work with ours. */ for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL); result == ISC_R_SUCCESS && !found_key; result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) { keyname = NULL; dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname); keyset = NULL; result = dns_message_findtype(keyname, dns_rdatatype_key, 0, &keyset); if (result != ISC_R_SUCCESS) continue; for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS && !found_key; result = dns_rdataset_next(keyset)) { dns_rdataset_current(keyset, &keyrdata); pubkey = NULL; result = dns_dnssec_keyfromrdata(keyname, &keyrdata, msg->mctx, &pubkey); if (result != ISC_R_SUCCESS) { dns_rdata_reset(&keyrdata); continue; } if (dst_key_alg(pubkey) == DNS_KEYALG_DH) { if (dst_key_paramcompare(pubkey, tctx->dhkey)) { found_key = ISC_TRUE; ttl = keyset->ttl; break; } else found_incompatible = ISC_TRUE; } dst_key_free(&pubkey); dns_rdata_reset(&keyrdata); } } if (!found_key) { if (found_incompatible) { tkey_log("process_dhtkey: found an incompatible key"); tkeyout->error = dns_tsigerror_badkey; return (ISC_R_SUCCESS); } else { tkey_log("process_dhtkey: failed to find a key"); return (DNS_R_FORMERR); } } RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist)); isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata)); RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf)); isc_buffer_usedregion(&ourkeybuf, &ourkeyr); dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any, dns_rdatatype_key, &ourkeyr); dns_name_init(&ourname, NULL); dns_name_clone(dst_key_name(tctx->dhkey), &ourname); /* * XXXBEW The TTL should be obtained from the database, if it exists. */ RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist)); RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize)); RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize)); result = dst_key_computesecret(pubkey, tctx->dhkey, shared); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to compute shared secret: %s", isc_result_totext(result)); goto failure; } dst_key_free(&pubkey); isc_buffer_init(&secret, secretdata, sizeof(secretdata)); randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT); if (randomdata == NULL) goto failure; result = isc_entropy_getdata(tctx->ectx, randomdata, TKEY_RANDOM_AMOUNT, NULL, 0); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to obtain entropy: %s", isc_result_totext(result)); goto failure; } r.base = randomdata; r.length = TKEY_RANDOM_AMOUNT; r2.base = tkeyin->key; r2.length = tkeyin->keylen; RETERR(compute_secret(shared, &r2, &r, &secret)); isc_buffer_free(&shared); RETERR(dns_tsigkey_create(name, &tkeyin->algorithm, isc_buffer_base(&secret), isc_buffer_usedlength(&secret), ISC_TRUE, signer, tkeyin->inception, tkeyin->expire, ring->mctx, ring, NULL)); /* This key is good for a long time */ tkeyout->inception = tkeyin->inception; tkeyout->expire = tkeyin->expire; tkeyout->key = randomdata; tkeyout->keylen = TKEY_RANDOM_AMOUNT; return (ISC_R_SUCCESS); failure: if (!ISC_LIST_EMPTY(*namelist)) free_namelist(msg, namelist); if (shared != NULL) isc_buffer_free(&shared); if (pubkey != NULL) dst_key_free(&pubkey); if (randomdata != NULL) isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT); return (result); }
/*% parses a file and fills in the data structure. */ isc_result_t irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) { FILE *fp = NULL; char word[256]; isc_result_t rval, ret; irs_resconf_t *conf; int i, stopchar; REQUIRE(mctx != NULL); REQUIRE(filename != NULL); REQUIRE(strlen(filename) > 0U); REQUIRE(confp != NULL && *confp == NULL); conf = isc_mem_get(mctx, sizeof(*conf)); if (conf == NULL) return (ISC_R_NOMEMORY); conf->mctx = mctx; ISC_LIST_INIT(conf->nameservers); conf->numns = 0; conf->domainname = NULL; conf->searchnxt = 0; conf->resdebug = 0; conf->ndots = 1; for (i = 0; i < RESCONFMAXSEARCH; i++) conf->search[i] = NULL; errno = 0; if ((fp = fopen(filename, "r")) == NULL) { isc_mem_put(mctx, conf, sizeof(*conf)); return (ISC_R_INVALIDFILE); } ret = ISC_R_SUCCESS; do { stopchar = getword(fp, word, sizeof(word)); if (stopchar == EOF) { rval = ISC_R_SUCCESS; POST(rval); break; } if (strlen(word) == 0U) rval = ISC_R_SUCCESS; else if (strcmp(word, "nameserver") == 0) rval = resconf_parsenameserver(conf, fp); else if (strcmp(word, "domain") == 0) rval = resconf_parsedomain(conf, fp); else if (strcmp(word, "search") == 0) rval = resconf_parsesearch(conf, fp); else if (strcmp(word, "sortlist") == 0) rval = resconf_parsesortlist(conf, fp); else if (strcmp(word, "options") == 0) rval = resconf_parseoption(conf, fp); else { /* unrecognised word. Ignore entire line */ rval = ISC_R_SUCCESS; stopchar = eatline(fp); if (stopchar == EOF) { break; } } if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) ret = rval; } while (1); fclose(fp); /* If we don't find a nameserver fall back to localhost */ if (conf->numns == 0) { INSIST(ISC_LIST_EMPTY(conf->nameservers)); /* XXX: should we catch errors? */ (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers); (void)add_server(conf->mctx, "::1", &conf->nameservers); } /* * Construct unified search list from domain or configured * search list */ ISC_LIST_INIT(conf->searchlist); if (conf->domainname != NULL) { ret = add_search(conf, conf->domainname); } else if (conf->searchnxt > 0) { for (i = 0; i < conf->searchnxt; i++) { ret = add_search(conf, conf->search[i]); if (ret != ISC_R_SUCCESS) break; } } conf->magic = IRS_RESCONF_MAGIC; if (ret != ISC_R_SUCCESS) irs_resconf_destroy(&conf); else *confp = conf; return (ret); }
static isc_result_t process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring) { isc_result_t result = ISC_R_SUCCESS; dst_key_t *dstkey = NULL; dns_tsigkey_t *tsigkey = NULL; dns_fixedname_t principal; isc_stdtime_t now; isc_region_t intoken; isc_buffer_t *outtoken = NULL; gss_ctx_id_t gss_ctx = NULL; /* * You have to define either a gss credential (principal) to * accept with tkey-gssapi-credential, or you have to * configure a specific keytab (with tkey-gssapi-keytab) in * order to use gsstkey */ if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) { tkey_log("process_gsstkey(): no tkey-gssapi-credential " "or tkey-gssapi-keytab configured"); return (ISC_R_NOPERM); } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkeyout->error = dns_tsigerror_badalg; tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */ return (ISC_R_SUCCESS); } /* * XXXDCL need to check for key expiry per 4.1.1 * XXXDCL need a way to check fully established, perhaps w/key_flags */ intoken.base = tkeyin->key; intoken.length = tkeyin->keylen; result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring); if (result == ISC_R_SUCCESS) gss_ctx = dst_key_getgssctx(tsigkey->key); dns_fixedname_init(&principal); /* * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set */ result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab, &intoken, &outtoken, &gss_ctx, dns_fixedname_name(&principal), tctx->mctx); if (result == DNS_R_INVALIDTKEY) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); tkeyout->error = dns_tsigerror_badkey; tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */ return (ISC_R_SUCCESS); } else if (result == ISC_R_FAILURE) goto failure; ENSURE(result == DNS_R_CONTINUE || result == ISC_R_SUCCESS); /* * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times. */ isc_stdtime_get(&now); if (tsigkey == NULL) { #ifdef GSSAPI OM_uint32 gret, minor, lifetime; #endif isc_uint32_t expire; RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey, &intoken)); /* * Limit keys to 1 hour or the context's lifetime whichever * is smaller. */ expire = now + 3600; #ifdef GSSAPI gret = gss_context_time(&minor, gss_ctx, &lifetime); if (gret == GSS_S_COMPLETE && now + lifetime < expire) expire = now + lifetime; #endif RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm, dstkey, ISC_TRUE, dns_fixedname_name(&principal), now, expire, ring->mctx, ring, NULL)); dst_key_free(&dstkey); tkeyout->inception = now; tkeyout->expire = expire; } else { tkeyout->inception = tsigkey->inception; tkeyout->expire = tkeyout->expire; dns_tsigkey_detach(&tsigkey); } if (outtoken) { tkeyout->key = isc_mem_get(tkeyout->mctx, isc_buffer_usedlength(outtoken)); if (tkeyout->key == NULL) { result = ISC_R_NOMEMORY; goto failure; } tkeyout->keylen = isc_buffer_usedlength(outtoken); memcpy(tkeyout->key, isc_buffer_base(outtoken), isc_buffer_usedlength(outtoken)); isc_buffer_free(&outtoken); } else { tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen); if (tkeyout->key == NULL) { result = ISC_R_NOMEMORY; goto failure; } tkeyout->keylen = tkeyin->keylen; memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen); } tkeyout->error = dns_rcode_noerror; tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */ return (ISC_R_SUCCESS); failure: if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (dstkey != NULL) dst_key_free(&dstkey); if (outtoken != NULL) isc_buffer_free(&outtoken); tkey_log("process_gsstkey(): %s", isc_result_totext(result)); /* XXXSRA */ return (result); }
int main(int argc, char **argv) { isc_boolean_t show_final_mem = ISC_FALSE; isc_buffer_t key_txtbuffer; char key_txtsecret[256]; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_SUCCESS; const char *keyname = NULL; const char *randomfile = NULL; const char *serveraddr = NULL; dns_secalg_t alg; const char *algname; char *p; int ch; int port; int keysize = -1; struct in_addr addr4_dummy; struct in6_addr addr6_dummy; char *chrootdir = NULL; char *user = NULL; isc_boolean_t keyonly = ISC_FALSE; int len; keydef = keyfile = RNDC_KEYFILE; result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) memmove(program, "rndc-confgen", 13); progname = program; keyname = DEFAULT_KEYNAME; alg = DST_ALG_HMACMD5; serveraddr = DEFAULT_SERVER; port = DEFAULT_PORT; isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "aA:b:c:hk:Mmp:r:s:t:u:Vy")) != -1) { switch (ch) { case 'a': keyonly = ISC_TRUE; break; case 'A': algname = isc_commandline_argument; alg = alg_fromtext(algname); if (alg == DST_ALG_UNKNOWN) fatal("Unsupported algorithm '%s'", algname); break; case 'b': keysize = strtol(isc_commandline_argument, &p, 10); if (*p != '\0' || keysize < 0) fatal("-b requires a non-negative number"); break; case 'c': keyfile = isc_commandline_argument; break; case 'h': usage(0); case 'k': case 'y': /* Compatible with rndc -y. */ keyname = isc_commandline_argument; break; case 'M': isc_mem_debugging = ISC_MEM_DEBUGTRACE; break; case 'm': show_final_mem = ISC_TRUE; break; case 'p': port = strtol(isc_commandline_argument, &p, 10); if (*p != '\0' || port < 0 || port > 65535) fatal("port '%s' out of range", isc_commandline_argument); break; case 'r': randomfile = isc_commandline_argument; break; case 's': serveraddr = isc_commandline_argument; if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) fatal("-s should be an IPv4 or IPv6 address"); break; case 't': chrootdir = isc_commandline_argument; break; case 'u': user = isc_commandline_argument; break; case 'V': verbose = ISC_TRUE; break; case '?': if (isc_commandline_option != '?') { fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); usage(1); } else usage(0); break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } argc -= isc_commandline_index; argv += isc_commandline_index; POST(argv); if (argc > 0) usage(1); if (keysize < 0) keysize = alg_bits(alg); algname = alg_totext(alg); DO("create memory context", isc_mem_create(0, 0, &mctx)); isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); if (keyonly) { write_key_file(keyfile, chrootdir == NULL ? user : NULL, keyname, &key_txtbuffer, alg); if (chrootdir != NULL) { char *buf; len = strlen(chrootdir) + strlen(keyfile) + 2; buf = isc_mem_get(mctx, len); if (buf == NULL) fatal("isc_mem_get(%d) failed\n", len); snprintf(buf, len, "%s%s%s", chrootdir, (*keyfile != '/') ? "/" : "", keyfile); write_key_file(buf, user, keyname, &key_txtbuffer, alg); isc_mem_put(mctx, buf, len); } } else { printf("\ # Start of rndc.conf\n\ key \"%s\" {\n\ algorithm %s;\n\ secret \"%.*s\";\n\ };\n\ \n\ options {\n\ default-key \"%s\";\n\ default-server %s;\n\ default-port %d;\n\ };\n\ # End of rndc.conf\n\ \n\ # Use with the following in named.conf, adjusting the allow list as needed:\n\ # key \"%s\" {\n\ # algorithm %s;\n\ # secret \"%.*s\";\n\ # };\n\ # \n\ # controls {\n\ # inet %s port %d\n\ # allow { %s; } keys { \"%s\"; };\n\ # };\n\ # End of named.conf\n", keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), keyname, serveraddr, port, keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), serveraddr, port, serveraddr, keyname); } if (show_final_mem) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); return (0); }
static isc_result_t ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret) { ns_interface_t *ifp; isc_result_t result; int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) return (ISC_R_NOMEMORY); ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; ifp->flags = 0; strncpy(ifp->name, name, sizeof(ifp->name)); ifp->name[sizeof(ifp->name)-1] = '\0'; ifp->clientmgr = NULL; result = isc_mutex_init(&ifp->lock); if (result != ISC_R_SUCCESS) goto lock_create_failure; result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr, ns_g_timermgr, &ifp->clientmgr); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ns_clientmgr_create() failed: %s", isc_result_totext(result)); goto clientmgr_create_failure; } for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) ifp->udpdispatch[disp] = NULL; ifp->tcpsocket = NULL; /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual * connections will be handled in parallel even though there is * only one client initially. */ ifp->ntcptarget = 1; ifp->ntcpcurrent = 0; ifp->nudpdispatch = 0; ISC_LINK_INIT(ifp, link); ns_interfacemgr_attach(mgr, &ifp->mgr); ISC_LIST_APPEND(mgr->interfaces, ifp, link); ifp->references = 1; ifp->magic = IFACE_MAGIC; *ifpret = ifp; return (ISC_R_SUCCESS); clientmgr_create_failure: DESTROYLOCK(&ifp->lock); lock_create_failure: ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); return (ISC_R_UNEXPECTED); }
static isc_result_t opensslrsa_tofile(const dst_key_t *key, const char *directory) { int i; RSA *rsa; dst_private_t priv; unsigned char *bufs[8]; isc_result_t result; #if USE_EVP if (key->keydata.pkey == NULL) return (DST_R_NULLKEY); rsa = EVP_PKEY_get1_RSA(key->keydata.pkey); if (rsa == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); #else if (key->keydata.rsa == NULL) return (DST_R_NULLKEY); rsa = key->keydata.rsa; #endif memset(bufs, 0, sizeof(bufs)); for (i = 0; i < 8; i++) { bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n)); if (bufs[i] == NULL) { result = ISC_R_NOMEMORY; goto fail; } } i = 0; priv.elements[i].tag = TAG_RSA_MODULUS; priv.elements[i].length = BN_num_bytes(rsa->n); BN_bn2bin(rsa->n, bufs[i]); priv.elements[i].data = bufs[i]; i++; priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT; priv.elements[i].length = BN_num_bytes(rsa->e); BN_bn2bin(rsa->e, bufs[i]); priv.elements[i].data = bufs[i]; i++; if (rsa->d != NULL) { priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT; priv.elements[i].length = BN_num_bytes(rsa->d); BN_bn2bin(rsa->d, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (rsa->p != NULL) { priv.elements[i].tag = TAG_RSA_PRIME1; priv.elements[i].length = BN_num_bytes(rsa->p); BN_bn2bin(rsa->p, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (rsa->q != NULL) { priv.elements[i].tag = TAG_RSA_PRIME2; priv.elements[i].length = BN_num_bytes(rsa->q); BN_bn2bin(rsa->q, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (rsa->dmp1 != NULL) { priv.elements[i].tag = TAG_RSA_EXPONENT1; priv.elements[i].length = BN_num_bytes(rsa->dmp1); BN_bn2bin(rsa->dmp1, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (rsa->dmq1 != NULL) { priv.elements[i].tag = TAG_RSA_EXPONENT2; priv.elements[i].length = BN_num_bytes(rsa->dmq1); BN_bn2bin(rsa->dmq1, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (rsa->iqmp != NULL) { priv.elements[i].tag = TAG_RSA_COEFFICIENT; priv.elements[i].length = BN_num_bytes(rsa->iqmp); BN_bn2bin(rsa->iqmp, bufs[i]); priv.elements[i].data = bufs[i]; i++; } if (key->engine != NULL) { priv.elements[i].tag = TAG_RSA_ENGINE; priv.elements[i].length = strlen(key->engine) + 1; priv.elements[i].data = (unsigned char *)key->engine; i++; } if (key->label != NULL) { priv.elements[i].tag = TAG_RSA_LABEL; priv.elements[i].length = strlen(key->label) + 1; priv.elements[i].data = (unsigned char *)key->label; i++; } priv.nelements = i; result = dst__privstruct_writefile(key, &priv, directory); fail: #if USE_EVP RSA_free(rsa); #endif for (i = 0; i < 8; i++) { if (bufs[i] == NULL) break; isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n)); } return (result); }
static void lookup_done(isc_task_t *task, isc_event_t *event) { ns_lwdclient_t *client; ns_lwdclientmgr_t *cm; dns_lookupevent_t *levent; lwres_buffer_t lwb; dns_name_t *name; dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; isc_result_t result; lwres_result_t lwresult; isc_region_t r; isc_buffer_t b; lwres_grbnresponse_t *grbn; int i; UNUSED(task); lwb.base = NULL; client = event->ev_arg; cm = client->clientmgr; INSIST(client->lookup == (dns_lookup_t *)event->ev_sender); levent = (dns_lookupevent_t *)event; grbn = &client->grbn; ns_lwdclient_log(50, "lookup event result = %s", isc_result_totext(levent->result)); result = levent->result; if (result != ISC_R_SUCCESS) { dns_lookup_destroy(&client->lookup); isc_event_free(&event); levent = NULL; switch (result) { case DNS_R_NXDOMAIN: case DNS_R_NCACHENXDOMAIN: result = ns_lwsearchctx_next(&client->searchctx); if (result != ISC_R_SUCCESS) lwresult = LWRES_R_NOTFOUND; else { start_lookup(client); return; } break; case DNS_R_NXRRSET: case DNS_R_NCACHENXRRSET: lwresult = LWRES_R_TYPENOTFOUND; break; default: lwresult = LWRES_R_FAILURE; } ns_lwdclient_errorpktsend(client, lwresult); return; } name = levent->name; b = client->recv_buffer; grbn->flags = 0; grbn->nrdatas = 0; grbn->rdatas = NULL; grbn->rdatalen = NULL; grbn->nsigs = 0; grbn->sigs = NULL; grbn->siglen = NULL; result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer); if (result != ISC_R_SUCCESS) goto out; grbn->realname = (char *)isc_buffer_used(&b); grbn->realnamelen = isc_buffer_usedlength(&client->recv_buffer) - isc_buffer_usedlength(&b); ns_lwdclient_log(50, "found name '%.*s'", grbn->realnamelen, grbn->realname); grbn->rdclass = cm->view->rdclass; grbn->rdtype = client->rdtype; rdataset = levent->rdataset; if (rdataset != NULL) { /* The normal case */ grbn->nrdatas = dns_rdataset_count(rdataset); grbn->rdatas = isc_mem_get(cm->mctx, grbn->nrdatas * sizeof(unsigned char *)); if (grbn->rdatas == NULL) goto out; grbn->rdatalen = isc_mem_get(cm->mctx, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->rdatalen == NULL) goto out; i = 0; result = fill_array(&i, rdataset, grbn->nrdatas, grbn->rdatas, grbn->rdatalen); if (result != ISC_R_SUCCESS) goto out; INSIST(i == grbn->nrdatas); grbn->ttl = rdataset->ttl; if (rdataset->trust == dns_trust_secure) grbn->flags |= LWRDATA_VALIDATED; } else { /* The SIG query case */ result = iterate_node(grbn, levent->db, levent->node, cm->mctx); if (result != ISC_R_SUCCESS) goto out; } ns_lwdclient_log(50, "filled in %d rdata%s", grbn->nrdatas, (grbn->nrdatas == 1) ? "" : "s"); sigrdataset = levent->sigrdataset; if (sigrdataset != NULL) { grbn->nsigs = dns_rdataset_count(sigrdataset); grbn->sigs = isc_mem_get(cm->mctx, grbn->nsigs * sizeof(unsigned char *)); if (grbn->sigs == NULL) goto out; grbn->siglen = isc_mem_get(cm->mctx, grbn->nsigs * sizeof(lwres_uint16_t)); if (grbn->siglen == NULL) goto out; i = 0; result = fill_array(&i, sigrdataset, grbn->nsigs, grbn->sigs, grbn->siglen); if (result != ISC_R_SUCCESS) goto out; INSIST(i == grbn->nsigs); ns_lwdclient_log(50, "filled in %d signature%s", grbn->nsigs, (grbn->nsigs == 1) ? "" : "s"); } dns_lookup_destroy(&client->lookup); isc_event_free(&event); /* * Render the packet. */ client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; client->pkt.result = LWRES_R_SUCCESS; lwresult = lwres_grbnresponse_render(cm->lwctx, grbn, &client->pkt, &lwb); if (lwresult != LWRES_R_SUCCESS) goto out; isc_mem_put(cm->mctx, grbn->rdatas, grbn->nrdatas * sizeof(unsigned char *)); isc_mem_put(cm->mctx, grbn->rdatalen, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->sigs != NULL) isc_mem_put(cm->mctx, grbn->sigs, grbn->nsigs * sizeof(unsigned char *)); if (grbn->siglen != NULL) isc_mem_put(cm->mctx, grbn->siglen, grbn->nsigs * sizeof(lwres_uint16_t)); r.base = lwb.base; r.length = lwb.used; client->sendbuf = r.base; client->sendlength = r.length; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) goto out2; NS_LWDCLIENT_SETSEND(client); return; out: if (grbn->rdatas != NULL) isc_mem_put(cm->mctx, grbn->rdatas, grbn->nrdatas * sizeof(unsigned char *)); if (grbn->rdatalen != NULL) isc_mem_put(cm->mctx, grbn->rdatalen, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->sigs != NULL) isc_mem_put(cm->mctx, grbn->sigs, grbn->nsigs * sizeof(unsigned char *)); if (grbn->siglen != NULL) isc_mem_put(cm->mctx, grbn->siglen, grbn->nsigs * sizeof(lwres_uint16_t)); out2: if (client->lookup != NULL) dns_lookup_destroy(&client->lookup); if (lwb.base != NULL) lwres_context_freemem(cm->lwctx, lwb.base, lwb.length); if (event != NULL) isc_event_free(&event); ns_lwdclient_log(50, "error constructing getrrsetbyname response"); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); }
static isc_result_t bdbhpt_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { isc_result_t result; int bdbhptres; int bdbFlags = 0; bdbhpt_instance_t *db = NULL; UNUSED(dlzname); UNUSED(driverarg); /* verify we have 4 arg's passed to the driver */ if (argc != 4) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "bdbhpt driver requires at least " "3 command line args."); return (ISC_R_FAILURE); } switch((char) *argv[1]) { /* * Transactional mode. Highest safety - lowest speed. */ case 'T': case 't': bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN; isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "bdbhpt driver using transactional mode."); break; /* * Concurrent mode. Lower safety (no rollback) - * higher speed. */ case 'C': case 'c': bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL; isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "bdbhpt driver using concurrent mode."); break; /* * Private mode. No inter-process communication & no locking. * Lowest saftey - highest speed. */ case 'P': case 'p': bdbFlags = DB_PRIVATE | DB_INIT_MPOOL; isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "bdbhpt driver using private mode."); break; default: isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "bdbhpt driver requires the operating mode " "be set to P or C or T. You specified '%s'", argv[1]); return (ISC_R_FAILURE); } /* allocate and zero memory for driver structure */ db = isc_mem_get(ns_g_mctx, sizeof(bdbhpt_instance_t)); if (db == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Could not allocate memory for " "database instance object."); return (ISC_R_NOMEMORY); } memset(db, 0, sizeof(bdbhpt_instance_t)); /* attach to the memory context */ isc_mem_attach(ns_g_mctx, &db->mctx); /* * create bdbhpt environment * Basically bdbhpt allocates and assigns memory to db->dbenv */ bdbhptres = db_env_create(&db->dbenv, 0); if (bdbhptres != 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "bdbhpt environment could not be created. " "bdbhpt error: %s", db_strerror(bdbhptres)); result = ISC_R_FAILURE; goto init_cleanup; } /* open bdbhpt environment */ bdbhptres = db->dbenv->open(db->dbenv, argv[2], bdbFlags | bdbhpt_threads | DB_CREATE, 0); if (bdbhptres != 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "bdbhpt environment at '%s' could not be opened." " bdbhpt error: %s", argv[2], db_strerror(bdbhptres)); result = ISC_R_FAILURE; goto init_cleanup; } /* open dlz_data database. */ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->data, dlz_data, argv[3], DB_DUP | DB_DUPSORT); if (result != ISC_R_SUCCESS) goto init_cleanup; /* open dlz_xfr database. */ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->xfr, dlz_xfr, argv[3], DB_DUP | DB_DUPSORT); if (result != ISC_R_SUCCESS) goto init_cleanup; /* open dlz_zone database. */ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->zone, dlz_zone, argv[3], 0); if (result != ISC_R_SUCCESS) goto init_cleanup; /* open dlz_client database. */ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->client, dlz_client, argv[3], DB_DUP | DB_DUPSORT); if (result != ISC_R_SUCCESS) goto init_cleanup; *dbdata = db; return(ISC_R_SUCCESS); init_cleanup: bdbhpt_cleanup(db); return result; }
static isc_result_t iterate_node(lwres_grbnresponse_t *grbn, dns_db_t *db, dns_dbnode_t *node, isc_mem_t *mctx) { int used = 0, count; int size = 8, oldsize = 0; unsigned char **rdatas = NULL, **oldrdatas = NULL, **newrdatas = NULL; lwres_uint16_t *lens = NULL, *oldlens = NULL, *newlens = NULL; dns_rdatasetiter_t *iter = NULL; dns_rdataset_t set; dns_ttl_t ttl = ISC_INT32_MAX; lwres_uint32_t flags = LWRDATA_VALIDATED; isc_result_t result = ISC_R_NOMEMORY; result = dns_db_allrdatasets(db, node, NULL, 0, &iter); if (result != ISC_R_SUCCESS) goto out; rdatas = isc_mem_get(mctx, size * sizeof(*rdatas)); if (rdatas == NULL) goto out; lens = isc_mem_get(mctx, size * sizeof(*lens)); if (lens == NULL) goto out; for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(iter)) { result = ISC_R_NOMEMORY; dns_rdataset_init(&set); dns_rdatasetiter_current(iter, &set); if (set.type != dns_rdatatype_rrsig) { dns_rdataset_disassociate(&set); continue; } count = dns_rdataset_count(&set); if (used + count > size) { /* copy & reallocate */ oldsize = size; oldrdatas = rdatas; oldlens = lens; rdatas = NULL; lens = NULL; size *= 2; rdatas = isc_mem_get(mctx, size * sizeof(*rdatas)); if (rdatas == NULL) goto out; lens = isc_mem_get(mctx, size * sizeof(*lens)); if (lens == NULL) goto out; memcpy(rdatas, oldrdatas, used * sizeof(*rdatas)); memcpy(lens, oldlens, used * sizeof(*lens)); isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas)); isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens)); oldrdatas = NULL; oldlens = NULL; } if (set.ttl < ttl) ttl = set.ttl; if (set.trust != dns_trust_secure) flags &= (~LWRDATA_VALIDATED); result = fill_array(&used, &set, size, rdatas, lens); dns_rdataset_disassociate(&set); if (result != ISC_R_SUCCESS) goto out; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; if (result != ISC_R_SUCCESS) goto out; dns_rdatasetiter_destroy(&iter); /* * If necessary, shrink and copy the arrays. */ if (size != used) { result = ISC_R_NOMEMORY; newrdatas = isc_mem_get(mctx, used * sizeof(*rdatas)); if (newrdatas == NULL) goto out; newlens = isc_mem_get(mctx, used * sizeof(*lens)); if (newlens == NULL) goto out; memcpy(newrdatas, rdatas, used * sizeof(*rdatas)); memcpy(newlens, lens, used * sizeof(*lens)); isc_mem_put(mctx, rdatas, size * sizeof(*rdatas)); isc_mem_put(mctx, lens, size * sizeof(*lens)); grbn->rdatas = newrdatas; grbn->rdatalen = newlens; } else { grbn->rdatas = rdatas; grbn->rdatalen = lens; } grbn->nrdatas = used; grbn->ttl = ttl; grbn->flags = flags; return (ISC_R_SUCCESS); out: dns_rdatasetiter_destroy(&iter); if (rdatas != NULL) isc_mem_put(mctx, rdatas, size * sizeof(*rdatas)); if (lens != NULL) isc_mem_put(mctx, lens, size * sizeof(*lens)); if (oldrdatas != NULL) isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas)); if (oldlens != NULL) isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens)); if (newrdatas != NULL) isc_mem_put(mctx, newrdatas, used * sizeof(*oldrdatas)); return (result); }
static void control_recvmessage(isc_task_t *task, isc_event_t *event) { controlconnection_t *conn; controllistener_t *listener; controlkey_t *key; isccc_sexpr_t *request = NULL; isccc_sexpr_t *response = NULL; isccc_region_t ccregion; isccc_region_t secret; isc_stdtime_t now; isc_buffer_t b; isc_region_t r; isc_uint32_t len; isc_buffer_t text; char textarray[1024]; isc_result_t result; isc_result_t eresult; isccc_sexpr_t *_ctrl; isccc_time_t sent; isccc_time_t exp; isc_uint32_t nonce; REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG); conn = event->ev_arg; listener = conn->listener; secret.rstart = NULL; /* Is the server shutting down? */ if (listener->controls->shuttingdown) goto cleanup; if (conn->ccmsg.result != ISC_R_SUCCESS) { if (conn->ccmsg.result != ISC_R_CANCELED && conn->ccmsg.result != ISC_R_EOF) log_invalid(&conn->ccmsg, conn->ccmsg.result); goto cleanup; } request = NULL; for (key = ISC_LIST_HEAD(listener->keys); key != NULL; key = ISC_LIST_NEXT(key, link)) { ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer); ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer); secret.rstart = isc_mem_get(listener->mctx, key->secret.length); if (secret.rstart == NULL) goto cleanup; memcpy(secret.rstart, key->secret.base, key->secret.length); secret.rend = secret.rstart + key->secret.length; result = isccc_cc_fromwire(&ccregion, &request, &secret); if (result == ISC_R_SUCCESS) break; isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); if (result == ISCCC_R_BADAUTH) { /* * For some reason, request is non-NULL when * isccc_cc_fromwire returns ISCCC_R_BADAUTH. */ if (request != NULL) isccc_sexpr_free(&request); } else { log_invalid(&conn->ccmsg, result); goto cleanup; } } if (key == NULL) { log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH); goto cleanup; } /* We shouldn't be getting a reply. */ if (isccc_cc_isreply(request)) { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } isc_stdtime_get(&now); /* * Limit exposure to replay attacks. */ _ctrl = isccc_alist_lookup(request, "_ctrl"); if (_ctrl == NULL) { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) { if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) { log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW); goto cleanup_request; } } else { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } /* * Expire messages that are too old. */ if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS && now > exp) { log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED); goto cleanup_request; } /* * Duplicate suppression (required for UDP). */ isccc_cc_cleansymtab(listener->controls->symtab, now); result = isccc_cc_checkdup(listener->controls->symtab, request, now); if (result != ISC_R_SUCCESS) { if (result == ISC_R_EXISTS) result = ISCCC_R_DUPLICATE; log_invalid(&conn->ccmsg, result); goto cleanup_request; } if (conn->nonce != 0 && (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS || conn->nonce != nonce)) { log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH); goto cleanup_request; } /* * Establish nonce. */ while (conn->nonce == 0) isc_random_get(&conn->nonce); isc_buffer_init(&text, textarray, sizeof(textarray)); eresult = ns_control_docommand(request, &text); result = isccc_cc_createresponse(request, now, now + 60, &response); if (result != ISC_R_SUCCESS) goto cleanup_request; if (eresult != ISC_R_SUCCESS) { isccc_sexpr_t *data; data = isccc_alist_lookup(response, "_data"); if (data != NULL) { const char *estr = isc_result_totext(eresult); if (isccc_cc_definestring(data, "err", estr) == NULL) goto cleanup_response; } } if (isc_buffer_usedlength(&text) > 0) { isccc_sexpr_t *data; data = isccc_alist_lookup(response, "_data"); if (data != NULL) { char *str = (char *)isc_buffer_base(&text); if (isccc_cc_definestring(data, "text", str) == NULL) goto cleanup_response; } } _ctrl = isccc_alist_lookup(response, "_ctrl"); if (_ctrl == NULL || isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL) goto cleanup_response; ccregion.rstart = conn->buffer + 4; ccregion.rend = conn->buffer + sizeof(conn->buffer); result = isccc_cc_towire(response, &ccregion, &secret); if (result != ISC_R_SUCCESS) goto cleanup_response; isc_buffer_init(&b, conn->buffer, 4); len = sizeof(conn->buffer) - REGION_SIZE(ccregion); isc_buffer_putuint32(&b, len - 4); r.base = conn->buffer; r.length = len; result = isc_socket_send(conn->sock, &r, task, control_senddone, conn); if (result != ISC_R_SUCCESS) goto cleanup_response; conn->sending = ISC_TRUE; isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); isccc_sexpr_free(&request); isccc_sexpr_free(&response); return; cleanup_response: isccc_sexpr_free(&response); cleanup_request: isccc_sexpr_free(&request); isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); cleanup: isc_socket_detach(&conn->sock); isccc_ccmsg_invalidate(&conn->ccmsg); conn->ccmsg_valid = ISC_FALSE; maybe_free_connection(conn); maybe_free_listener(listener); }
ISC_TASKFUNC_SCOPE isc_result_t isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp) { isc_result_t result; unsigned int i, started = 0; isc__taskmgr_t *manager; /* * Create a new task manager. */ REQUIRE(workers > 0); REQUIRE(managerp != NULL && *managerp == NULL); #ifndef USE_WORKER_THREADS UNUSED(i); UNUSED(started); #endif #ifdef USE_SHARED_MANAGER if (taskmgr != NULL) { if (taskmgr->refs == 0) return (ISC_R_SHUTTINGDOWN); taskmgr->refs++; *managerp = (isc_taskmgr_t *)taskmgr; return (ISC_R_SUCCESS); } #endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); manager->common.methods = &taskmgrmethods; manager->common.impmagic = TASK_MANAGER_MAGIC; manager->common.magic = ISCAPI_TASKMGR_MAGIC; manager->mctx = NULL; result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) goto cleanup_mgr; #ifdef USE_WORKER_THREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, workers * sizeof(isc_thread_t)); if (manager->threads == NULL) { result = ISC_R_NOMEMORY; goto cleanup_lock; } if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); result = ISC_R_UNEXPECTED; goto cleanup_threads; } if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); result = ISC_R_UNEXPECTED; goto cleanup_workavailable; } #endif /* USE_WORKER_THREADS */ if (default_quantum == 0) default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; INIT_LIST(manager->tasks); INIT_LIST(manager->ready_tasks); manager->tasks_running = 0; manager->exclusive_requested = ISC_FALSE; manager->exiting = ISC_FALSE; manager->excl = NULL; isc_mem_attach(mctx, &manager->mctx); #ifdef USE_WORKER_THREADS LOCK(&manager->lock); /* * Start workers. */ for (i = 0; i < workers; i++) { if (isc_thread_create(run, manager, &manager->threads[manager->workers]) == ISC_R_SUCCESS) { manager->workers++; started++; } } UNLOCK(&manager->lock); if (started == 0) { manager_free(manager); return (ISC_R_NOTHREADS); } isc_thread_setconcurrency(workers); #endif /* USE_WORKER_THREADS */ #ifdef USE_SHARED_MANAGER manager->refs = 1; taskmgr = manager; #endif /* USE_SHARED_MANAGER */ *managerp = (isc_taskmgr_t *)manager; return (ISC_R_SUCCESS); #ifdef USE_WORKER_THREADS cleanup_workavailable: (void)isc_condition_destroy(&manager->work_available); cleanup_threads: isc_mem_free(mctx, manager->threads); cleanup_lock: DESTROYLOCK(&manager->lock); #endif cleanup_mgr: isc_mem_put(mctx, manager, sizeof(*manager)); return (result); }
static isc_result_t get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; controlkey_t *keyid = NULL; char secret[1024]; isc_buffer_t b; CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx)); CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config)); CHECK(cfg_map_get(config, "key", &key)); keyid = isc_mem_get(mctx, sizeof(*keyid)); if (keyid == NULL) CHECK(ISC_R_NOMEMORY); keyid->keyname = isc_mem_strdup(mctx, cfg_obj_asstring(cfg_map_getname(key))); keyid->secret.base = NULL; keyid->secret.length = 0; ISC_LINK_INIT(keyid, link); if (keyid->keyname == NULL) CHECK(ISC_R_NOMEMORY); CHECK(bind9_check_key(key, ns_g_lctx)); (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm(algstr, NULL, NULL) != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel", algstr, keyid->keyname); goto cleanup; } isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on command channel: %s", keyid->keyname, isc_result_totext(result)); CHECK(result); } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); CHECK(ISC_R_NOMEMORY); } memcpy(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); ISC_LIST_APPEND(*keyids, keyid, link); keyid = NULL; result = ISC_R_SUCCESS; cleanup: if (keyid != NULL) free_controlkey(keyid, mctx); if (config != NULL) cfg_obj_destroy(pctx, &config); if (pctx != NULL) cfg_parser_destroy(&pctx); return (result); }
isc_result_t dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region, unsigned int reservelen) { struct xrdata *x; unsigned char *rawbuf; #if DNS_RDATASET_FIXED unsigned char *offsetbase; #endif unsigned int buflen; isc_result_t result; unsigned int nitems; unsigned int nalloc; unsigned int i; #if DNS_RDATASET_FIXED unsigned int *offsettable; #endif unsigned int length; buflen = reservelen + 2; nalloc = dns_rdataset_count(rdataset); nitems = nalloc; if (nitems == 0) return (ISC_R_FAILURE); if (nalloc > 0xffff) return (ISC_R_NOSPACE); x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); if (x == NULL) return (ISC_R_NOMEMORY); /* * Save all of the rdata members into an array. */ result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) goto free_rdatas; for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) { INSIST(result == ISC_R_SUCCESS); dns_rdata_init(&x[i].rdata); dns_rdataset_current(rdataset, &x[i].rdata); #if DNS_RDATASET_FIXED x[i].order = i; #endif result = dns_rdataset_next(rdataset); } if (result != ISC_R_NOMORE) goto free_rdatas; if (i != nalloc) { /* * Somehow we iterated over fewer rdatas than * dns_rdataset_count() said there were! */ result = ISC_R_FAILURE; goto free_rdatas; } /* * Put into DNSSEC order. */ qsort(x, nalloc, sizeof(struct xrdata), compare_rdata); /* * Remove duplicates and compute the total storage required. * * If an rdata is not a duplicate, accumulate the storage size * required for the rdata. We do not store the class, type, etc, * just the rdata, so our overhead is 2 bytes for the number of * records, and 8 for each rdata, (length(2), offset(4) and order(2)) * and then the rdata itself. */ for (i = 1; i < nalloc; i++) { if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) { x[i-1].rdata.data = NULL; x[i-1].rdata.length = 0; #if DNS_RDATASET_FIXED /* * Preserve the least order so A, B, A -> A, B * after duplicate removal. */ if (x[i-1].order < x[i].order) x[i].order = x[i-1].order; #endif nitems--; } else { #if DNS_RDATASET_FIXED buflen += (8 + x[i-1].rdata.length); #else buflen += (2 + x[i-1].rdata.length); #endif /* * Provide space to store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) buflen++; } } /* * Don't forget the last item! */ #if DNS_RDATASET_FIXED buflen += (8 + x[i-1].rdata.length); #else buflen += (2 + x[i-1].rdata.length); #endif /* * Provide space to store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) buflen++; /* * Ensure that singleton types are actually singletons. */ if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) { /* * We have a singleton type, but there's more than one * RR in the rdataset. */ result = DNS_R_SINGLETON; goto free_rdatas; } /* * Allocate the memory, set up a buffer, start copying in * data. */ rawbuf = isc_mem_get(mctx, buflen); if (rawbuf == NULL) { result = ISC_R_NOMEMORY; goto free_rdatas; } #if DNS_RDATASET_FIXED /* Allocate temporary offset table. */ offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int)); if (offsettable == NULL) { isc_mem_put(mctx, rawbuf, buflen); result = ISC_R_NOMEMORY; goto free_rdatas; } memset(offsettable, 0, nalloc * sizeof(unsigned int)); #endif region->base = rawbuf; region->length = buflen; rawbuf += reservelen; #if DNS_RDATASET_FIXED offsetbase = rawbuf; #endif *rawbuf++ = (nitems & 0xff00) >> 8; *rawbuf++ = (nitems & 0x00ff); #if DNS_RDATASET_FIXED /* Skip load order table. Filled in later. */ rawbuf += nitems * 4; #endif for (i = 0; i < nalloc; i++) { if (x[i].rdata.data == NULL) continue; #if DNS_RDATASET_FIXED offsettable[x[i].order] = rawbuf - offsetbase; #endif length = x[i].rdata.length; if (rdataset->type == dns_rdatatype_rrsig) length++; *rawbuf++ = (length & 0xff00) >> 8; *rawbuf++ = (length & 0x00ff); #if DNS_RDATASET_FIXED rawbuf += 2; /* filled in later */ #endif /* * Store the per RR meta data. */ if (rdataset->type == dns_rdatatype_rrsig) { *rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ? DNS_RDATASLAB_OFFLINE : 0; } memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length); rawbuf += x[i].rdata.length; } #if DNS_RDATASET_FIXED fillin_offsets(offsetbase, offsettable, nalloc); isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int)); #endif result = ISC_R_SUCCESS; free_rdatas: isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); return (result); }
isc_result_t dst_key_fromnamedfile(const char *filename, const char *dirname, int type, isc_mem_t *mctx, dst_key_t **keyp) { isc_result_t result; dst_key_t *pubkey = NULL, *key = NULL; char *newfilename = NULL; int newfilenamelen = 0; isc_lex_t *lex = NULL; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(filename != NULL); REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); /* If an absolute path is specified, don't use the key directory */ #ifndef WIN32 if (filename[0] == '/') dirname = NULL; #else /* WIN32 */ if (filename[0] == '/' || filename[0] == '\\') dirname = NULL; #endif newfilenamelen = strlen(filename) + 5; if (dirname != NULL) newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) return (ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, dirname, filename, ".key"); INSIST(result == ISC_R_SUCCESS); result = dst_key_read_public(newfilename, type, mctx, &pubkey); isc_mem_put(mctx, newfilename, newfilenamelen); newfilename = NULL; if (result != ISC_R_SUCCESS) return (result); if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { result = computeid(pubkey); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } *keyp = pubkey; return (ISC_R_SUCCESS); } result = algorithm_status(pubkey->key_alg); if (result != ISC_R_SUCCESS) { dst_key_free(&pubkey); return (result); } key = get_key_struct(pubkey->key_name, pubkey->key_alg, pubkey->key_flags, pubkey->key_proto, 0, pubkey->key_class, mctx); if (key == NULL) { dst_key_free(&pubkey); return (ISC_R_NOMEMORY); } if (key->func->parse == NULL) RETERR(DST_R_UNSUPPORTEDALG); newfilenamelen = strlen(filename) + 9; if (dirname != NULL) newfilenamelen += strlen(dirname) + 1; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) RETERR(ISC_R_NOMEMORY); result = addsuffix(newfilename, newfilenamelen, dirname, filename, ".private"); INSIST(result == ISC_R_SUCCESS); RETERR(isc_lex_create(mctx, 1500, &lex)); RETERR(isc_lex_openfile(lex, newfilename)); isc_mem_put(mctx, newfilename, newfilenamelen); RETERR(key->func->parse(key, lex, pubkey)); isc_lex_destroy(&lex); RETERR(computeid(key)); if (pubkey->key_id != key->key_id) RETERR(DST_R_INVALIDPRIVATEKEY); dst_key_free(&pubkey); *keyp = key; return (ISC_R_SUCCESS); out: if (pubkey != NULL) dst_key_free(&pubkey); if (newfilename != NULL) isc_mem_put(mctx, newfilename, newfilenamelen); if (lex != NULL) isc_lex_destroy(&lex); dst_key_free(&key); return (result); }
static isc_result_t pkcs11dsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { CK_RV rv; CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 }; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_DSA; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_PRIME, NULL, 0 }, { CKA_SUBPRIME, NULL, 0 }, { CKA_BASE, NULL, 0 }, { CKA_VALUE, NULL, 0 } }; CK_ATTRIBUTE *attr; pk11_object_t *dsa; pk11_context_t *pk11_ctx; isc_result_t ret; unsigned int i; pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE, ISC_FALSE, NULL, pk11_get_best_token(OP_DSA)); if (ret != ISC_R_SUCCESS) goto err; dsa = key->keydata.pkey; if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) { pk11_ctx->ontoken = dsa->ontoken; pk11_ctx->object = dsa->object; goto token_key; } for (attr = pk11_attribute_first(dsa); attr != NULL; attr = pk11_attribute_next(dsa, attr)) switch (attr->type) { case CKA_PRIME: INSIST(keyTemplate[6].type == attr->type); keyTemplate[6].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[6].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); keyTemplate[6].ulValueLen = attr->ulValueLen; break; case CKA_SUBPRIME: INSIST(keyTemplate[7].type == attr->type); keyTemplate[7].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[7].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen); keyTemplate[7].ulValueLen = attr->ulValueLen; break; case CKA_BASE: INSIST(keyTemplate[8].type == attr->type); keyTemplate[8].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[8].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen); keyTemplate[8].ulValueLen = attr->ulValueLen; break; case CKA_VALUE2: INSIST(keyTemplate[9].type == CKA_VALUE); keyTemplate[9].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[9].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[9].pValue, attr->pValue, attr->ulValueLen); keyTemplate[9].ulValueLen = attr->ulValueLen; break; } pk11_ctx->object = CK_INVALID_HANDLE; pk11_ctx->ontoken = ISC_FALSE; PK11_RET(pkcs_C_CreateObject, (pk11_ctx->session, keyTemplate, (CK_ULONG) 10, &pk11_ctx->object), ISC_R_FAILURE); token_key: PK11_RET(pkcs_C_SignInit, (pk11_ctx->session, &mech, pk11_ctx->object), ISC_R_FAILURE); dctx->ctxdata.pk11_ctx = pk11_ctx; for (i = 6; i <= 9; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } return (ISC_R_SUCCESS); err: if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); for (i = 6; i <= 9; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }