• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/srv/bpo/opendnssec/opendnssec-1.3.2/enforcer/ksm/ksm_key.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ksm_key.c 4656 2011-03-25 08:51:54Z rb $
00003  *
00004  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00029 /*+
00030  * KsmKey - Manipulation of Key Information
00031  *
00032  * Description:
00033  *      Holds the functions needed to manipulate the KEYDATA table.
00034  *
00035  *      N.B.  The table is the KEYDATA table - rather than the KEY table - as
00036  *      KEY is a reserved word in SQL.
00037 -*/
00038 
00039 #include <assert.h>
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <time.h>
00044 
00045 #include "ksm/database.h"
00046 #include "ksm/database_statement.h"
00047 #include "ksm/datetime.h"
00048 #include "ksm/db_fields.h"
00049 #include "ksm/debug.h"
00050 #include "ksm/kmedef.h"
00051 #include "ksm/ksm.h"
00052 #include "ksm/ksmdef.h"
00053 #include "ksm/ksm_internal.h"
00054 #include "ksm/message.h"
00055 #include "ksm/string_util.h"
00056 #include "ksm/string_util2.h"
00057 
00058 /*+
00059  * KsmKeyPairCreate - Create Entry in the KeyPairs table 
00060  *                    (i.e. key creation in the HSM)
00061  *
00062  * Description:
00063  *      Creates a key in the database.
00064  *
00065  * Arguments:
00066  *      policy_id
00067  *          policy that the key is created for
00068  *      HSMKeyID
00069  *          ID the key is refered to in the HSM
00070  *      smID
00071  *          security module ID
00072  *      size
00073  *          size of key
00074  *      alg
00075  *          algorithm used
00076  *      generate
00077  *          timestamp of generation
00078  *
00079  *      DB_ID* id (returned)
00080  *          ID of the created entry.  This will be undefined on error.
00081  *
00082  * Returns:
00083  *      int
00084  *          Status return.  0=> Success, non-zero => error.
00085 -*/
00086 int KsmKeyPairCreate(int policy_id, const char* HSMKeyID, int smID, int size, int alg, const char* generate, DB_ID* id)
00087 {
00088     unsigned long rowid;                        /* ID of last inserted row */
00089     int         status = 0;         /* Status return */
00090     char*       sql = NULL;         /* SQL Statement */
00091 
00092     /* Check arguments */
00093     if (id == NULL) {
00094         return MsgLog(KSM_INVARG, "NULL id");
00095     }
00096 
00097     sql = DisSpecifyInit("keypairs", "policy_id, HSMkey_id, securitymodule_id, size, algorithm, generate");
00098     DisAppendInt(&sql, policy_id);
00099     DisAppendString(&sql, HSMKeyID);
00100     DisAppendInt(&sql, smID);
00101     DisAppendInt(&sql, size);
00102     DisAppendInt(&sql, alg);
00103     DisAppendString(&sql, generate);
00104     DisEnd(&sql);
00105 
00106     /* Execute the statement */
00107 
00108     status = DbExecuteSqlNoResult(DbHandle(), sql);
00109     DisFree(sql);
00110 
00111     if (status == 0) {
00112 
00113         /* Succcess, get the ID of the inserted record */
00114 
00115                 status = DbLastRowId(DbHandle(), &rowid);
00116                 if (status == 0) {
00117                         *id = (DB_ID) rowid;
00118                 }
00119     }
00120 
00121     return status;
00122 }
00123 
00124 /*+
00125  * KsmDnssecKeyCreate - Create Entry in Dnsseckeys table 
00126  *                      (i.e. when a key is assigned to a policy/zone)
00127  *
00128  * Description:
00129  *      Allocates a key in the database.
00130  *
00131  * Arguments:
00132  *      KSM_KEY* data
00133  *          Data to insert into the database.  The ID argument is ignored.
00134  *
00135  *      DB_ID* id (returned)
00136  *          ID of the created entry.  This will be undefined on error.
00137  *
00138  * Returns:
00139  *      int
00140  *          Status return.  0=> Success, non-zero => error.
00141 -*/
00142 
00143 int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char* time, DB_ID* id)
00144 {
00145         unsigned long rowid;                    /* ID of last inserted row */
00146     int         status = 0;         /* Status return */
00147     char*       sql = NULL;         /* SQL Statement */
00148     char*       columns = NULL;     /* what columns are we setting */
00149 
00150     /* Check arguments */
00151     if (id == NULL) {
00152         return MsgLog(KSM_INVARG, "NULL id");
00153     }
00154 
00155     StrAppend(&columns, "zone_id, keypair_id, keytype, state");
00156     if (state != KSM_STATE_GENERATE) {
00157         StrAppend(&columns, ", ");
00158         StrAppend(&columns, KsmKeywordStateValueToName(state));
00159     }
00160 
00161     sql = DisSpecifyInit("dnsseckeys", columns);
00162     DisAppendInt(&sql, zone_id);
00163     DisAppendInt(&sql, keypair_id);
00164     DisAppendInt(&sql, keytype);
00165     DisAppendInt(&sql, state);
00166     if (state != KSM_STATE_GENERATE) {
00167         DisAppendString(&sql, time);
00168     }
00169     DisEnd(&sql);
00170 
00171     /* Execute the statement */
00172 
00173     status = DbExecuteSqlNoResult(DbHandle(), sql);
00174     DisFree(sql);
00175     StrFree(columns);
00176 
00177     if (status == 0) {
00178 
00179         /* Succcess, get the ID of the inserted record */
00180 
00181                 status = DbLastRowId(DbHandle(), &rowid);
00182                 if (status == 0) {
00183                         *id = (DB_ID) rowid;
00184                 }
00185     }
00186 
00187     return status;
00188 }
00189 
00190 /*+
00191  * KsmKeyInitSql - Query for Key Information With Sql Query
00192  *
00193  * Description:
00194  *      Performs a query for keys in the keydata table that match the given
00195  *      conditions.
00196  *
00197  * Arguments:
00198  *      DB_RESULT* result
00199  *          Pointer to a result to be used for information retrieval.  Will
00200  *          be NULL on error.
00201  *
00202  *      const char* sql
00203  *          SQL statement to select keys.
00204  *
00205  *          (Actually, the statement could be anything, but it is assumed
00206  *          that it is an SQL statement starting "SELECT xxx FROM KEYDATA".)
00207  *
00208  * Returns:
00209  *      int
00210  *          Status return.  0 on success.
00211 -*/
00212 
00213 int KsmKeyInitSql(DB_RESULT* result, const char* sql)
00214 {
00215     return DbExecuteSql(DbHandle(), sql, result);
00216 }
00217 
00218 
00219 
00220 
00221 /*+
00222  * KsmKeyInit - Query for Key Information
00223  *
00224  * Description:
00225  *      Performs a query for keys in the keydata table that match the given
00226  *      conditions.
00227  *
00228  * Arguments:
00229  *      DB_RESULT* result
00230  *          Pointer to a result to be used for information retrieval.  Will
00231  *          be NULL on error.
00232  *
00233  *      DQS_QUERY_CONDITION* condition
00234  *          Array of condition objects, each defining a condition.  The
00235  *          conditions are ANDed together.  The array should end with an object
00236  *          with a condition code of 0.
00237  *
00238  *          If NULL, all objects are selected.
00239  *
00240  * Returns:
00241  *      int
00242  *          Status return.  0 on success.
00243 -*/
00244 
00245 int KsmKeyInit(DB_RESULT* result, DQS_QUERY_CONDITION* condition)
00246 {
00247     int     i;                  /* Condition index */
00248     char*   sql = NULL;         /* SQL query */
00249     int     status = 0;         /* Status return */
00250 
00251     /* Construct the query */
00252 
00253     sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
00254     if (condition) {
00255         for (i = 0; condition[i].compare != DQS_END_OF_LIST; ++i) {
00256             switch (condition[i].code) {
00257             case DB_KEYDATA_ALGORITHM:
00258                 DqsConditionInt(&sql, "ALGORITHM", condition[i].compare,
00259                     condition[i].data.number, i);
00260                 break;
00261 
00262             case DB_KEYDATA_ID:
00263                 DqsConditionInt(&sql, "ID", condition[i].compare,
00264                     condition[i].data.number, i);
00265                 break;
00266 
00267             case DB_KEYDATA_KEYTYPE:
00268                 DqsConditionInt(&sql, "KEYTYPE", condition[i].compare,
00269                     condition[i].data.number, i);
00270                 break;
00271 
00272             case DB_KEYDATA_STATE:
00273                 DqsConditionInt(&sql, "STATE", condition[i].compare,
00274                         condition[i].data.number, i);
00275                 break;
00276 
00277             case DB_KEYDATA_ZONE_ID:
00278                 DqsConditionInt(&sql, "ZONE_ID", condition[i].compare,
00279                     condition[i].data.number, i);
00280                 break;
00281 
00282             default:
00283 
00284                 /* Warn about unrecognised condition code */
00285 
00286                 MsgLog(KME_UNRCONCOD, condition[i].code);
00287             }
00288         }
00289     }
00290     DqsEnd(&sql);
00291 
00292     /* Execute query and free up the query string */
00293 
00294     status = KsmKeyInitSql(result, sql);
00295     DqsFree(sql);
00296 
00297     return status;
00298 }
00299 
00300 
00301 
00302 /*+
00303  * KsmKeyInitId - Query for Key Information by ID
00304  *
00305  * Description:
00306  *      Performs a query for a key in the zone table that matches the
00307  *      given ID.
00308  *
00309  * Arguments:
00310  *      DB_RESULT* result
00311  *          Pointer to a result to be used for information retrieval.  Will
00312  *          be NULL on error.
00313  *
00314  *      DB_ID id
00315  *          ID of the object.
00316  *
00317  * Returns:
00318  *      int
00319  *          Status return.  0 on success.
00320 -*/
00321 
00322 int KsmKeyInitId(DB_RESULT* result, DB_ID id)
00323 {
00324     DQS_QUERY_CONDITION condition[2];   /* Condition for query */
00325 
00326     /* Initialize */
00327 
00328     condition[0].code = DB_KEYDATA_ID;
00329     condition[0].compare = DQS_COMPARE_EQ;
00330     condition[0].data.number = (int) id;
00331 
00332     condition[1].compare = DQS_END_OF_LIST;
00333 
00334     return KsmKeyInit(result, condition);
00335 }
00336 
00337 
00338 
00339 /*+
00340  * KsmKey - Return Key Information
00341  *
00342  * Description:
00343  *      Returns information about the next key in the result set.
00344  *
00345  * Arguments:
00346  *      DB_RESULT result
00347  *          Handle from KsmKeyInit
00348  *
00349  *      KSM_KEYDATA* data
00350  *          Data is returned in here.
00351  *
00352  * Returns:
00353  *      int
00354  *          Status return:
00355  *              0           success
00356  *              -1          end of record set reached
00357  *              non-zero    some error occurred and a message has been output.
00358  *
00359  *          If the status is non-zero, the returned data is meaningless.
00360 -*/
00361 
00362 int KsmKey(DB_RESULT result, KSM_KEYDATA* data)
00363 {
00364     DB_ROW      row = NULL;     /* Row data */
00365     int         status = 0;     /* Return status */
00366 
00367     /* Check arguments */
00368     if (data == NULL) {
00369         return MsgLog(KSM_INVARG, "NULL data");
00370     }
00371 
00372         /* Initialize */
00373 
00374         memset(data, 0, sizeof(KSM_KEYDATA));
00375 
00376     /* Get the next row from the data and copy data across */
00377 
00378         status = DbFetchRow(result, &row);
00379 
00380         if (status == 0) {
00381         status = DbUnsignedLong(row, DB_KEYDATA_ID, &(data->keypair_id));
00382         }
00383 
00384         if (status == 0) {
00385         status = DbInt(row, DB_KEYDATA_STATE, &(data->state));
00386         }
00387 
00388         if (status == 0) {
00389         status = DbStringBuffer(row, DB_KEYDATA_GENERATE,
00390             data->generate, sizeof(data->generate));
00391         }
00392 
00393         if (status == 0) {
00394         status = DbStringBuffer(row, DB_KEYDATA_PUBLISH,
00395             data->publish, sizeof(data->publish));
00396         }
00397 
00398         if (status == 0) {
00399         status = DbStringBuffer(row, DB_KEYDATA_READY,
00400             data->ready, sizeof(data->ready));
00401         }
00402 
00403         if (status == 0) {
00404         status = DbStringBuffer(row, DB_KEYDATA_ACTIVE,
00405             data->active, sizeof(data->active));
00406         }
00407 
00408         if (status == 0) {
00409         status = DbStringBuffer(row, DB_KEYDATA_RETIRE,
00410             data->retire, sizeof(data->retire));
00411         }
00412 
00413         if (status == 0) {
00414         status = DbStringBuffer(row, DB_KEYDATA_DEAD,
00415             data->dead, sizeof(data->dead));
00416         }
00417 
00418         if (status == 0) {
00419         status = DbInt(row, DB_KEYDATA_KEYTYPE, &(data->keytype));
00420         }
00421 
00422         if (status == 0) {
00423         status = DbInt(row, DB_KEYDATA_ALGORITHM, &(data->algorithm));
00424         }
00425 
00426 /*      if (status == 0) {
00427         status = DbInt(row, DB_KEYDATA_SIGLIFETIME, &(data->siglifetime));
00428         }
00429 */
00430         if (status == 0) {
00431         status = DbStringBuffer(row, DB_KEYDATA_LOCATION,
00432             data->location, sizeof(data->location));
00433     }
00434 
00435         if (status == 0) {
00436         status = DbInt(row, DB_KEYDATA_ZONE_ID, &(data->zone_id));
00437         }
00438 
00439         if (status == 0) {
00440         status = DbInt(row, DB_KEYDATA_FIXED_DATE, &(data->fixedDate));
00441         }
00442 
00443         DbFreeRow(row);
00444 
00445     return status;
00446 }
00447 
00448 
00449 /*+
00450  * KsmKeyEnd - End Key Information
00451  *
00452  * Description:
00453  *      Called at the end of a ksm_key cycle, frees up the stored
00454  *      result set.
00455  *
00456  *      N.B. This does not clear stored error information, so allowing it
00457  *      to be called after a failure return from KsmKey to free up database
00458  *      context whilst preserving the reason for the error.
00459  *
00460  * Arguments:
00461  *      DB_RESULT result
00462  *          Handle from KsmKeyInit
00463 -*/
00464 
00465 void KsmKeyEnd(DB_RESULT result)
00466 {
00467     DbFreeResult(result);
00468 }
00469 
00470 
00471 
00472 /*+
00473  * KsmKeyData - Return Data for Key
00474  *
00475  * Description:
00476  *      Returns data for the named Key.
00477  *
00478  * Arguments:
00479  *      DB_ID id
00480  *          Name/ID of the Key.
00481  *
00482  *      KSM_GROUP* data
00483  *          Data for the Key.
00484  *
00485  * Returns:
00486  *      int
00487  *          Status return.  One of:
00488  *
00489  *              0       Success
00490  *              -1      Key not found
00491  *              Other   Error
00492 -*/
00493 
00494 int KsmKeyData(DB_ID id, KSM_KEYDATA* data)
00495 {
00496     DB_RESULT   result;     /* Handle to the data */
00497     int         status;     /* Status return code */
00498 
00499     status = KsmKeyInitId(&result, id);
00500     if (status == 0) {
00501 
00502         /* Retrieve the key data */
00503 
00504         status = KsmKey(result, data);
00505         (void) KsmKeyEnd(result);
00506     }
00507     /*
00508      * else {
00509      *      On error, a message will have been output
00510      * }
00511      */
00512 
00513     return status;
00514 }
00515 
00516 /*+
00517  * KsmKeyPredict - predict how many keys are needed
00518  *
00519  * Description:
00520  *      Given a policy and a keytype work out how many keys will be required
00521  *      during the timeinterval specified (in seconds).
00522  *
00523  *      We assume no emergency rollover and that a key has just been published
00524  *
00525  *      Dt      = interval
00526  *      Sp      = safety margin
00527  *      Lk      = lifetime of the key (either KSK or ZSK)
00528  *      Ek  = no of standby keys 
00529  * 
00530  *      no of keys = ( (Dt + Sp)/Lk ) + Ek
00531  *      
00532  *      (rounded up)
00533  *
00534  * Arguments:
00535  *      int policy_id
00536  *          The policy in question
00537  *      KSM_TYPE key_type
00538  *          KSK or ZSK
00539  *      int shared_keys 
00540  *          0 if keys not shared between zones
00541  *      int interval
00542  *          timespan (in seconds)
00543  *      int *count
00544  *          (OUT) the number of keys (-1 on error)
00545  *      int rollover_scheme
00546  *          KSK rollover scheme in use
00547  *      int zone_count
00548  *          Number of zones on this policy
00549  *
00550  * Returns:
00551  *      int
00552  *          Status return.  One of:
00553  *
00554  *              0       Success
00555  *              Other   Error
00556 -*/
00557 
00558 int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count) 
00559 { 
00560     int status = 0;   /* Status return */ 
00561     KSM_PARCOLL coll; /* Parameters collection */ 
00562 
00563     /* Check arguments */
00564     if (count == NULL) {
00565         return MsgLog(KSM_INVARG, "NULL count");
00566     }
00567 
00568     /* make sure that we have at least one zone */ 
00569     if (zone_count == 0) { 
00570         *count = 0; 
00571         return status; 
00572     } 
00573 
00574     /* Check that we have a valid key type */
00575     if ((keytype != KSM_TYPE_KSK) && (keytype != KSM_TYPE_ZSK)) {
00576         status = MsgLog(KME_UNKEYTYPE, keytype);
00577         return status;
00578     }
00579 
00580     /* Get list of parameters */
00581     status = KsmParameterCollection(&coll, policy_id);
00582     if (status != 0) {
00583         *count = -1;
00584         return status;
00585     }
00586 
00587     /* We should have the policy now */
00588     if (keytype == KSM_TYPE_KSK)
00589     {
00590         if (coll.ksklife == 0) {
00591             *count = coll.standbyksks + 1;
00592         } 
00593         else if (rollover_scheme == KSM_ROLL_DNSKEY) {
00594             *count = ((interval + coll.pub_safety + coll.propdelay + coll.kskttl)/coll.ksklife) + coll.standbyksks + 1;
00595         }
00596         else if (rollover_scheme == KSM_ROLL_DS) {
00597             *count = ((interval + coll.pub_safety + coll.kskpropdelay + coll.dsttl)/coll.ksklife) + coll.standbyksks + 1;
00598         }
00599 /*        else if (rollover_scheme == KSM_ROLL_RRSET) {
00600             temp = MAX((propdelay + kskttl), (kskpropdelay + dsttl));
00601             if (RFC5011) {
00602                 temp = max(temp, 30*24*60*60);
00603             }
00604             *count = ((interval + coll.pub_safety + temp)/coll.ksklife) + coll.standbyksks + 1;
00605         } */
00606 
00607     }
00608     else if (keytype == KSM_TYPE_ZSK)
00609     {
00610         if (coll.zsklife == 0) {
00611             *count = coll.standbyzsks + 1;
00612         } else {
00613             *count = ((interval + coll.pub_safety)/coll.zsklife) + coll.standbyzsks + 1;
00614         }
00615     } 
00616 
00617     if (shared_keys == KSM_KEYS_NOT_SHARED) { 
00618         *count *= zone_count;
00619     }
00620 
00621     return status;
00622 }
00623 
00624 /*+ 
00625  * KsmKeyCountQueue - Return Number of Keys in the queue before active state 
00626  * 
00627  * Description: 
00628  *      Returns the number of keys in the KSM_STATE_GENERATE, KSM_STATE_PUBLISH,  
00629  *      KSM_STATE_READY and KSM_STATE_ACTIVE state. 
00630  *      (plus KSM_STATE_DSSUB, KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY 
00631  *      for standby KSKs)
00632  * 
00633  * Arguments: 
00634  *      int keytype 
00635  *          Key type, KSK or ZSK 
00636  * 
00637  *      int* count (returned) 
00638  *          Number of keys in the que. 
00639  * 
00640  *      int zone_id 
00641  *          ID of zone that we are looking at (-1 == all zones) 
00642  * 
00643  * Returns: 
00644  *      int 
00645  *          Status return. 0 => success, Other implies error, in which case a 
00646  *          message will have been output. 
00647 -*/ 
00648 
00649 int KsmKeyCountQueue(int keytype, int* count, int zone_id) 
00650 { 
00651     int     clause = 0;     /* Clause count */ 
00652     char*   sql = NULL;     /* SQL to interrogate database */ 
00653     int     status = 0;     /* Status return */ 
00654     char    in[128];        /* Easily large enought for 7 keys */ 
00655     size_t  nchar;          /* Number of output characters */
00656 
00657     /* Create the SQL command to interrogate the database */ 
00658 
00659     nchar = snprintf(in, sizeof(in), "(%d, %d, %d, %d, %d, %d, %d)", 
00660             KSM_STATE_GENERATE, KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_DSSUB, KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY); 
00661     if (nchar >= sizeof(in)) { 
00662         status = MsgLog(KME_BUFFEROVF, "KsmKeyCountQueue"); 
00663         return status; 
00664     }
00665 
00666     sql = DqsCountInit("KEYDATA_VIEW"); 
00667     DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++); 
00668     DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, in, clause++);
00669     if (zone_id != -1) { 
00670         DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++); 
00671     } 
00672     DqsEnd(&sql); 
00673  
00674     /* Execute the query and free resources */ 
00675  
00676     status = DbIntQuery(DbHandle(), count, sql); 
00677     DqsFree(sql); 
00678  
00679     /* Report any errors */ 
00680  
00681     if (status != 0) { 
00682         status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 
00683     } 
00684  
00685     return status; 
00686 }
00687 
00688 /*+ 
00689  * KsmKeyCountStillGood - Return Number of Keys that will still be usable at a particular
00690  *                        time given a number of parameters 
00691  * 
00692  * Description: 
00693  *      Returns the number of keys in the KSM_STATE_GENERATE, KSM_STATE_PUBLISH,
00694  *      KSM_STATE_READY, KSM_STATE_ACTIVE (or KSM_STATE_DSSUB, 
00695  *      KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY for standby KSKs) state after 
00696  *      the given interval. 
00697  * 
00698  * Arguments:
00699  *      int policy_id
00700  *          id of the policy for which they key must have been created 
00701  *              (-1 == all policies)
00702  *      int sm
00703  *          id of security module
00704  *              (-1 == all modules)
00705  *      int bits
00706  *          size of key desired
00707  *              (-1 == all sizes)
00708  *      int algorithm
00709  *          algorithm of key desired
00710  *              (-1 == all algorithms`)
00711  *      int interval
00712  *          how many seconds in the future we are talking about
00713  *      const char* datetime
00714  *          string describing when this calculation is being run
00715  * 
00716  *      int* count (returned) 
00717  *          Number of keys in the que. 
00718  * 
00719  *      int keytype 
00720  *          Key type, KSK or ZSK 
00721  * 
00722  * Returns: 
00723  *      int 
00724  *          Status return. 0 => success, Other implies error, in which case a 
00725  *          message will have been output. 
00726 -*/ 
00727  
00728 int KsmKeyCountStillGood(int policy_id, int sm, int bits, int algorithm, int interval, const char* datetime, int *count, int keytype)
00729 { 
00730     int     where = 0;      /* WHERE clause value */
00731     char*   sql = NULL;     /* SQL to interrogate database */ 
00732     int     status = 0;     /* Status return */ 
00733     char    in[128];        /* Easily large enought for three keys */ 
00734     char    buffer[512];    /* For constructing part of the command */
00735     size_t  nchar;          /* Number of output characters */
00736     int     total_interval; /* interval plus retirement time */
00737     KSM_PARCOLL collection; /* Parameters collection */
00738  
00739     /* 
00740      * Construct the "IN" statement listing the states of the keys that 
00741      * are included in the output. 
00742      */ 
00743 
00744     /* Get list of parameters */
00745     status = KsmParameterCollection(&collection, policy_id);
00746     if (status != 0) {
00747         return status;
00748     }
00749 
00750     if (keytype == KSM_TYPE_ZSK)
00751     {
00752         total_interval = KsmParameterZskTtl(&collection) +
00753                          KsmParameterPropagationDelay(&collection) +
00754                          KsmParameterPubSafety(&collection) +
00755                          interval;
00756     } else {
00757         total_interval = KsmParameterKskTtl(&collection) +
00758                          KsmParameterKskPropagationDelay(&collection) +
00759                          KsmParameterPubSafety(&collection) +
00760                          interval;
00761     }
00762 
00763     nchar = snprintf(in, sizeof(in), "(%d, %d, %d, %d, %d, %d, %d)", 
00764         KSM_STATE_GENERATE, KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_DSSUB, KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY); 
00765     if (nchar >= sizeof(in)) { 
00766         status = MsgLog(KME_BUFFEROVF, "KsmKeyCountStillGood"); 
00767         return status; 
00768     } 
00769 
00770     /* 
00771      * TODO is there an alternative to DATE_ADD which is more generic? 
00772      */
00773 #ifdef USE_MYSQL
00774     nchar = snprintf(buffer, sizeof(buffer),
00775         "DATE_ADD('%s', INTERVAL %d SECOND)", datetime, total_interval);
00776 #else
00777     nchar = snprintf(buffer, sizeof(buffer),
00778         "DATETIME('%s', '+%d SECONDS')", datetime, total_interval);
00779 #endif /* USE_MYSQL */
00780     if (nchar >= sizeof(buffer)) {
00781         status = MsgLog(KME_BUFFEROVF, "KsmKeyCountStillGood");
00782         return status;
00783     }
00784 
00785     /* Create the SQL command to interrogate the database */ 
00786  
00787     sql = DqsCountInit("KEYDATA_VIEW");
00788     if (policy_id != -1) {
00789         DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
00790     }
00791     if (sm != -1) {
00792         DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
00793     }
00794     if (bits != -1) {
00795         DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
00796     }
00797     if (algorithm != -1) {
00798         DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
00799     }
00800 
00801     DqsConditionKeyword(&sql, "(STATE", DQS_COMPARE_IN, in, where++);
00802     StrAppend(&sql, " or STATE is NULL)");
00803     
00804     /* Can't use our generic functions for this aggregated clause */
00805 #ifdef USE_MYSQL
00806     StrAppend(&sql, " and (RETIRE > ");
00807 #else
00808     StrAppend(&sql, " and (DATETIME(RETIRE) > ");
00809 #endif /* USE_MYSQL */
00810     StrAppend(&sql, buffer);
00811     StrAppend(&sql, " or RETIRE is NULL)");
00812 
00813     /*DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);*/
00814     DqsEnd(&sql); 
00815  
00816     /* Execute the query and free resources */ 
00817  
00818     status = DbIntQuery(DbHandle(), count, sql); 
00819     DqsFree(sql); 
00820  
00821     /* Report any errors */ 
00822  
00823     if (status != 0) { 
00824         status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle())); 
00825     } 
00826  
00827     return status; 
00828 }
00829 
00830 /*+
00831  * KsmKeyGetUnallocated
00832  *
00833  * Description:
00834  *      Given a set of policy values get the next unallocated keypair
00835  *      Executes:
00836  *          select min(id) from keydata 
00837  *              where policy_id = policy_id 
00838  *                and securitymodule_id = sm 
00839  *                and size = bits 
00840  *                and algorithm = algorithm 
00841  *                and state is KSM_STATE_GENERATE
00842  *
00843  * Arguments:
00844  *      int policy_id
00845  *          id of the policy for which they key must have been created
00846  *      int sm
00847  *          id of security module
00848  *      int bits
00849  *          size of key desired
00850  *      int algorithm
00851  *          algorithm of key desired
00852  *      int zone_id
00853  *          zone we are allocating to
00854  *      int share_keys
00855  *          0 if keys are not shared; 1 if they are
00856  *      int *keypair_id (out)
00857  *          id of next keypair
00858  *
00859  * Returns:
00860  *      int
00861  *          Status return.  0=> Success, non-zero => error.
00862  *          -1 == no free keys on that policy
00863  */
00864 
00865 int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int share_keys, int *keypair_id) 
00866 {
00867 
00868     int     where = 0;          /* WHERE clause value */
00869     char*   sql = NULL;         /* SQL query */
00870     DB_RESULT       result;     /* Handle converted to a result object */
00871     DB_ROW      row = NULL;     /* Row data */
00872     int     status = 0;         /* Status return */
00873     char    in_sql[1024];
00874     char    in_sql2[1024];
00875 
00876     if (share_keys == KSM_KEYS_NOT_SHARED) {
00877         /* Construct the query */
00878         sql = DqsSpecifyInit("KEYDATA_VIEW","min(id)");
00879         DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
00880         DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
00881         DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
00882         DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
00883         DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);
00884     } else {
00885         snprintf(in_sql, 1024, "(select id from KEYALLOC_VIEW where zone_id = %d)", zone_id);
00886         snprintf(in_sql2, 1024, "(select distinct id from KEYDATA_VIEW where policy_id = %d and state in (%d, %d))", policy_id, KSM_STATE_RETIRE, KSM_STATE_DEAD);
00887 
00888         /* Construct the query */
00889         sql = DqsSpecifyInit("KEYALLOC_VIEW","min(id)");
00890         DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
00891         DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
00892         DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
00893         DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
00894         DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);
00895         DqsConditionKeyword(&sql, "id", DQS_COMPARE_NOT_IN, in_sql, where++);
00896         DqsConditionKeyword(&sql, "id", DQS_COMPARE_NOT_IN, in_sql2, where++);
00897     }
00898     /* Execute query and free up the query string */
00899     status = DbExecuteSql(DbHandle(), sql, &result);
00900     DqsFree(sql);
00901     
00902     if (status != 0)
00903     {
00904         status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
00905         DbFreeResult(result);
00906         return status;
00907         }
00908 
00909     /* Get the next row from the data */
00910     status = DbFetchRow(result, &row);
00911     if (status == 0) {
00912         DbInt(row, DB_KEYDATA_ID, keypair_id);
00913     }
00914     else if (status == -1) {}
00915         /* No rows to return (but no DB error) */
00916         else {
00917         status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
00918         }
00919 
00920     DbFreeRow(row);
00921     DbFreeResult(result);
00922     return status;
00923 }
00924 
00925 /*+
00926  * KsmMarkKeysAsDead - When deleting zones we may need to indicate that keys are now dead
00927  *                     (i.e. when keysharing is turned off or if we removed is the last zone on a policy)
00928  *
00929  * Description:
00930  *      Marks selected keys as dead in the database.
00931  *
00932  * Arguments:
00933  *      int zone_id
00934  *          ID of the zone (-1 if all zones are being removed)
00935  *
00936  * Returns:
00937  *      int
00938  *          Status return.  0=> Success, non-zero => error.
00939 -*/
00940 
00941 int KsmMarkKeysAsDead(int zone_id)
00942 {
00943     int status = 0;
00944 
00945     DB_RESULT       result;         /* Result of query */
00946     KSM_KEYDATA     data;           /* key information */
00947     char*           sql = NULL;     /* SQL query */
00948     int             clause = 0;
00949 
00950     /* Find all the keys which are on that zone but are not already dead */
00951     sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
00952     DqsConditionInt(&sql, "state", DQS_COMPARE_LT, KSM_STATE_DEAD, clause++);
00953     DqsConditionInt(&sql, "state", DQS_COMPARE_GT, KSM_STATE_GENERATE, clause++);
00954     if (zone_id != -1) {
00955         DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, clause++);
00956     }
00957     DqsEnd(&sql);
00958 
00959     /* Now iterate round the keys meeting the condition and print them */
00960 
00961     status = KsmKeyInitSql(&result, sql);
00962     if (status == 0) {
00963         status = KsmKey(result, &data);
00964         while (status == 0) {
00965 
00966             /* Kill the Key */
00967                         status = KsmKillKey(data.keypair_id);
00968                         if (status == 0) {
00969                                 status = KsmKey(result, &data);
00970                         }
00971         }
00972 
00973         /* Convert EOF status to success */
00974 
00975         if (status == -1) {
00976             status = 0;
00977         }
00978 
00979         KsmKeyEnd(result);
00980     }
00981 
00982     return 0;
00983 }
00984 
00985 /*+
00986  * KsmKillKey - Update key status to "dead"
00987  *
00988  * Description:
00989  *      Changes a keys status to dead (from any state)
00990  *
00991  * Arguments:
00992  *      int keypair_id
00993  *          Which key to process
00994  *
00995  * Returns:
00996  *      int
00997  *          Status return.  0=> Success, non-zero => error.
00998 -*/
00999 
01000 int KsmKillKey(int keypair_id)
01001 {
01002     int         status = 0;         /* Status return */
01003     char*       sql = NULL;         /* SQL Statement */
01004     int         set = 0;
01005     char*       now = DtParseDateTimeString("now");
01006 
01007     /* Check datetime in case it came back NULL */
01008     if (now == NULL) {
01009         printf("Couldn't turn \"now\" into a date, quitting...\n");
01010         exit(1);
01011     }
01012 
01013     sql = DusInit("dnsseckeys");
01014     DusSetInt(&sql, "STATE", KSM_STATE_DEAD, set++);
01015     DusSetString(&sql, "DEAD", now, set++);
01016     DusConditionInt(&sql, "ID", DQS_COMPARE_EQ, keypair_id, 0);
01017     DusEnd(&sql);
01018 
01019     /* Execute the statement */
01020 
01021     status = DbExecuteSqlNoResult(DbHandle(), sql);
01022     DusFree(sql);
01023 
01024     StrFree(now);
01025 
01026     return status;
01027 }
01028 

Generated on Mon Oct 31 2011 14:38:30 for OpenDNSSEC-enforcer by  doxygen 1.7.1