summaryrefslogtreecommitdiff
path: root/usr.sbin/nsd/tsig.h
blob: 1c2c1211715fd3069e37739443c6ea5b72254209 (plain)
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_ */