typo
[openssl.git] / ssl / dnssec.c
1 #include <openssl/opensslconf.h>
2
3 #include <string.h>
4 #include <openssl/bio.h>
5 #include <openssl/dso.h>
6
7 #include "ssl.h"
8
9 #ifndef OPENSSL_SYS_WIN32
10 #include <netdb.h>
11 #include <sys/socket.h>
12 #endif
13
14 #ifndef OPENSSL_NO_LIBUNBOUND
15 #include <unbound.h>
16
17 static struct ub_ctx *ctx = NULL;
18 static DSO *unbound_dso = NULL;
19
20 static union {
21         void *p; struct ub_ctx *(*f)(); }
22         p_ub_ctx_create = {NULL};
23
24 static union {
25         void *p; int (*f)(struct ub_ctx *,const char *); }
26         p_ub_ctx_resolvconf = {NULL};
27
28 static union {
29         void *p; int (*f)(struct ub_ctx *,const char *); }
30         p_ub_ctx_add_ta_file = {NULL};
31
32 static union {
33         void *p; void (*f)(struct ub_ctx *); }
34         p_ub_ctx_delete = {NULL};
35
36 static union {
37         void *p; int (*f)(struct ub_ctx *,const char *,int,int,struct ub_result**); }
38         p_ub_resolve = {NULL};
39
40 static union {
41         void *p; void (*f)(struct ub_result*); }
42         p_ub_resolve_free = {NULL};
43
44 #if defined(__GNUC__) && __GNUC__>=2
45  static void unbound_init(void) __attribute__((constructor));
46  static void unbound_fini(void) __attribute__((destructor));
47 #endif 
48
49 static void unbound_init(void)
50 {
51         DSO *dso;
52
53         if ((dso = DSO_load(NULL, "unbound", NULL, 0)) == NULL) return;
54
55         if ((p_ub_ctx_create.p = DSO_bind_func(dso,"ub_ctx_create")) == NULL ||
56             (p_ub_ctx_resolvconf.p = DSO_bind_func(dso,"ub_ctx_resolvconf")) == NULL ||
57             (p_ub_ctx_add_ta_file.p = DSO_bind_func(dso,"ub_ctx_add_ta_file")) == NULL ||
58             (p_ub_ctx_delete.p = DSO_bind_func(dso,"ub_ctx_delete")) == NULL ||
59             (p_ub_resolve.p = DSO_bind_func(dso,"ub_resolve")) == NULL ||
60             (p_ub_resolve_free.p = DSO_bind_func(dso,"ub_resolve_free")) == NULL ||
61             (ctx = p_ub_ctx_create.f()) == NULL) {
62                 DSO_free(dso);
63                 return;
64         }
65
66         unbound_dso = dso;
67
68         /* FIXME: parameterize these through CONF */
69         p_ub_ctx_resolvconf.f(ctx,"/etc/resolv.conf");
70         p_ub_ctx_add_ta_file.f(ctx,"/var/lib/unbound/root.key");
71 }
72
73 static void unbound_fini(void)
74 {
75         if (ctx != NULL) p_ub_ctx_delete.f(ctx);
76         if (unbound_dso != NULL) DSO_free(unbound_dso);
77 }
78 #endif
79
80 /*
81  * Output is array packed as [len][data][len][data][0]
82  */
83 unsigned char *SSL_get_tlsa_record_byname (const char *name,int port,int type)
84 {
85         unsigned char *ret=NULL;
86         char *query=NULL;
87         size_t qlen;
88
89 #ifndef OPENSSL_NO_LIBUNBOUND
90         if (ctx == NULL) return NULL;
91 #elif defined(RRSET_VALIDATED)
92         static union {
93                 void *p; int (*f)(const char*,unsigned int,unsigned int,unsigned int,struct rrsetinfo **); }
94                 p_getrrsetbyname = {NULL};
95         static union {
96                 void *p; void (*f)(struct rrsetinfo *); }
97                 p_freerrset = {NULL};
98
99         if (p_getrrsetbyname.p==NULL) {
100                 if ((p_getrrsetbyname.p = DSO_global_lookup("getrrsetbyname")) == NULL ||
101                     (p_freerrset.p = DSO_global_lookup("freerrset")) == NULL)
102                         p_getrrsetbyname.p = (void*)-1;
103         }
104
105         if (p_getrrsetbyname.p == (void *)-1) return NULL;
106 #endif
107
108         qlen = 7+5+strlen(name)+1;
109         if ((query = OPENSSL_malloc(qlen)) == NULL)
110                 return NULL;
111
112         BIO_snprintf(query,qlen,"_%u._%s.%s",port&0xffff,type==SOCK_STREAM?"tcp":"udp",name);
113
114 #ifndef OPENSSL_NO_LIBUNBOUND
115         {
116         struct ub_result *tlsa=NULL;
117
118         if (p_ub_resolve.f(ctx,query,52,1,&tlsa)==0 &&
119             tlsa->havedata && tlsa->data[0]!=NULL) {
120                 ret=(void*)-1;  /* -1 means insecure */
121                 if (tlsa->secure) do {
122                         unsigned char *data;
123                         unsigned int dlen, i;
124
125                         for (dlen=0, i=0; tlsa->data[i]; i++)
126                                 dlen += sizeof(int)+(unsigned int)tlsa->len[i];
127                         dlen +=sizeof(int);
128
129                         if ((ret = OPENSSL_malloc(dlen)) == NULL) break;
130                         
131                         for (data=ret, i=0; tlsa->data[i]; i++) {
132                                 dlen = (unsigned int)tlsa->len[i];
133                                 memcpy(data,&dlen,sizeof(dlen));
134                                 data += sizeof(dlen);
135                                 memcpy(data,tlsa->data[i],dlen);
136                                 data += dlen;
137                         }
138                         dlen = 0;
139                         memcpy(data,&dlen,sizeof(dlen)); /* trailing zero */
140                 } while (0);    
141                 p_ub_resolve_free.f(tlsa);
142         }
143         }
144 #elif defined(RRSET_VALIDATED)
145         {
146         struct rrsetinfo *rrset=NULL;
147
148         if (p_getrrsetbyname.f(query,1,52,RRSET_VALIDATED,&rrset) == 0 && rrset->rri_nrdatas) {
149                 ret=(void*)-1;  /* -1 means insecure */
150                 if ((rrset->rri_flags&RRSET_VALIDATED)) do {
151                         unsigned char *data;
152                         unsigned int dlen, i;
153
154                         for (dlen=0, i=0; i<rrset->rri_nrdatas; i++)
155                                 dlen += sizeof(int)+rrset->rri_rdatas[i].rdi_length;
156                         dlen +=sizeof(int);
157
158                         if ((ret = OPENSSL_malloc(sizeof(int)+dlen)) == NULL) break;
159
160                         for (data=ret, i=0; i<rrset->rri_rdatas[i].rdi_length; i++) {
161                                 *(unsigned int *)data = dlen = rrset->rri_rdatas[i].rdi_length;
162                                 data += sizeof(unsigned int);
163                                 memcpy(data,rrset->rri_rdatas[i].rdi_data,dlen);
164                                 data += dlen;
165                         }
166                         *(unsigned int *)data = 0;      /* trailing zero */
167                 } while (0);    
168                 p_freerrset.f(rrset);
169         }
170         }
171 #elif defined(_WIN32_NOT_YET)
172         {
173         PDNS_RECORD rrset;
174
175         DnsQuery_A(query,52,DNS_QUERY_STANDARD,NULL,&rrset,NULL);
176         DnsRecordListFree(rrset,DnsFreeRecordList);
177         }
178 #endif
179         CRYPTO_free(query);
180
181         return ret;
182 }