324 lines
8.5 KiB
C
324 lines
8.5 KiB
C
/* $NetBSD: dnskeygen.c,v 1.5 2002/06/20 11:42:54 itojun Exp $ */
|
|
|
|
#if !defined(lint) && !defined(SABER)
|
|
static const char rcsid[] = "Id: dnskeygen.c,v 1.14 2001/09/25 04:50:14 marka Exp";
|
|
#endif /* not lint */
|
|
|
|
/*
|
|
* Portions Copyright (c) 1995-1999 by TISLabs at Network Associates, Inc.
|
|
*
|
|
* Permission to use, copy modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND NETWORK ASSOCIATES
|
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
|
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
|
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
|
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
|
*/
|
|
|
|
#include "port_before.h"
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include "arpa/nameser.h"
|
|
|
|
#include <isc/dst.h>
|
|
|
|
#include "port_after.h"
|
|
|
|
#define PRINT_SUPPORTED 2
|
|
#ifndef PATH_SEP
|
|
#define PATH_SEP '/'
|
|
#endif
|
|
|
|
static void usage(const char *str, int full);
|
|
|
|
static short dsa_sizes[] = {512, 576, 640, 704, 768, 832, 896, 960, 1024, 0};
|
|
static char *prog;
|
|
|
|
int
|
|
main(int argc, char **argv) {
|
|
DST_KEY *pubkey;
|
|
char *name=NULL;
|
|
int ch;
|
|
char str[128];
|
|
int alg = 0;
|
|
int zone_key = 0, user_key = 0, end_key = 0, key_type = 0;
|
|
int size = -1, exp = 0;
|
|
int no_auth = 0, no_conf = 0;
|
|
int sign_val = 0, flags = 0, protocol = -1;
|
|
int i, err = 0;
|
|
extern char *optarg;
|
|
|
|
dst_init();
|
|
if ((prog = strrchr(argv[0], PATH_SEP)) == NULL)
|
|
prog = strdup(argv[0]);
|
|
else
|
|
prog = strdup(++prog);
|
|
|
|
/* process input arguments */
|
|
while ((ch = getopt(argc, argv, "achiuzn:s:p:D:H:R:F"))!= -1) {
|
|
switch (ch) {
|
|
case 'a':
|
|
no_auth = NS_KEY_NO_AUTH;
|
|
break;
|
|
case 'c':
|
|
no_conf = NS_KEY_NO_CONF;
|
|
break;
|
|
case 'F':
|
|
exp=1;
|
|
break;
|
|
case 'n':
|
|
if (optarg)
|
|
name = strdup(optarg);
|
|
else
|
|
usage("-n not followed by name", 0);
|
|
i = strlen(name);
|
|
if (name[i-1] != '.') {
|
|
printf("** Adding dot to the name to make it"
|
|
" fully qualified domain name**\n");
|
|
free(name);
|
|
name = malloc(i+2);
|
|
strcpy(name, optarg);
|
|
strcat(name, ".");
|
|
}
|
|
break;
|
|
case 'p':
|
|
if (optarg && isdigit(optarg[0]))
|
|
protocol = atoi(optarg);
|
|
else
|
|
usage("-p flag not followed by a number", 0);
|
|
break;
|
|
case 's':
|
|
/* Default: not signatory key */
|
|
if (optarg && isdigit(optarg[0]))
|
|
sign_val = (int) atoi(optarg);
|
|
else
|
|
usage("-s flag requires a value",0);
|
|
break;
|
|
case 'h':
|
|
end_key = NS_KEY_NAME_ENTITY;
|
|
key_type++;
|
|
break;
|
|
case 'u' :
|
|
user_key = NS_KEY_NAME_USER;
|
|
key_type++;
|
|
break ;
|
|
case 'z':
|
|
zone_key = NS_KEY_NAME_ZONE;
|
|
key_type++;
|
|
break;
|
|
case 'H':
|
|
if (optarg && isdigit(optarg[0]))
|
|
size = (int) atoi(optarg);
|
|
else
|
|
usage("-H flag requires a size",0);
|
|
if (alg != 0)
|
|
usage("Only ONE alg can be specified", 1);
|
|
alg = KEY_HMAC_MD5;
|
|
if (!dst_check_algorithm(alg))
|
|
usage("Algorithm HMAC-MD5 not available",
|
|
PRINT_SUPPORTED);
|
|
break;
|
|
case 'R':
|
|
if (optarg && isdigit(optarg[0]))
|
|
size = (int) atoi(optarg);
|
|
else
|
|
usage("-R flag requires a size",0);
|
|
if (alg != 0)
|
|
usage("Only ONE alg can be specified", 1);
|
|
alg = NS_ALG_MD5RSA;
|
|
if (!dst_check_algorithm(alg))
|
|
usage("Algorithm RSA not available",
|
|
PRINT_SUPPORTED);
|
|
break;
|
|
case 'D':
|
|
if (optarg && isdigit(optarg[0]))
|
|
size = (int) atoi(optarg);
|
|
else
|
|
usage("-D flag requires a size", 0);
|
|
if (alg != 0)
|
|
usage("Only ONE alg can be specified", 1);
|
|
alg = NS_ALG_DSS;
|
|
if (dst_check_algorithm(alg) == 0)
|
|
usage("Algorithm DSS not available",
|
|
PRINT_SUPPORTED);
|
|
break;
|
|
default:
|
|
err++;
|
|
} /* switch */
|
|
} /* while (getopt) */
|
|
|
|
/*
|
|
* Command line parsed make sure required parameters are present
|
|
*/
|
|
if (name == NULL)
|
|
usage("No key name specified -n <name>", 1);
|
|
|
|
if (alg == 0)
|
|
usage("No algorithm specififed -{DHR}", 1);
|
|
|
|
if (key_type == 0)
|
|
usage("Key type -{zhu} must be specified", 1);
|
|
else if (key_type > 1)
|
|
usage("Only one key type -{zhu} must be specified", 1);
|
|
|
|
if (alg == NS_ALG_DSS)
|
|
no_conf = NS_KEY_NO_CONF; /* dss keys can not encrypt */
|
|
|
|
if (protocol == -1) {
|
|
if (zone_key || end_key)
|
|
protocol = NS_KEY_PROT_DNSSEC;
|
|
else
|
|
protocol = NS_KEY_PROT_EMAIL;
|
|
}
|
|
if (protocol < 0 || protocol > 255)
|
|
usage("Protocol value out of range [0..255]", 0);
|
|
|
|
if (sign_val < 0 || sign_val > 15) {
|
|
sprintf(str, "%s: Signatory value %d out of range[0..15]\n",
|
|
prog, sign_val);
|
|
usage(str, 0);
|
|
}
|
|
/* if any of bits 321 is set bit 0 can not be set*/
|
|
if (sign_val & 0xe)
|
|
sign_val &= 0xe;
|
|
|
|
/* if a zone key make sure at least one of the signer flags is set */
|
|
if ((protocol == NS_KEY_PROT_DNSSEC) && (sign_val == 0))
|
|
sign_val = 0x01;
|
|
|
|
if (no_auth && no_conf) { /* null key specified */
|
|
if (sign_val > 0)
|
|
sign_val = 0x0; /* null key can not sign */
|
|
if (size > 0)
|
|
size = 0; /* null key must have size 0 */
|
|
}
|
|
|
|
if (size > 0) {
|
|
if (alg == NS_ALG_MD5RSA){
|
|
if (size < 512 || size > 4096)
|
|
usage("Size out of range", 1);
|
|
}
|
|
else if (exp)
|
|
usage("-F can only be specified with -R", 0);
|
|
if (alg == NS_ALG_DSS) {
|
|
for (i = 0; dsa_sizes[i]; i++)
|
|
if (size <= dsa_sizes[i])
|
|
break;
|
|
if (size != dsa_sizes[i])
|
|
usage("Invalid DSS key size", 1);
|
|
}
|
|
}
|
|
else if (size < 0)
|
|
usage("No size specified", 0);
|
|
else /* size == 0 */
|
|
sign_val = 0;
|
|
|
|
if (err)
|
|
usage("errors encountered/unknown flag", 1);
|
|
|
|
flags = no_conf | no_auth | end_key | user_key | zone_key | sign_val;
|
|
|
|
/* process defaults */
|
|
#ifdef WARN_NONZONE_SIGNER
|
|
if (signer && (user_key | end_key))
|
|
printf("Warning: User/End key is allowed to sign\n");
|
|
#endif
|
|
|
|
/* create a public/private key pair */
|
|
if (alg == NS_ALG_MD5RSA)
|
|
printf("Generating %d bit RSA Key for %s\n\n",size, name);
|
|
else if (alg == NS_ALG_DSS)
|
|
printf("Generating %d bit DSS Key for %s\n\n",size, name);
|
|
else if (alg == KEY_HMAC_MD5)
|
|
printf("Generating %d bit HMAC-MD5 Key for %s\n\n",
|
|
size, name);
|
|
|
|
/* Make the key
|
|
* dst_generate_key_pair will place result in files that it
|
|
* knows about K<name><foot>.public and K<name><foot>.private
|
|
*/
|
|
pubkey = dst_generate_key(name, size, exp, flags, protocol, alg);
|
|
|
|
if (pubkey == NULL) {
|
|
printf("Failed generating key for %s\n", name);
|
|
exit(12);
|
|
}
|
|
|
|
if (dst_write_key(pubkey, DST_PRIVATE) < 0) {
|
|
printf ("Failed to write private key for %s %d %d\n",
|
|
name, pubkey->dk_id, pubkey->dk_alg);
|
|
exit(12);
|
|
}
|
|
|
|
if (dst_write_key(pubkey, DST_PUBLIC) <= 0) {
|
|
if (access(name, F_OK))
|
|
printf("Not allowed to overwrite existing file\n");
|
|
else
|
|
printf("Failed to write public key for %s %d %d\n",
|
|
name, pubkey->dk_id, pubkey->dk_alg);
|
|
exit(12);
|
|
}
|
|
|
|
printf("Generated %d bit Key for %s id=%d alg=%d flags=%d\n\n",
|
|
size, name, pubkey->dk_id, pubkey->dk_alg,
|
|
pubkey->dk_flags);
|
|
exit(0);
|
|
}
|
|
|
|
static void
|
|
usage(const char *str, int flag) {
|
|
int i;
|
|
|
|
printf("\nNo key generated\n");
|
|
if (*str != '\0')
|
|
printf("Usage:%s: %s\n",prog, str);
|
|
printf("Usage:%s -{DHR} <size> [-F] -{zhu} [-ac] [-p <no>]"
|
|
" [-s <no>] -n name\n", prog);
|
|
if (flag == 0)
|
|
exit(2);
|
|
printf("\t-D generate DSA/DSS KEY: size must be one of following:\n");
|
|
printf("\t\t");
|
|
for(i = 0; dsa_sizes[i] > 0; i++)
|
|
printf(" %d,", dsa_sizes[i]);
|
|
printf("\n");
|
|
printf("\t-H generate HMAC-MD5 KEY: size in the range [1..512]:\n");
|
|
printf("\t-R generate RSA KEY: size in the range [512..4096]\n");
|
|
printf("\t-F RSA KEYS only: use large exponent\n");
|
|
|
|
printf("\t-z Zone key \n");
|
|
printf("\t-h Host/Entity key \n");
|
|
printf("\t-u User key \n");
|
|
|
|
printf("\t-a Key CANNOT be used for authentication\n");
|
|
printf("\t-c Key CANNOT be used for encryption\n");
|
|
|
|
printf("\t-p Set protocol field to <no>\n");
|
|
printf("\t\t default: 2 (email) for Host keys, 3 (dnssec) for all others\n");
|
|
printf("\t-s Strength value this key signs DNS records with\n");
|
|
printf("\t\t default: 1 for Zone keys, 0 for all others\n");
|
|
printf("\t-n name: the owner of the key\n");
|
|
|
|
if (flag == PRINT_SUPPORTED) {
|
|
printf("Available algorithms are:");
|
|
if (dst_check_algorithm(NS_ALG_MD5RSA) == 1)
|
|
printf(" RSA");
|
|
if (dst_check_algorithm(NS_ALG_DSS) == 1)
|
|
printf(" DSS");
|
|
if (dst_check_algorithm(KEY_HMAC_MD5) == 1)
|
|
printf(" HMAC-MD5");
|
|
printf("\n");
|
|
}
|
|
|
|
exit (3);
|
|
}
|