diff options
Diffstat (limited to 'lib/dns/dst_parse.c')
| -rw-r--r-- | lib/dns/dst_parse.c | 64 | 
1 files changed, 49 insertions, 15 deletions
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index ca43cb3d12414..2b950d5a3b9cf 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -1,5 +1,5 @@  /* - * Portions Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2013  Internet Systems Consortium, Inc. ("ISC")   * Portions Copyright (C) 1999-2002  Internet Software Consortium.   *   * Permission to use, copy, modify, and/or distribute this software for any @@ -178,14 +178,18 @@ find_numericdata(const char *s) {  }  static int -check_rsa(const dst_private_t *priv) { +check_rsa(const dst_private_t *priv, isc_boolean_t external) {  	int i, j;  	isc_boolean_t have[RSA_NTAGS];  	isc_boolean_t ok;  	unsigned int mask; +	if (external) +		return ((priv->nelements == 0) ? 0 : -1); +  	for (i = 0; i < RSA_NTAGS; i++)  		have[i] = ISC_FALSE; +  	for (j = 0; j < priv->nelements; j++) {  		for (i = 0; i < RSA_NTAGS; i++)  			if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i)) @@ -231,10 +235,15 @@ check_dh(const dst_private_t *priv) {  }  static int -check_dsa(const dst_private_t *priv) { +check_dsa(const dst_private_t *priv, isc_boolean_t external) {  	int i, j; + +	if (external) +		return ((priv->nelements == 0)? 0 : -1); +  	if (priv->nelements != DSA_NTAGS)  		return (-1); +  	for (i = 0; i < DSA_NTAGS; i++) {  		for (j = 0; j < priv->nelements; j++)  			if (priv->elements[j].tag == TAG(DST_ALG_DSA, i)) @@ -246,7 +255,11 @@ check_dsa(const dst_private_t *priv) {  }  static int -check_gost(const dst_private_t *priv) { +check_gost(const dst_private_t *priv, isc_boolean_t external) { + +	if (external) +		return ((priv->nelements == 0)? 0 : -1); +  	if (priv->nelements != GOST_NTAGS)  		return (-1);  	if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) @@ -255,7 +268,11 @@ check_gost(const dst_private_t *priv) {  }  static int -check_ecdsa(const dst_private_t *priv) { +check_ecdsa(const dst_private_t *priv, isc_boolean_t external) { + +	if (external) +		return ((priv->nelements == 0) ? 0 : -1); +  	if (priv->nelements != ECDSA_NTAGS)  		return (-1);  	if (priv->elements[0].tag != TAG(DST_ALG_ECDSA256, 0)) @@ -309,7 +326,7 @@ check_hmac_sha(const dst_private_t *priv, unsigned int ntags,  static int  check_data(const dst_private_t *priv, const unsigned int alg, -	   isc_boolean_t old) +	   isc_boolean_t old, isc_boolean_t external)  {  	/* XXXVIX this switch statement is too sparse to gen a jump table. */  	switch (alg) { @@ -318,17 +335,17 @@ check_data(const dst_private_t *priv, const unsigned int alg,  	case DST_ALG_NSEC3RSASHA1:  	case DST_ALG_RSASHA256:  	case DST_ALG_RSASHA512: -		return (check_rsa(priv)); +		return (check_rsa(priv, external));  	case DST_ALG_DH:  		return (check_dh(priv));  	case DST_ALG_DSA:  	case DST_ALG_NSEC3DSA: -		return (check_dsa(priv)); +		return (check_dsa(priv, external));  	case DST_ALG_ECCGOST: -		return (check_gost(priv)); +		return (check_gost(priv, external));  	case DST_ALG_ECDSA256:  	case DST_ALG_ECDSA384: -		return (check_ecdsa(priv)); +		return (check_ecdsa(priv, external));  	case DST_ALG_HMACMD5:  		return (check_hmac_md5(priv, old));  	case DST_ALG_HMACSHA1: @@ -372,6 +389,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,  	unsigned int opt = ISC_LEXOPT_EOL;  	isc_stdtime_t when;  	isc_result_t ret; +	isc_boolean_t external = ISC_FALSE;  	REQUIRE(priv != NULL); @@ -470,6 +488,11 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,  			goto fail;  		} +		if (strcmp(DST_AS_STR(token), "External:") == 0) { +			external = ISC_TRUE; +			goto next; +		} +  		/* Numeric metadata */  		tag = find_numericdata(DST_AS_STR(token));  		if (tag >= 0) { @@ -534,8 +557,14 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,  		READLINE(lex, opt, &token);  		data = NULL;  	} +   done: -	check = check_data(priv, alg, ISC_TRUE); +	if (external && priv->nelements != 0) { +		ret = DST_R_INVALIDPRIVATEKEY; +		goto fail; +	} + +	check = check_data(priv, alg, ISC_TRUE, external);  	if (check < 0) {  		ret = DST_R_INVALIDPRIVATEKEY;  		goto fail; @@ -544,6 +573,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,  		goto fail;  	} +	key->external = external; +  	return (ISC_R_SUCCESS);  fail: @@ -573,7 +604,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,  	REQUIRE(priv != NULL); -	ret = check_data(priv, dst_key_alg(key), ISC_FALSE); +	ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external);  	if (ret < 0)  		return (DST_R_INVALIDPRIVATEKEY);  	else if (ret != ISC_R_SUCCESS) @@ -691,6 +722,9 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,  	       fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);  	} +	if (key->external) +	       fprintf(fp, "External:\n"); +  	/* Add the metadata tags */  	if (major > 1 || (major == 1 && minor >= 3)) {  		for (i = 0; i < NUMERIC_NTAGS; i++) { @@ -706,14 +740,14 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,  			isc_buffer_init(&b, buffer, sizeof(buffer));  			result = dns_time32_totext(when, &b); -		       if (result != ISC_R_SUCCESS) { +			if (result != ISC_R_SUCCESS) {  			       fclose(fp);  			       return (DST_R_INVALIDPRIVATEKEY); -		       } +			}  			isc_buffer_usedregion(&b, &r); -		       fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length, +			fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,  				r.base);  		}  	}  | 
