dnssec.c revision 1.6
1/*	$OpenBSD: dnssec.c,v 1.6 2001/06/29 18:52:16 ho Exp $	*/
2
3/*
4 * Copyright (c) 2001 H�kan Olsson.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/types.h>
30#include <netinet/in.h>
31#include <arpa/nameser.h>
32#include <arpa/inet.h>
33#include <stdlib.h>
34
35#include <openssl/rsa.h>
36#include <dns/keyvalues.h>
37#include <lwres/lwres.h>
38#include <lwres/netdb.h>
39
40#include "sysdep.h"
41
42#include "dnssec.h"
43#include "exchange.h"
44#include "ipsec_num.h"
45#include "libcrypto.h"
46#include "log.h"
47#include "message.h"
48#include "transport.h"
49#include "util.h"
50
51/* adapted from <dns/rdatastruct.h> / RFC 2535  */
52struct dns_rdata_key {
53  u_int16_t flags;
54  u_int8_t protocol;
55  u_int8_t algorithm;
56  u_int16_t datalen;
57  unsigned char *data;
58};
59
60/* XXX IPv4 specific */
61void *
62dns_get_key (int type, struct message *msg, int *keylen)
63{
64  struct rrsetinfo *rr;
65  struct hostent *hostent;
66  struct sockaddr *dst;
67  int ret, i;
68  struct dns_rdata_key key_rr;
69  u_int8_t algorithm;
70
71  switch (type)
72    {
73    case IKE_AUTH_RSA_SIG:
74      algorithm = DNS_KEYALG_RSA;
75      break;
76
77    case IKE_AUTH_RSA_ENC:
78    case IKE_AUTH_RSA_ENC_REV:
79      /* XXX Not yet. */
80      /* algorithm = DNS_KEYALG_RSA; */
81      return 0;
82
83    case IKE_AUTH_DSS:
84      /* XXX Not yet. */
85      /* algorithm = DNS_KEYALG_DSS; */
86      return 0;
87
88    case IKE_AUTH_PRE_SHARED:
89    default:
90      return 0;
91    }
92
93  /* Get peer IP address */
94  msg->transport->vtbl->get_dst (msg->transport, &dst);
95  /* Get peer name and aliases */
96  switch (dst->sa_family)
97    {
98    case AF_INET:
99      hostent =
100	lwres_gethostbyaddr ((char *)&((struct sockaddr_in *)dst)->sin_addr,
101			     sizeof (struct in_addr), PF_INET);
102      break;
103    case AF_INET6:
104      hostent =
105	lwres_gethostbyaddr ((char *)&((struct sockaddr_in6 *)dst)->sin6_addr,
106			     sizeof (struct in6_addr), PF_INET6);
107      break;
108    default:
109      log_print ("dns_get_key: unsupported protocol family %d",
110		 dst->sa_family);
111      return 0;
112    }
113
114  if (!hostent)
115    {
116#ifdef USE_DEBUG
117      char *dst_str;
118
119      if (sockaddr2text (dst, &dst_str, 0))
120	dst_str = 0;
121
122      LOG_DBG ((LOG_MISC, 30,
123		"dns_get_key: lwres_gethostbyaddr (%s) failed: %s",
124		dst_str ? dst_str : "<???>", lwres_hstrerror (lwres_h_errno)));
125
126      if (dst_str)
127	free (dst_str);
128#endif
129      return 0;
130    }
131
132  /* Try host official name */
133  LOG_DBG ((LOG_MISC, 50, "dns_get_key: trying KEY RR for %s",
134	    hostent->h_name));
135  ret = lwres_getrrsetbyname (hostent->h_name, C_IN, T_KEY, 0, &rr);
136  if (ret)
137    {
138      /* Try host aliases */
139      i = 0;
140      while (hostent->h_aliases[i] && ret)
141	{
142	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: trying KEY RR for alias %s",
143		    hostent->h_aliases[i]));
144	  ret = lwres_getrrsetbyname (hostent->h_aliases[i], C_IN, T_KEY, 0,
145				      &rr);
146	  i++;
147	}
148    }
149
150  if (ret)
151    {
152      LOG_DBG ((LOG_MISC, 30, "dns_get_key: no DNS responses (error %d)",
153		ret));
154      return 0;
155    }
156
157  LOG_DBG ((LOG_MISC, 80,
158	    "dns_get_key: rrset class %d type %d ttl %d nrdatas %d nrsigs %d",
159	    rr->rri_rdclass, rr->rri_rdtype, rr->rri_ttl, rr->rri_nrdatas,
160	    rr->rri_nsigs));
161
162  /* We don't accept unvalidated data. */
163  if (!(rr->rri_flags & RRSET_VALIDATED))
164    {
165      LOG_DBG ((LOG_MISC, 10, "dns_get_key: got unvalidated response"));
166      lwres_freerrset (rr);
167      return 0;
168    }
169
170  /* Sanity. */
171  if (rr->rri_nrdatas == 0 || rr->rri_rdtype != T_KEY)
172    {
173      LOG_DBG ((LOG_MISC, 30, "dns_get_key: no KEY RRs recieved"));
174      lwres_freerrset (rr);
175      return 0;
176    }
177
178  memset (&key_rr, 0, sizeof key_rr);
179
180  /*
181   * Find a key with the wanted algorithm, if any.
182   * XXX If there are several keys present, we currently only find the first.
183   */
184  for (i = 0; i < rr->rri_nrdatas && key_rr.datalen == 0; i++)
185    {
186      key_rr.flags     = ntohs ((u_int16_t) *rr->rri_rdatas[i].rdi_data);
187      key_rr.protocol  = *(rr->rri_rdatas[i].rdi_data + 2);
188      key_rr.algorithm = *(rr->rri_rdatas[i].rdi_data + 3);
189
190      if (key_rr.protocol != DNS_KEYPROTO_IPSEC)
191	{
192	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored non-IPsec key"));
193	  continue;
194	}
195
196      if (key_rr.algorithm != algorithm)
197	{
198	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored key with other alg"));
199	  continue;
200	}
201
202      key_rr.datalen = rr->rri_rdatas[i].rdi_length - 4;
203      if (key_rr.datalen <= 0)
204	{
205	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored bad key"));
206	  key_rr.datalen = 0;
207	  continue;
208	}
209
210      /* This key seems to fit our requirements... */
211      key_rr.data = (char *)malloc (key_rr.datalen);
212      if (!key_rr.data)
213	{
214	  log_error ("dns_get_key: malloc (%d) failed", key_rr.datalen);
215	  lwres_freerrset (rr);
216	  return 0;
217	}
218      memcpy (key_rr.data, rr->rri_rdatas[i].rdi_data + 4, key_rr.datalen);
219      *keylen = key_rr.datalen;
220    }
221
222  lwres_freerrset (rr);
223
224  if (key_rr.datalen)
225    return key_rr.data;
226  else
227    return 0;
228}
229
230int
231dns_RSA_dns_to_x509 (u_int8_t *key, int keylen, RSA **rsa_key)
232{
233  RSA *rsa;
234  int key_offset;
235  u_int8_t e_len;
236
237  if (!key || keylen <= 0)
238    {
239      log_print ("dns_RSA_dns_to_x509: invalid public key");
240      return -1;
241    }
242
243  rsa = LC (RSA_new, ());
244  if (rsa == NULL)
245    {
246      log_error ("dns_RSA_dns_to_x509: failed to allocate new RSA struct");
247      return -1;
248    }
249
250  e_len = *key;
251  key_offset = 1;
252
253  if (e_len == 0)
254    {
255      if (keylen < 3)
256	{
257	  log_print ("dns_RSA_dns_to_x509: invalid public key");
258	  LC (RSA_free, (rsa));
259	  return -1;
260	}
261      e_len  = *(key + key_offset++) << 8;
262      e_len += *(key + key_offset++);
263    }
264
265  if (e_len > (keylen - key_offset))
266    {
267      log_print ("dns_RSA_dns_to_x509: invalid public key");
268      LC (RSA_free, (rsa));
269      return -1;
270    }
271
272  rsa->e = LC (BN_bin2bn, (key + key_offset, e_len, NULL));
273  key_offset += e_len;
274
275  /* XXX if (keylen <= key_offset) -> "invalid public key" ? */
276
277  rsa->n = LC (BN_bin2bn, (key + key_offset, keylen - key_offset, NULL));
278
279  *rsa_key = rsa;
280
281  LOG_DBG ((LOG_MISC, 30, "dns_RSA_dns_to_x509: got %d bits RSA key",
282	    LC (BN_num_bits, (rsa->n))));
283
284  return 0;
285}
286
287#if notyet
288int
289dns_RSA_x509_to_dns (RSA *rsa_key, u_int8_t *key, int *keylen)
290{
291  return 0;
292}
293#endif
294