dnssec.c revision 1.3
1/*	$OpenBSD: dnssec.c,v 1.3 2001/01/27 15:39:54 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
50/* adapted from <dns/rdatastruct.h> / RFC 2535  */
51struct dns_rdata_key {
52  u_int16_t flags;
53  u_int8_t protocol;
54  u_int8_t algorithm;
55  u_int16_t datalen;
56  unsigned char *data;
57};
58
59/* XXX IPv4 specific */
60void *
61dns_get_key (int type, struct message *msg, int *keylen)
62{
63  struct rrsetinfo *rr;
64  struct hostent *hostent;
65  struct sockaddr_in *dst;
66  int ret, i;
67  struct dns_rdata_key key_rr;
68  u_int8_t algorithm;
69
70  switch (type)
71    {
72    case IKE_AUTH_RSA_SIG:
73      algorithm = DNS_KEYALG_RSA;
74      break;
75
76    case IKE_AUTH_RSA_ENC:
77    case IKE_AUTH_RSA_ENC_REV:
78      /* XXX Not yet. */
79      /* algorithm = DNS_KEYALG_RSA; */
80      return 0;
81
82    case IKE_AUTH_DSS:
83      /* XXX Not yet. */
84      /* algorithm = DNS_KEYALG_DSS; */
85      return 0;
86
87    case IKE_AUTH_PRE_SHARED:
88    default:
89      return 0;
90    }
91
92  /* Get peer IP address */
93  msg->transport->vtbl->get_dst (msg->transport, (struct sockaddr **)&dst, &i);
94  /* Get peer name and aliases */
95  hostent = lwres_gethostbyaddr ((char *)&dst->sin_addr,
96				 sizeof (struct in_addr), PF_INET);
97
98  if (!hostent)
99    {
100      LOG_DBG ((LOG_MISC, 30,
101		"dns_get_key: lwres_gethostbyaddr (%s) failed: %s",
102		inet_ntoa (((struct sockaddr_in *)dst)->sin_addr),
103		lwres_hstrerror (lwres_h_errno)));
104      return 0;
105    }
106
107  /* Try host official name */
108  LOG_DBG ((LOG_MISC, 50, "dns_get_key: trying KEY RR for %s",
109	    hostent->h_name));
110  ret = lwres_getrrsetbyname (hostent->h_name, C_IN, T_KEY, 0, &rr);
111  if (ret)
112    {
113      /* Try host aliases */
114      i = 0;
115      while (hostent->h_aliases[i] && ret)
116	{
117	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: trying KEY RR for alias %s",
118		    hostent->h_aliases[i]));
119	  ret = lwres_getrrsetbyname (hostent->h_aliases[i], C_IN, T_KEY, 0,
120				      &rr);
121	  i++;
122	}
123    }
124
125  if (ret)
126    {
127      LOG_DBG ((LOG_MISC, 30, "dns_get_key: no DNS responses (error %d)",
128		ret));
129      return 0;
130    }
131
132  LOG_DBG ((LOG_MISC, 80,
133	    "dns_get_key: rrset class %d type %d ttl %d nrdatas %d nrsigs %d",
134	    rr->rri_rdclass, rr->rri_rdtype, rr->rri_ttl, rr->rri_nrdatas,
135	    rr->rri_nsigs));
136
137  /* We don't accept unvalidated data. */
138  if (!(rr->rri_flags & RRSET_VALIDATED))
139    {
140      LOG_DBG ((LOG_MISC, 10, "dns_get_key: got unvalidated response"));
141      lwres_freerrset (rr);
142      return 0;
143    }
144
145  /* Sanity. */
146  if (rr->rri_nrdatas == 0 || rr->rri_rdtype != T_KEY)
147    {
148      LOG_DBG ((LOG_MISC, 30, "dns_get_key: no KEY RRs recieved"));
149      lwres_freerrset (rr);
150      return 0;
151    }
152
153  memset (&key_rr, 0, sizeof key_rr);
154
155  /*
156   * Find a key with the wanted algorithm, if any.
157   * XXX If there are several keys present, we currently only find the first.
158   */
159  for (i = 0; i < rr->rri_nrdatas && key_rr.datalen == 0; i++)
160    {
161      key_rr.flags     = ntohs ((u_int16_t) *rr->rri_rdatas[i].rdi_data);
162      key_rr.protocol  = *(rr->rri_rdatas[i].rdi_data + 2);
163      key_rr.algorithm = *(rr->rri_rdatas[i].rdi_data + 3);
164
165      if (key_rr.protocol != DNS_KEYPROTO_IPSEC)
166	{
167	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored non-IPSEC key"));
168	  continue;
169	}
170
171      if (key_rr.algorithm != algorithm)
172	{
173	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored key with other alg"));
174	  continue;
175	}
176
177      key_rr.datalen = rr->rri_rdatas[i].rdi_length - 4;
178      if (key_rr.datalen <= 0)
179	{
180	  LOG_DBG ((LOG_MISC, 50, "dns_get_key: ignored bad key"));
181	  key_rr.datalen = 0;
182	  continue;
183	}
184
185      /* This key seems to fit our requirements... */
186      key_rr.data = (char *)malloc (key_rr.datalen);
187      if (!key_rr.data)
188	{
189	  log_error ("dns_get_key: malloc (%d) failed", key_rr.datalen);
190	  lwres_freerrset (rr);
191	  return 0;
192	}
193      memcpy (key_rr.data, rr->rri_rdatas[i].rdi_data + 4, key_rr.datalen);
194      *keylen = key_rr.datalen;
195    }
196
197  lwres_freerrset (rr);
198
199  if (key_rr.datalen)
200    return key_rr.data;
201  else
202    return 0;
203}
204
205int
206dns_RSA_dns_to_x509 (u_int8_t *key, int keylen, RSA **rsa_key)
207{
208  RSA *rsa;
209  int key_offset;
210  u_int8_t e_len;
211
212  if (!key || keylen <= 0)
213    {
214      log_print ("dns_RSA_dns_to_x509: invalid public key");
215      return -1;
216    }
217
218  rsa = LC (RSA_new, ());
219  if (rsa == NULL)
220    {
221      log_error ("dns_RSA_dns_to_x509: failed to allocate new RSA struct");
222      return -1;
223    }
224
225  e_len = *key;
226  key_offset = 1;
227
228  if (e_len == 0)
229    {
230      if (keylen < 3)
231	{
232	  log_print ("dns_RSA_dns_to_x509: invalid public key");
233	  LC (RSA_free, (rsa));
234	  return -1;
235	}
236      e_len  = *(key + key_offset++) << 8;
237      e_len += *(key + key_offset++);
238    }
239
240  if (e_len > (keylen - key_offset))
241    {
242      log_print ("dns_RSA_dns_to_x509: invalid public key");
243      LC (RSA_free, (rsa));
244      return -1;
245    }
246
247  rsa->e = LC (BN_bin2bn, (key + key_offset, e_len, NULL));
248  key_offset += e_len;
249
250  /* XXX if (keylen <= key_offset) -> "invalid public key" ? */
251
252  rsa->n = LC (BN_bin2bn, (key + key_offset, keylen - key_offset, NULL));
253
254  *rsa_key = rsa;
255
256  LOG_DBG ((LOG_MISC, 30, "dns_RSA_dns_to_x509: got %d bits RSA key",
257	    LC (BN_num_bits, (rsa->n))));
258
259  return 0;
260}
261
262#if notyet
263int
264dns_RSA_x509_to_dns (RSA *rsa_key, u_int8_t *key, int *keylen)
265{
266  return 0;
267}
268#endif
269