1 /*
2  * Copyright (c) 2016 NLNet Labs
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include "config.h"
29 #include <getopt.h>
30 
31 #include "cmdhandler.h"
32 #include "daemon/enforcercommands.h"
33 #include "daemon/engine.h"
34 #include "file.h"
35 #include "log.h"
36 #include "str.h"
37 #include "clientpipe.h"
38 #include "duration.h"
39 #include "libhsm.h"
40 #include "libhsmdns.h"
41 #include "db/key_data.h"
42 #include "db/db_error.h"
43 
44 #include "keystate/keystate_import_cmd.h"
45 #include "keystate/keystate_list_cmd.h"
46 
47 static const char *module_str = "keystate_import_cmd";
48 /* 5 states are: generate, publish, ready, active and retire */
49 /* For every state we should specify the values of DS, DNSKEY, RRSIGDNSKEY
50    and RRSIG. These values can be HIDDEN(0),    RUMOURED(1), OMNIPRESENT(2),
51    UNRETENTIVE(3), NA(4)*/
52 const int ksk_mapping[5][4] = {{0,0,0,4},{0,1,1,4},{1,2,2,4},{1,2,2,4},{3,2,2,4}};
53 const int zsk_mapping[5][4] = {{4,0,4,0},{4,1,4,0},{4,2,4,1},{4,2,4,2},{4,2,4,3}};
54 const int ds_at_parent [5] = {0,0,1,3,5};
55 
56 
max(int a,int b)57 static int max(int a, int b) { return a>b?a:b; }
min(int a,int b)58 static int min(int a, int b) { return a<b?a:b; }
59 
60 
61 int
perform_hsmkey_import(int sockfd,db_connection_t * dbconn,const char * ckaid,const char * rep,const char * zonename,int bits,int alg,int keytype,unsigned int time)62 perform_hsmkey_import(int sockfd, db_connection_t *dbconn,
63 	const char *ckaid, const char *rep, const char *zonename,
64 	int bits, int alg, int keytype, unsigned int time)
65 {
66     hsm_ctx_t *hsm_ctx;
67     hsm_key_t *hsm_key = NULL;
68     char *hsm_err;
69     libhsm_key_t *libhsmkey;
70     zone_db_t *zone;
71 
72   /* Create an HSM context and check that the repository exists  */
73     if (!(hsm_ctx = hsm_create_context())) {
74         return -1;
75     }
76     if (!hsm_token_attached(hsm_ctx, rep)) {
77         if ((hsm_err = hsm_get_error(hsm_ctx))) {
78             ods_log_error("[%s] Error: Unable to check for the repository %s, HSM error: %s", module_str, rep, hsm_err);
79             client_printf_err(sockfd, "Unable to check for the repository %s, HSM error: %s\n", rep, hsm_err);
80             free(hsm_err);
81         }
82         else {
83             ods_log_error("[%s] Error: Unable to find repository %s in HSM", module_str, rep);
84             client_printf_err(sockfd, "Unable to find repository %s in HSM\n", rep);
85         }
86         hsm_destroy_context(hsm_ctx);
87         return -1;
88     }
89 
90     if (!(libhsmkey = hsm_find_key_by_id(hsm_ctx, ckaid))) {
91 	ods_log_error("[%s] Error: Unable to find the key with this locator: %s", module_str, ckaid);
92 	client_printf_err(sockfd, "Unable to find the key with this locator: %s\n", ckaid);
93 	hsm_destroy_context(hsm_ctx);
94 	return -1;
95     }
96     libhsm_key_free(libhsmkey);
97     hsm_key = hsm_key_new_get_by_locator(dbconn, ckaid);
98     if (hsm_key) {
99         ods_log_error("[%s] Error: Already used this key with this locator: %s", module_str, ckaid);
100         client_printf_err(sockfd, "Already used this key with this locator: %s\n", ckaid);
101         hsm_key_free(hsm_key);
102         hsm_destroy_context(hsm_ctx);
103         return -1;
104     }
105 
106     zone = zone_db_new_get_by_name(dbconn, zonename);
107     if (!(hsm_key = hsm_key_new(dbconn))
108                 || hsm_key_set_algorithm(hsm_key, alg)
109                 || hsm_key_set_bits(hsm_key, bits)
110                 || hsm_key_set_inception(hsm_key, time)
111                 || hsm_key_set_key_type(hsm_key, HSM_KEY_KEY_TYPE_RSA)
112                 || hsm_key_set_locator(hsm_key, ckaid)
113                 || hsm_key_set_policy_id(hsm_key, zone_db_policy_id(zone))
114                 || hsm_key_set_repository(hsm_key, rep)
115                 || hsm_key_set_role(hsm_key, keytype)
116                 || hsm_key_set_state(hsm_key, (hsm_key_state_t)HSM_KEY_STATE_PRIVATE)
117                 || hsm_key_create(hsm_key))
118     {
119         ods_log_error("[%s] hsm key creation failed, database or memory error", module_str);
120         hsm_key_free(hsm_key);
121         hsm_destroy_context(hsm_ctx);
122         zone_db_free(zone);
123         return -1;
124     }
125     ods_log_debug("[%s] hsm key with this locator %s is created successfully", module_str, ckaid);
126     hsm_key_free(hsm_key);
127     hsm_destroy_context(hsm_ctx);
128     zone_db_free(zone);
129     return 0;
130 }
131 
132 int
perform_keydata_import(int sockfd,db_connection_t * dbconn,const char * ckaid,const char * rep,const char * zonename,int alg,int keystate,int keytype,unsigned int time,int setmin,db_value_t * hsmkey_id)133 perform_keydata_import(int sockfd, db_connection_t *dbconn,
134         const char *ckaid, const char *rep, const char *zonename,
135         int alg, int keystate, int keytype, unsigned int time, int setmin, db_value_t *hsmkey_id)
136 {
137     key_data_t *key_data = NULL;
138     hsm_ctx_t *hsm_ctx;
139     char *hsm_err;
140     uint16_t tag;
141     hsm_key_t * hsmkey;
142     libhsm_key_t *libhsmkey;
143     zone_db_t *zone;
144 
145     /* Create a HSM context and check that the repository exists  */
146     if (!(hsm_ctx = hsm_create_context())) {
147         return -1;
148     }
149     if (!hsm_token_attached(hsm_ctx, rep)) {
150         if ((hsm_err = hsm_get_error(hsm_ctx))) {
151             ods_log_error("[%s] Error: Unable to check for the repository %s, HSM error: %s", module_str, rep, hsm_err);
152             client_printf_err(sockfd, "Unable to check for the repository %s, HSM error: %s\n", rep, hsm_err);
153             free(hsm_err);
154         }
155         else {
156             ods_log_error("[%s] Error: Unable to find repository %s in HSM", module_str, rep);
157             client_printf_err(sockfd, "Unable to find repository %s in HSM\n", rep);
158         }
159         hsm_destroy_context(hsm_ctx);
160         return -1;
161     }
162 
163     if (!(libhsmkey = hsm_find_key_by_id(hsm_ctx, ckaid))) {
164         ods_log_error("[%s] Error: Unable to find the key with this locator: %s", module_str, ckaid);
165         client_printf_err(sockfd, "Unable to find the key with this locator: %s\n", ckaid);
166         hsm_destroy_context(hsm_ctx);
167         return -1;
168     }
169     libhsm_key_free(libhsmkey);
170     if (!(hsmkey = hsm_key_new_get_by_locator(dbconn, ckaid))) {
171         ods_log_error("[%s] Error: Cannot get hsmkey %s from database, database error", module_str, ckaid);
172         hsm_destroy_context(hsm_ctx);
173         return -1;
174     }
175     if (hsm_keytag(ckaid, alg, KEY_DATA_ROLE_SEP(keytype), &tag)) {
176         ods_log_error("[%s] Error: Keytag for this key %s is not correct", module_str, ckaid);
177     }
178 
179     zone = zone_db_new_get_by_name(dbconn, zonename);
180     if (!(key_data = key_data_new(dbconn))
181                 || key_data_set_zone_id(key_data, zone_db_id(zone))
182                 || key_data_set_hsm_key_id(key_data, hsm_key_id(hsmkey))
183 		|| key_data_set_algorithm (key_data, alg)
184                 || key_data_set_inception(key_data, time)
185 		|| key_data_set_introducing (key_data, keystate < 4 ? 1 : 0)
186 		|| key_data_set_active_zsk(key_data, keytype == 1 || keystate < 2 || keystate > 3 ? 0 : 1)
187 		|| key_data_set_publish(key_data,0 < keystate ? 1 : 0)
188 		|| key_data_set_active_ksk(key_data, keytype == 2 || keystate == 0 ? 0 : 1)
189 		|| key_data_set_role(key_data, keytype)
190 		|| key_data_set_ds_at_parent(key_data, keytype == 1 ? ds_at_parent[keystate] : 0)
191 		|| key_data_set_keytag(key_data, tag)
192 		|| key_data_set_minimize(key_data,setmin)
193                 || key_data_create(key_data))
194     {
195         ods_log_error("[%s] key data creation failed, database or memory error", module_str);
196         hsm_key_free(hsmkey);
197         key_data_free(key_data);
198         hsm_destroy_context(hsm_ctx);
199         zone_db_free(zone);
200         return -1;
201     }
202     zone_db_free(zone);
203     ods_log_debug("[%s] key data with this locator %s is created successfully", module_str, ckaid);
204     key_data_free(key_data);
205     hsm_destroy_context(hsm_ctx);
206     db_value_copy (hsmkey_id, hsm_key_id(hsmkey));
207     hsm_key_free(hsmkey);
208     return 0;
209 }
210 
211 int
perform_keystate_import(int sockfd,db_connection_t * dbconn,const char * ckaid,const char * rep,const char * zonename,int keystate,int keytype,unsigned int time,db_value_t * hsmkeyid)212 perform_keystate_import(int sockfd, db_connection_t *dbconn,
213         const char *ckaid, const char *rep, const char *zonename,
214         int keystate, int keytype, unsigned int time, db_value_t *hsmkeyid)
215 {
216     key_state_t *key_state = NULL;
217     hsm_ctx_t *hsm_ctx;
218     char *hsm_err;
219     int ttl;
220     key_data_t* key;
221     const db_value_t* keydataid;
222     policy_t* policy;
223     libhsm_key_t *libhsmkey;
224     zone_db_t *zone;
225 
226     /* Create a HSM context and check that the repository exists  */
227     if (!(hsm_ctx = hsm_create_context())) {
228         return -1;
229     }
230     if (!hsm_token_attached(hsm_ctx, rep)) {
231         if ((hsm_err = hsm_get_error(hsm_ctx))) {
232             ods_log_error("[%s] Error: Unable to check for the repository %s, HSM error: %s", module_str, rep, hsm_err);
233             client_printf_err(sockfd, "Unable to check for the repository %s, HSM error: %s\n", rep, hsm_err);
234             free(hsm_err);
235         }
236         else {
237             ods_log_error("[%s] Error: Unable to find repository %s in HSM", module_str, rep);
238             client_printf_err(sockfd, "Unable to find repository %s in HSM\n", rep);
239         }
240         hsm_destroy_context(hsm_ctx);
241         return -1;
242     }
243 
244     if (!(libhsmkey = hsm_find_key_by_id(hsm_ctx, ckaid))) {
245         ods_log_error("[%s] Error: Unable to find the key with this locator: %s", module_str, ckaid);
246         client_printf(sockfd, "Unable to find the key with this locator: %s\n", ckaid);
247         hsm_destroy_context(hsm_ctx);
248         return -1;
249     }
250     libhsm_key_free(libhsmkey);
251     key = key_data_new_get_by_hsm_key_id(dbconn, hsmkeyid);
252     keydataid = key_data_id(key);
253 
254     policy = policy_new(dbconn);
255     zone = zone_db_new_get_by_name(dbconn, zonename);
256     policy_get_by_id(policy, zone_db_policy_id(zone));
257     zone_db_free(zone);
258 
259     if (!(key_state = key_state_new(dbconn))
260                 || key_state_set_key_data_id(key_state, keydataid)
261                 || key_state_set_type(key_state, KEY_STATE_TYPE_DS)
262                 || key_state_set_last_change (key_state, time)
263                 || key_state_set_minimize(key_state, (key_data_minimize(key) >> 2) & 1)
264                 || key_state_set_ttl (key_state, policy_parent_ds_ttl(policy))
265 		|| key_state_set_state(key_state, keytype == 1 ? ksk_mapping[keystate][0] : zsk_mapping[keystate][0])
266                 || key_state_create(key_state))
267     {
268         ods_log_error("[%s] key state creation for DS failed, database or memory error", module_str);
269         key_data_free(key);
270         policy_free(policy);
271         key_state_free(key_state);
272         hsm_destroy_context(hsm_ctx);
273         return -1;
274     }
275     key_state_free(key_state);
276 
277     if (!(key_state = key_state_new(dbconn))
278                 || key_state_set_key_data_id(key_state, keydataid)
279                 || key_state_set_type(key_state, KEY_STATE_TYPE_DNSKEY)
280                 || key_state_set_last_change (key_state, time)
281                 || key_state_set_minimize(key_state, (key_data_minimize(key) >> 1) & 1)
282                 || key_state_set_ttl (key_state, policy_keys_ttl(policy))
283 		|| key_state_set_state(key_state, keytype == 1 ? ksk_mapping[keystate][1] : zsk_mapping[keystate][1])
284                 || key_state_create(key_state))
285     {
286         ods_log_error("[%s] key state creation for DNSKEY failed, database or memory error", module_str);
287         key_data_free(key);
288         policy_free(policy);
289         key_state_free(key_state);
290         hsm_destroy_context(hsm_ctx);
291         return -1;
292     }
293     key_state_free(key_state);
294 
295     if (!(key_state = key_state_new(dbconn))
296                 || key_state_set_key_data_id(key_state, keydataid)
297                 || key_state_set_type(key_state, KEY_STATE_TYPE_RRSIGDNSKEY)
298                 || key_state_set_last_change (key_state, time)
299                 || key_state_set_ttl (key_state, policy_keys_ttl(policy))
300                 || key_state_set_state(key_state, keytype == 1 ? ksk_mapping[keystate][2] : zsk_mapping[keystate][2])
301                 || key_state_create(key_state))
302     {
303         ods_log_error("[%s] key state creation for RRSIGDNSKEY failed, database or memory error", module_str);
304         key_data_free(key);
305         policy_free(policy);
306         key_state_free(key_state);
307         hsm_destroy_context(hsm_ctx);
308         return -1;
309     }
310     key_state_free(key_state);
311 
312     ttl = max(min(policy_zone_soa_ttl(policy), policy_zone_soa_minimum(policy)),
313             (policy_denial_type(policy) == POLICY_DENIAL_TYPE_NSEC3
314                 ? ( policy_denial_ttl(policy) > policy_signatures_max_zone_ttl(policy)
315                     ? policy_denial_ttl(policy)
316                     : policy_signatures_max_zone_ttl(policy))
317                 : policy_signatures_max_zone_ttl(policy)));
318 
319     if (!(key_state = key_state_new(dbconn))
320                 || key_state_set_key_data_id(key_state, keydataid)
321        /*         || hsm_key_set_backup(hsm_key, (hsm->require_backup ? HSM_KEY_BACKUP_BACKUP_REQUIRED : HSM_KEY_BACKUP_NO_BACKUP))*/
322                 || key_state_set_type(key_state, KEY_STATE_TYPE_RRSIG)
323                 || key_state_set_last_change (key_state, time)
324                 || key_state_set_minimize(key_state, key_data_minimize(key) & 1)
325                 || key_state_set_ttl (key_state, ttl)
326                 || key_state_set_state(key_state, keytype == 1 ? ksk_mapping[keystate][3] : zsk_mapping[keystate][3])
327                 || key_state_create(key_state))
328     {
329         ods_log_error("[%s] key state creation for RRSIG failed, database or memory error", module_str);
330         key_data_free(key);
331         policy_free(policy);
332         key_state_free(key_state);
333         hsm_destroy_context(hsm_ctx);
334         return -1;
335     }
336     ods_log_debug("[%s] key state with this locator %s is created successfully", module_str, ckaid);
337 
338     key_data_free(key);
339     policy_free(policy);
340     key_state_free(key_state);
341     hsm_destroy_context(hsm_ctx);
342 
343     return 0;
344 }
345 
346 
347 
348 static void
usage(int sockfd)349 usage(int sockfd)
350 {
351     client_printf(sockfd,
352 		"key import\n"
353 		"	--cka_id <CKA_ID>			aka -k\n"
354 		"	--repository <repository>		aka -r\n"
355 		"	--zone <zone>				aka -z\n"
356 		"	--bits <size>				aka -b\n"
357 		"	--algorithm <algorithm>			aka -g\n"
358 		"	--keystate <state>			aka -e\n"
359 		"	--keytype <type>			aka -t\n"
360 		"	--inception_time <time>			aka -w\n"
361 	);
362 }
363 
364 static void
help(int sockfd)365 help(int sockfd)
366 {
367 	client_printf(sockfd,
368 		"Add a key which was created outside of the OpenDNSSEC into the enforcer database.\n"
369 		"\nOptions:\n"
370 		"cka_id		specify the locator of the key\n"
371 		"repository	name of the repository which the key must be stored\n"
372 		"zone		name of the zone for which this key is to be used\n"
373 		"bits		key size in bits\n"
374 		"algorithm	algorithm number \n"
375 		"keystate	state of the key in which the key will be after import\n"
376 		"keytype		type of the key, KSK, ZSK or CSK\n"
377 		"inception_time	time of inception\n\n");
378 }
379 
380 static int
run(int sockfd,cmdhandler_ctx_type * context,const char * cmd)381 run(int sockfd, cmdhandler_ctx_type* context, const char *cmd)
382 {
383     #define NARGV 18
384     char buf[ODS_SE_MAXLINE];
385     const char *argv[NARGV];
386     int argc = 0, long_index = 0, opt = 0;
387     const char *ckaid = NULL;
388     const char *repository = NULL;
389     const char *zonename = NULL;
390     const char *bits = NULL;
391     const char *algorithm = NULL;
392     const char* keytype = NULL;
393     const char* keystate = NULL;
394     const char *time = NULL;
395     zone_db_t *zone = NULL;
396     time_t inception = 0;
397     struct tm tm;
398     int setmin;
399     db_value_t *hsmkey_id;
400     policy_key_t *policy_key;
401     db_connection_t* dbconn = getconnectioncontext(context);
402 
403     static struct option long_options[] = {
404         {"zone", required_argument, 0, 'z'},
405         {"cka_id", required_argument, 0, 'k'},
406         {"repository", required_argument, 0, 'r'},
407         {"bits", required_argument, 0, 'b'},
408         {"algorithm", required_argument, 0, 'g'},
409         {"keytype", required_argument, 0, 't'},
410         {"keystate", required_argument, 0, 'e'},
411         {"inception_time", required_argument, 0, 'w'},
412         {0, 0, 0, 0}
413     };
414 
415     ods_log_debug("[%s] %s command", module_str, key_import_funcblock.cmdname);
416 
417     /* Use buf as an intermediate buffer for the command.*/
418     strncpy(buf, cmd, sizeof(buf));
419     buf[sizeof(buf)-1] = '\0';
420 
421     /* separate the arguments*/
422     argc = ods_str_explode(buf, NARGV, argv);
423     if (argc == -1) {
424         client_printf_err(sockfd, "too many arguments\n");
425         ods_log_error("[%s] too many arguments for %s command",
426                       module_str, key_import_funcblock.cmdname);
427         return -1;
428     }
429 
430     optind = 0;
431     while ((opt = getopt_long(argc, (char* const*)argv, "z:k:r:b:g:t:e:w:", long_options, &long_index)) != -1) {
432         switch (opt) {
433             case 'z':
434                 zonename = optarg;
435                 break;
436             case 'k':
437                 ckaid = optarg;
438                 break;
439             case 'r':
440                 repository = optarg;
441                 break;
442             case 'b':
443                 bits = optarg;
444                 break;
445             case 'g':
446                 algorithm = optarg;
447                 break;
448             case 't':
449                 keytype = optarg;
450                 break;
451             case 'e':
452                 keystate = optarg;
453                 break;
454             case 'w':
455                 time = optarg;
456                 break;
457             default:
458                 client_printf_err(sockfd, "unknown arguments\n");
459                 ods_log_error("[%s] unknown arguments for %s command",
460                                 module_str, key_import_funcblock.cmdname);
461                 return -1;
462         }
463     }
464 
465     if (keytype) {
466         if (strcasecmp(keytype, "KSK") && strcasecmp(keytype, "ZSK") && strcasecmp(keytype, "CSK")) {
467             ods_log_error("[%s] unknown keytype, should be one of KSK, ZSK, or CSK", module_str);
468             client_printf_err(sockfd, "unknown keytype, should be one of KSK, ZSK, or CSK\n");
469             return -1;
470         }
471     }
472     else {
473         ods_log_error("[%s] specify keytype for command %s", module_str, cmd);
474         client_printf_err(sockfd, "specify keytype: ZSK, KSK or CSK\n");
475         return -1;
476     }
477 
478     if (keystate) {
479         if (strcasecmp(keystate, "generate") && strcasecmp(keystate, "publish") && strcasecmp(keystate, "ready") && strcasecmp(keystate, "active") && strcasecmp(keystate, "retire") && strcasecmp(keystate, "revoke")) {
480             ods_log_error("[%s] unknown keystate", module_str);
481             client_printf_err(sockfd, "unknown keystate: states are generate, publish, ready, active or retire\n");
482             return -1;
483         }
484     }
485     else {
486         ods_log_error("[%s] specify keystate for command %s", module_str, cmd);
487         client_printf_err(sockfd, "specify keystate: generate, publish, ready, active or retire\n");
488         return -1;
489     }
490 
491     if (!zonename) {
492         ods_log_error("[%s] expected --zone for %s command", module_str, key_import_funcblock.cmdname);
493         client_printf_err(sockfd, "expected --zone \n");
494         return -1;
495     }
496     if (zonename && !(zone = zone_db_new_get_by_name(dbconn, zonename))) {
497         ods_log_error("[%s] Unknown zone: %s", module_str, zonename);
498         client_printf_err(sockfd, "Unknown zone: %s\n", zonename);
499         return -1;
500     }
501     free(zone);
502     zone = NULL;
503 
504     if (!algorithm) {
505         ods_log_error("[%s] specify an algorithm for command %s", module_str, cmd);
506         client_printf_err(sockfd, "specify an algorithm\n");
507         return -1;
508     }
509     if (!bits) {
510         ods_log_error("[%s] specify bits for command %s", module_str, cmd);
511         client_printf_err(sockfd, "specify bits\n");
512         return -1;
513     }
514     if (!repository) {
515         ods_log_error("[%s] specify repository for command %s", module_str, cmd);
516         client_printf_err(sockfd, "specify repository \n");
517         return -1;
518     }
519 
520     if (time && strptime(time, "%Y-%m-%d-%H:%M:%S", &tm)) {
521         tm.tm_isdst = -1;
522         inception = mktime(&tm);
523     }
524     else {
525         ods_log_error("[%s] specify inception time for command %s", module_str, cmd);
526         client_printf_err(sockfd, "specify inception time YYYY-MM-DD-HH:MM:SS\n");
527         return -1;
528     }
529 
530     /* gen = 0, pub = 1, ready = 2, act = 3, ... */
531     int state = -1;
532     if (!strcasecmp(keystate, "generate"))
533         state = 0;
534     else if (!strcasecmp(keystate,"publish"))
535         state = 1;
536     else if (!strcasecmp(keystate, "ready"))
537         state = 2;
538     else if (!strcasecmp(keystate, "active"))
539         state = 3;
540     else if (!strcasecmp(keystate, "retire"))
541         state = 4;
542     else if (!strcasecmp(keystate, "revoke"))
543         state = 5;
544 
545     int type = -1;
546     if (!strcasecmp(keytype, "KSK"))
547         type = 1;
548     else if (!strcasecmp(keytype, "ZSK"))
549         type = 2;
550     else if (!strcasecmp(keytype, "CSK"))
551         type = 3;
552 
553     hsmkey_id = db_value_new();
554     zone = zone_db_new_get_by_name(dbconn, zonename);
555     policy_key = policy_key_new_get_by_policyid_and_role(dbconn, zone_db_policy_id(zone), type);
556     zone_db_free(zone);
557     if (!policy_key) {
558         ods_log_error("Unable to get policyKey, database error!");
559         client_printf_err(sockfd, "Unable to get policyKey, database error!\n");
560         db_value_free((void*)hsmkey_id);
561         return -1;
562     }
563 
564     if (atoi(algorithm) != policy_key_algorithm(policy_key)) {
565         ods_log_error("Error: the given algorithm in import command doesn't match the algorithm in kasp");
566         client_printf_err(sockfd, "The given algorithm doesn't match the algorithm in kasp\n");
567         db_value_free((void*)hsmkey_id);
568         policy_key_free(policy_key);
569         return -1;
570     }
571 
572     setmin = policy_key_minimize(policy_key);
573     policy_key_free(policy_key);
574 
575     /* perform task immediately */
576     if (perform_hsmkey_import(sockfd, dbconn, ckaid, repository, zonename, atoi(bits), atoi(algorithm), type, (unsigned int)inception)
577         || perform_keydata_import(sockfd, dbconn, ckaid, repository, zonename, atoi(algorithm), state, type, (unsigned int)inception, setmin, hsmkey_id)
578         || perform_keystate_import(sockfd, dbconn, ckaid, repository, zonename, state, type, (unsigned int)inception, hsmkey_id)) {
579         ods_log_error("[%s] Error: Unable to add key to the database", module_str);
580         db_value_free((void*)hsmkey_id);
581         return -1;
582     }
583     db_value_free((void*)hsmkey_id);
584     client_printf(sockfd, "Key imported into zone %s\n", zonename);
585     return 0;
586 }
587 
588 struct cmd_func_block key_import_funcblock = {
589     "key import", &usage, &help, NULL, &run
590 };
591