1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
/*
* tsig.h -- TSIG definitions (RFC 2845).
*
* Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*/
#ifndef TSIG_H
#define TSIG_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "buffer.h"
#include "dname.h"
#define TSIG_ERROR_NOERROR 0
#define TSIG_ERROR_BADSIG 16
#define TSIG_ERROR_BADKEY 17
#define TSIG_ERROR_BADTIME 18
typedef struct tsig_algorithm tsig_algorithm_type;
typedef struct tsig_key tsig_key_type;
typedef struct tsig_record tsig_record_type;
enum tsig_status
{
TSIG_NOT_PRESENT,
TSIG_OK,
TSIG_ERROR
};
typedef enum tsig_status tsig_status_type;
struct tsig_lookup_struct_table
{
uint8_t id;
const char* short_name;
};
typedef struct tsig_lookup_struct_table tsig_lookup_algorithm_table;
/*
* A TSIG HMAC algorithm, such as hmac-md5.
*/
struct tsig_algorithm
{
/*
* Short name of the algorithm, such as "hmac-md5".
*/
const char *short_name;
/*
* Full wireformat name of the algorithm, such as
* "hmac-md5.sig-alg.reg.int."
*/
const dname_type *wireformat_name;
/*
* The maximum size of a digest generated by this algorithm.
*/
size_t maximum_digest_size;
/*
* Algorithm implementation specific data.
*/
const void *data;
/*
* Create a new HMAC context.
*/
void *(*hmac_create_context)(region_type *region);
/*
* Initialize an HMAC context with the specified algorithm and
* key.
*/
void (*hmac_init_context)(void *context,
tsig_algorithm_type *algorithm,
tsig_key_type *key);
/*
* Update the HMAC context with the specified data.
*/
void (*hmac_update)(void *context, const void *data, size_t size);
/*
* Generate the final digest. DIGEST points to a buffer of at
* least maximum_digest_size bytes.
*/
void (*hmac_final)(void *context, uint8_t *digest, size_t *size);
};
/*
* A TSIG key used to sign and verify packets.
*/
struct tsig_key
{
const dname_type *name;
size_t size;
uint8_t *data;
};
struct tsig_record
{
tsig_status_type status;
size_t position;
size_t response_count;
size_t updates_since_last_prepare;
void *context;
tsig_algorithm_type *algorithm;
tsig_key_type *key;
size_t prior_mac_size;
uint8_t *prior_mac_data;
/* TSIG RR data is allocated in the rr_region. */
region_type *rr_region;
region_type *context_region;
const dname_type *key_name;
const dname_type *algorithm_name;
uint16_t signed_time_high;
uint32_t signed_time_low;
uint16_t signed_time_fudge;
uint16_t mac_size;
uint8_t *mac_data;
uint16_t original_query_id;
uint16_t error_code;
uint16_t other_size;
uint8_t *other_data;
};
/*
* Initialize the TSIG module (including TSIG implementation modules
* such as tsig-openssl).
*/
int tsig_init(region_type *region);
/*
* Add the specified key to the TSIG key table.
*/
void tsig_add_key(tsig_key_type *key);
void tsig_del_key(tsig_key_type *key);
/*
* Add the specified algorithm to the TSIG algorithm table.
*/
void tsig_add_algorithm(tsig_algorithm_type *algorithm);
/*
* Find an HMAC algorithm based on its short name.
*/
tsig_algorithm_type *tsig_get_algorithm_by_name(const char *name);
/*
* Return a descriptive error message based on the TSIG error code.
*/
const char *tsig_error(int error_code);
/*
* Create the tsig record internal structure. Allocs it.
* Call init_record afterwards before doing more with it.
*
* The region is used to attach a cleanup function that destroys the tsig.
*/
void tsig_create_record(tsig_record_type* tsig,
region_type* region);
/*
* Like tsig_create_record, with custom region settings.
* The size params are used to customise the rr_region and context_region.
* If region is NULL, no cleanup is attached to it.
*/
void tsig_create_record_custom(tsig_record_type* tsig,
region_type* region,
size_t chunk_size,
size_t large_object_size,
size_t initial_cleanup_size);
/*
* Destroy tsig record internals (the main ptr is user alloced).
* if region is nonNULL, removes cleanup.
*/
void tsig_delete_record(tsig_record_type* tsig, region_type* region);
/*
* Call this before starting to analyze or signing a sequence of
* packets.
*
* ALGORITHM and KEY are optional and are only needed if you want to
* sign the initial query. Otherwise the key and algorithm are looked
* up in the algorithm and key table when a received TSIG RR is
* processed.
*/
void tsig_init_record(tsig_record_type *data,
tsig_algorithm_type *algorithm,
tsig_key_type *key);
/*
* Validate the TSIG RR key and algorithm from the TSIG RR. Otherwise
* update the TSIG error code. The MAC itself is not validated.
*
* Returns non-zero if the key and algorithm could be validated.
*/
int tsig_from_query(tsig_record_type *tsig);
/*
* Prepare TSIG for signing of a query. This initializes TSIG with
* the algorithm and key stored in the TSIG record.
*/
void tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id);
/*
* Prepare TSIG for performing an HMAC calculation. If the TSIG
* contains a prior HMAC it is inserted first into the hash
* calculation.
*/
void tsig_prepare(tsig_record_type *tsig);
/*
* Add the first LENGTH octets of PACKET to the TSIG hash, replacing
* the PACKET's id with the original query id from TSIG. If the query
* is a response the TSIG response count is incremented.
*/
void tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length);
/*
* Finalize the TSIG record by hashing the TSIG data. If the TSIG
* response count is greater than 1 only the timers are hashed.
* Signed time is set to the current time. The TSIG record can be
* added to a packet using tsig_append_rr().
*
* The calculated MAC is also stored as the prior MAC, so it can be
* used as a running MAC.
*/
void tsig_sign(tsig_record_type *tsig);
/*
* Verify the calculated MAC against the MAC in the TSIG RR.
*
* The calculated MAC is also stored as the prior MAC, so it can be
* used as a running MAC.
*/
int tsig_verify(tsig_record_type *tsig);
/*
* Find the TSIG RR in QUERY and parse it if present. Store the
* parsed results in TSIG.
*
* Returns non-zero if no parsing error occurred, use the tsig->status
* field to find out if the TSIG record was present.
*/
int tsig_find_rr(tsig_record_type *tsig, buffer_type *packet);
/*
* Call this to analyze the TSIG RR starting at the current location
* of PACKET. On success true is returned and the results are stored
* in TSIG.
*
* Returns non-zero if no parsing error occurred, use the tsig->status
* field to find out if the TSIG record was present.
*/
int tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet);
/*
* Append the TSIG record to the response PACKET.
*/
void tsig_append_rr(tsig_record_type *tsig, buffer_type *packet);
/*
* The amount of space to reserve in the response for the TSIG data
* (if required).
*/
size_t tsig_reserved_space(tsig_record_type *tsig);
/*
* status or error_code must already be in error.
* prepares content for error packet.
*/
void tsig_error_reply(tsig_record_type *tsig);
/*
* compare tsig algorithm names case insensitive.
*/
int tsig_strlowercmp(const char* str1, const char* str2);
/*
* cleanup tsig openssl stuff.
*/
void tsig_finalize(void);
#endif /* TSIG_H */
|