📄 dst_api.c
字号:
dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx, dst_key_t **keyp){ dst_key_t *key; REQUIRE(opaque != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0, dns_rdataclass_in, mctx); if (key == NULL) return (ISC_R_NOMEMORY); key->opaque = opaque; *keyp = key; return (ISC_R_SUCCESS);}isc_result_tdst_key_generate(dns_name_t *name, unsigned int alg, unsigned int bits, unsigned int param, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp){ dst_key_t *key; isc_result_t ret; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(dns_name_isabsolute(name)); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); CHECKALG(alg); key = get_key_struct(name, alg, flags, protocol, bits, rdclass, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (bits == 0) { /* NULL KEY */ key->key_flags |= DNS_KEYTYPE_NOKEY; *keyp = key; return (ISC_R_SUCCESS); } if (key->func->generate == NULL) { dst_key_free(&key); return (DST_R_UNSUPPORTEDALG); } ret = key->func->generate(key, param); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } ret = computeid(key); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } *keyp = key; return (ISC_R_SUCCESS);}isc_boolean_tdst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key1)); REQUIRE(VALID_KEY(key2)); if (key1 == key2) return (ISC_TRUE); if (key1 == NULL || key2 == NULL) return (ISC_FALSE); if (key1->key_alg == key2->key_alg && key1->key_id == key2->key_id && key1->func->compare != NULL && key1->func->compare(key1, key2) == ISC_TRUE) return (ISC_TRUE); else return (ISC_FALSE);}isc_boolean_tdst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key1)); REQUIRE(VALID_KEY(key2)); if (key1 == key2) return (ISC_TRUE); if (key1 == NULL || key2 == NULL) return (ISC_FALSE); if (key1->key_alg == key2->key_alg && key1->func->paramcompare != NULL && key1->func->paramcompare(key1, key2) == ISC_TRUE) return (ISC_TRUE); else return (ISC_FALSE);}voiddst_key_free(dst_key_t **keyp) { isc_mem_t *mctx; dst_key_t *key; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(keyp != NULL && VALID_KEY(*keyp)); key = *keyp; mctx = key->mctx; if (key->opaque != NULL) { INSIST(key->func->destroy != NULL); key->func->destroy(key); } dns_name_free(key->key_name, mctx); isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); memset(key, 0, sizeof(dst_key_t)); isc_mem_put(mctx, key, sizeof(dst_key_t)); *keyp = NULL;}isc_boolean_tdst_key_isprivate(const dst_key_t *key) { REQUIRE(VALID_KEY(key)); INSIST(key->func->isprivate != NULL); return (key->func->isprivate(key));}isc_result_tdst_key_buildfilename(const dst_key_t *key, int type, const char *directory, isc_buffer_t *out) { REQUIRE(VALID_KEY(key)); REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC || type == 0); return (buildfilename(key->key_name, key->key_id, key->key_alg, type, directory, out));}isc_result_tdst_key_sigsize(const dst_key_t *key, unsigned int *n) { REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key)); REQUIRE(n != NULL); /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (key->key_alg) { case DST_ALG_RSAMD5: case DST_ALG_RSASHA1: *n = (key->key_size + 7) / 8; break; case DST_ALG_DSA: *n = DNS_SIG_DSASIGSIZE; break; case DST_ALG_HMACMD5: *n = 16; break; case DST_ALG_GSSAPI: *n = 128; /* XXX */ break; case DST_ALG_DH: default: return (DST_R_UNSUPPORTEDALG); } return (ISC_R_SUCCESS);}isc_result_tdst_key_secretsize(const dst_key_t *key, unsigned int *n) { REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key)); REQUIRE(n != NULL); if (key->key_alg == DST_ALG_DH) *n = (key->key_size + 7) / 8; else return (DST_R_UNSUPPORTEDALG); return (ISC_R_SUCCESS);}/*** *** Static methods ***//* * Allocates a key structure and fills in some of the fields. */static dst_key_t *get_key_struct(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, unsigned int bits, dns_rdataclass_t rdclass, isc_mem_t *mctx){ dst_key_t *key; isc_result_t result; key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t)); if (key == NULL) return (NULL); memset(key, 0, sizeof(dst_key_t)); key->magic = KEY_MAGIC; key->key_name = isc_mem_get(mctx, sizeof(dns_name_t)); if (key->key_name == NULL) { isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } dns_name_init(key->key_name, NULL); result = dns_name_dup(name, mctx, key->key_name); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } key->key_alg = alg; key->key_flags = flags; key->key_proto = protocol; key->mctx = mctx; key->opaque = NULL; key->key_size = bits; key->key_class = rdclass; key->func = dst_t_func[alg]; return (key);}/* * Reads a public key from disk */static isc_result_tread_public_key(const char *filename, int type, isc_mem_t *mctx, dst_key_t **keyp){ u_char rdatabuf[DST_KEY_MAXSIZE]; isc_buffer_t b; dns_fixedname_t name; isc_lex_t *lex = NULL; isc_token_t token; isc_result_t ret; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int opt = ISC_LEXOPT_DNSMULTILINE; char *newfilename; unsigned int newfilenamelen; dns_rdataclass_t rdclass = dns_rdataclass_in; isc_lexspecials_t specials; isc_uint32_t ttl; isc_result_t result; dns_rdatatype_t keytype; newfilenamelen = strlen(filename) + 5; newfilename = isc_mem_get(mctx, newfilenamelen); if (newfilename == NULL) return (ISC_R_NOMEMORY); ret = addsuffix(newfilename, newfilenamelen, filename, ".key"); INSIST(ret == ISC_R_SUCCESS); /* * Open the file and read its formatted contents * File format: * domain.name [ttl] [class] KEY <flags> <protocol> <algorithm> <key> */ /* 1500 should be large enough for any key */ ret = isc_lex_create(mctx, 1500, &lex); if (ret != ISC_R_SUCCESS) goto cleanup; memset(specials, 0, sizeof(specials)); specials['('] = 1; specials[')'] = 1; specials['"'] = 1; isc_lex_setspecials(lex, specials); isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); ret = isc_lex_openfile(lex, newfilename); if (ret != ISC_R_SUCCESS) goto cleanup;#define NEXTTOKEN(lex, opt, token) { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret != ISC_R_SUCCESS) \ goto cleanup; \ }#define BADTOKEN() { \ ret = ISC_R_UNEXPECTEDTOKEN; \ goto cleanup; \ } /* Read the domain name */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string) BADTOKEN(); dns_fixedname_init(&name); isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); isc_buffer_add(&b, strlen(DST_AS_STR(token))); ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, ISC_FALSE, NULL); if (ret != ISC_R_SUCCESS) goto cleanup; /* Read the next word: either TTL, class, or 'KEY' */ NEXTTOKEN(lex, opt, &token); /* If it's a TTL, read the next one */ result = dns_ttl_fromtext(&token.value.as_textregion, &ttl); if (result == ISC_R_SUCCESS) NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string) BADTOKEN(); ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion); if (ret == ISC_R_SUCCESS) NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string) BADTOKEN(); if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) keytype = dns_rdatatype_dnskey; else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) keytype = dns_rdatatype_key; /* SIG(0), TKEY */ else BADTOKEN(); if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) || ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) { ret = DST_R_BADKEYTYPE; goto cleanup; } isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, ISC_FALSE, mctx, &b, NULL); if (ret != ISC_R_SUCCESS) goto cleanup; ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx, keyp); if (ret != ISC_R_SUCCESS) goto cleanup; cleanup: if (lex != NULL) isc_lex_destroy(&lex); isc_mem_put(mctx, newfilename, newfilenamelen); return (ret);}static isc_boolean_tissymmetric(const dst_key_t *key) { REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(VALID_KEY(key)); /* XXXVIX this switch statement is too sparse to gen a jump table. */ switch (key->key_alg) { case DST_ALG_RSAMD5: case DST_ALG_RSASHA1: case DST_ALG_DSA: case DST_ALG_DH: return (ISC_FALSE); case DST_ALG_HMACMD5: case DST_ALG_GSSAPI: return (ISC_TRUE); default: return (ISC_FALSE); }}/* * Writes a public key to disk in DNS format. */static isc_result_twrite_public_key(const dst_key_t *key, int type, const char *directory) { FILE *fp; isc_buffer_t keyb, textb, fileb, classb; isc_region_t r; char filename[ISC_DIR_NAMEMAX]; unsigned char key_array[DST_KEY_MAXSIZE]; char text_array[DST_KEY_MAXTEXTSIZE]; char class_array[10]; isc_result_t ret; dns_rdata_t rdata = DNS_RDATA_INIT; isc_fsaccess_t access; REQUIRE(VALID_KEY(key)); isc_buffer_init(&keyb, key_array, sizeof(key_array)); isc_buffer_init(&textb, text_array, sizeof(text_array)); isc_buffer_init(&classb, class_array, sizeof(class_array)); ret = dst_key_todns(key, &keyb); if (ret != ISC_R_SUCCESS) return (ret); isc_buffer_usedregion(&keyb, &r); dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r); ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb); if (ret != ISC_R_SUCCESS) return (DST_R_INVALIDPUBLICKEY); ret = dns_rdataclass_totext(key->key_class, &classb); if (ret != ISC_R_SUCCESS) return (DST_R_INVALIDPUBLICKEY); /* * Make the filename. */ isc_buffer_init(&fileb, filename, sizeof(filename)); ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb); if (ret != ISC_R_SUCCESS) return (ret); /* * Create public key file. */ if ((fp = fopen(filename, "w")) == NULL) return (DST_R_WRITEERROR); if (issymmetric(key)) { access = 0; isc_fsaccess_add(ISC_FSACCESS_OWNER, ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, &access); (void)isc_fsaccess_set(filename, access); } ret = dns_name_print(key->key_name, fp); if (ret != ISC_R_SUCCESS) return (ret); fprintf(fp, " "); isc_buffer_usedregion(&classb, &r); fwrite(r.base, 1, r.length, fp); if ((type & DST_TYPE_KEY) != 0) fprintf(fp, " KEY "); else fprintf(fp, " DNSKEY "); isc_buffer_usedregion(&textb, &r); fwrite(r.base, 1, r.length, fp); fputc('\n', fp); fclose(fp); return (ISC_R_SUCCESS);}static isc_result_tbuildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, unsigned int type, const char *directory, isc_buffer_t *out){ const char *suffix = ""; unsigned int len; isc_result_t result; REQUIRE(out != NULL); if ((type & DST_TYPE_PRIVATE) != 0) suffix = ".private"; else if (type == DST_TYPE_PUBLIC) suffix = ".key"; if (directory != NULL) { if (isc_buffer_availablelength(out) < strlen(directory)) return (ISC_R_NOSPACE); isc_buffer_putstr(out, directory); if (strlen(directory) > 0U && directory[strlen(directory) - 1] != '/') isc_buffer_putstr(out, "/"); } if (isc_buffer_availablelength(out) < 1) return (ISC_R_NOSPACE); isc_buffer_putstr(out, "K"); result = dns_name_tofilenametext(name, ISC_FALSE, out); if (result != ISC_R_SUCCESS) return (result); len = 1 + 3 + 1 + 5 + strlen(suffix) + 1; if (isc_buffer_availablelength(out) < len) return (ISC_R_NOSPACE); sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id, suffix); isc_buffer_add(out, len); return (ISC_R_SUCCESS);}static isc_result_tcomputeid(dst_key_t *key) { isc_buffer_t dnsbuf; unsigned char dns_array[DST_KEY_MAXSIZE]; isc_region_t r; isc_result_t ret; isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array)); ret = dst_key_todns(key, &dnsbuf); if (ret != ISC_R_SUCCESS) return (ret); isc_buffer_usedregion(&dnsbuf, &r); key->key_id = dst_region_computeid(&r, key->key_alg); return (ISC_R_SUCCESS);}static isc_result_tfrombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp){ dst_key_t *key; isc_result_t ret; REQUIRE(dns_name_isabsolute(name)); REQUIRE(source != NULL); REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx); if (key == NULL) return (ISC_R_NOMEMORY); if (isc_buffer_remaininglength(source) > 0) { ret = algorithm_status(alg); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } if (key->func->fromdns == NULL) { dst_key_free(&key); return (DST_R_UNSUPPORTEDALG); } ret = key->func->fromdns(key, source); if (ret != ISC_R_SUCCESS) { dst_key_free(&key); return (ret); } } *keyp = key; return (ISC_R_SUCCESS);}static isc_result_talgorithm_status(unsigned int alg) { REQUIRE(dst_initialized == ISC_TRUE); if (dst_algorithm_supported(alg)) return (ISC_R_SUCCESS);#ifndef OPENSSL if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || alg == DST_ALG_DSA || alg == DST_ALG_DH || alg == DST_ALG_HMACMD5) return (DST_R_NOCRYPTO);#endif return (DST_R_UNSUPPORTEDALG);}static isc_result_taddsuffix(char *filename, unsigned int len, const char *ofilename, const char *suffix){ int olen = strlen(ofilename); int n; if (olen > 1 && ofilename[olen - 1] == '.') olen -= 1; else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) olen -= 8; else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) olen -= 4; n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); if (n < 0) return (ISC_R_NOSPACE); return (ISC_R_SUCCESS);}isc_result_tdst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { unsigned int flags = dst_entropy_flags; if (pseudo) flags &= ~ISC_ENTROPY_GOODONLY; return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -