Back to index

tor  0.2.3.19-rc
dnsserv.c
Go to the documentation of this file.
00001 /* Copyright (c) 2007-2012, The Tor Project, Inc. */
00002 /* See LICENSE for licensing information */
00003 
00011 #include "or.h"
00012 #include "dnsserv.h"
00013 #include "config.h"
00014 #include "connection.h"
00015 #include "connection_edge.h"
00016 #include "control.h"
00017 #include "main.h"
00018 #include "policies.h"
00019 #ifdef HAVE_EVENT2_DNS_H
00020 #include <event2/dns.h>
00021 #include <event2/dns_compat.h>
00022 /* XXXX this implies we want an improved evdns  */
00023 #include <event2/dns_struct.h>
00024 #else
00025 #include "eventdns.h"
00026 #endif
00027 
00031 static void
00032 evdns_server_callback(struct evdns_server_request *req, void *data_)
00033 {
00034   const listener_connection_t *listener = data_;
00035   entry_connection_t *entry_conn;
00036   edge_connection_t *conn;
00037   int i = 0;
00038   struct evdns_server_question *q = NULL;
00039   struct sockaddr_storage addr;
00040   struct sockaddr *sa;
00041   int addrlen;
00042   tor_addr_t tor_addr;
00043   uint16_t port;
00044   int err = DNS_ERR_NONE;
00045   char *q_name;
00046 
00047   tor_assert(req);
00048 
00049   log_info(LD_APP, "Got a new DNS request!");
00050 
00051   req->flags |= 0x80; /* set RA */
00052 
00053   /* First, check whether the requesting address matches our SOCKSPolicy. */
00054   if ((addrlen = evdns_server_request_get_requesting_addr(req,
00055                       (struct sockaddr*)&addr, (socklen_t)sizeof(addr))) < 0) {
00056     log_warn(LD_APP, "Couldn't get requesting address.");
00057     evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
00058     return;
00059   }
00060   (void) addrlen;
00061   sa = (struct sockaddr*) &addr;
00062   if (tor_addr_from_sockaddr(&tor_addr, sa, &port)<0) {
00063     log_warn(LD_APP, "Requesting address wasn't recognized.");
00064     evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
00065     return;
00066   }
00067 
00068   if (!socks_policy_permits_address(&tor_addr)) {
00069     log_warn(LD_APP, "Rejecting DNS request from disallowed IP.");
00070     evdns_server_request_respond(req, DNS_ERR_REFUSED);
00071     return;
00072   }
00073 
00074   /* Now, let's find the first actual question of a type we can answer in this
00075    * DNS request.  It makes us a little noncompliant to act like this; we
00076    * should fix that eventually if it turns out to make a difference for
00077    * anybody. */
00078   if (req->nquestions == 0) {
00079     log_info(LD_APP, "No questions in DNS request; sending back nil reply.");
00080     evdns_server_request_respond(req, 0);
00081     return;
00082   }
00083   if (req->nquestions > 1) {
00084     log_info(LD_APP, "Got a DNS request with more than one question; I only "
00085              "handle one question at a time for now.  Skipping the extras.");
00086   }
00087   for (i = 0; i < req->nquestions; ++i) {
00088     if (req->questions[i]->dns_question_class != EVDNS_CLASS_INET)
00089       continue;
00090     switch (req->questions[i]->type) {
00091       case EVDNS_TYPE_A:
00092       case EVDNS_TYPE_PTR:
00093         q = req->questions[i];
00094       default:
00095         break;
00096       }
00097   }
00098   if (!q) {
00099     log_info(LD_APP, "None of the questions we got were ones we're willing "
00100              "to support. Sending NOTIMPL.");
00101     evdns_server_request_respond(req, DNS_ERR_NOTIMPL);
00102     return;
00103   }
00104   if (q->type != EVDNS_TYPE_A) {
00105     tor_assert(q->type == EVDNS_TYPE_PTR);
00106   }
00107 
00108   /* Make sure the name isn't too long: This should be impossible, I think. */
00109   if (err == DNS_ERR_NONE && strlen(q->name) > MAX_SOCKS_ADDR_LEN-1)
00110     err = DNS_ERR_FORMAT;
00111 
00112   if (err != DNS_ERR_NONE) {
00113     /* We got an error?  Then send back an answer immediately; we're done. */
00114     evdns_server_request_respond(req, err);
00115     return;
00116   }
00117 
00118   /* Make a new dummy AP connection, and attach the request to it. */
00119   entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
00120   conn = ENTRY_TO_EDGE_CONN(entry_conn);
00121   TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT;
00122   conn->is_dns_request = 1;
00123 
00124   tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr);
00125   TO_CONN(conn)->port = port;
00126   TO_CONN(conn)->address = tor_dup_addr(&tor_addr);
00127 
00128   if (q->type == EVDNS_TYPE_A)
00129     entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
00130   else
00131     entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
00132 
00133   strlcpy(entry_conn->socks_request->address, q->name,
00134           sizeof(entry_conn->socks_request->address));
00135 
00136   entry_conn->socks_request->listener_type = listener->_base.type;
00137   entry_conn->dns_server_request = req;
00138   entry_conn->isolation_flags = listener->isolation_flags;
00139   entry_conn->session_group = listener->session_group;
00140   entry_conn->nym_epoch = get_signewnym_epoch();
00141 
00142   if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) {
00143     log_warn(LD_APP, "Couldn't register dummy connection for DNS request");
00144     evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
00145     connection_free(ENTRY_TO_CONN(entry_conn));
00146     return;
00147   }
00148 
00149   control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
00150 
00151   /* Now, unless a controller asked us to leave streams unattached,
00152   * throw the connection over to get rewritten (which will
00153   * answer it immediately if it's in the cache, or completely bogus, or
00154   * automapped), and then attached to a circuit. */
00155   log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
00156            escaped_safe_str_client(q->name));
00157   q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */
00158   connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
00159   /* Now, the connection is marked if it was bad. */
00160 
00161   log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
00162            escaped_safe_str_client(q_name));
00163   tor_free(q_name);
00164 }
00165 
00171 int
00172 dnsserv_launch_request(const char *name, int reverse)
00173 {
00174   entry_connection_t *entry_conn;
00175   edge_connection_t *conn;
00176   char *q_name;
00177 
00178   /* Make a new dummy AP connection, and attach the request to it. */
00179   entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
00180   conn = ENTRY_TO_EDGE_CONN(entry_conn);
00181   conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
00182 
00183   if (reverse)
00184     entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
00185   else
00186     entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
00187 
00188   conn->is_dns_request = 1;
00189 
00190   strlcpy(entry_conn->socks_request->address, name,
00191           sizeof(entry_conn->socks_request->address));
00192 
00193   entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER;
00194   entry_conn->original_dest_address = tor_strdup(name);
00195   entry_conn->session_group = SESSION_GROUP_CONTROL_RESOLVE;
00196   entry_conn->nym_epoch = get_signewnym_epoch();
00197   entry_conn->isolation_flags = ISO_DEFAULT;
00198 
00199   if (connection_add(TO_CONN(conn))<0) {
00200     log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request");
00201     connection_free(TO_CONN(conn));
00202     return -1;
00203   }
00204 
00205   /* Now, unless a controller asked us to leave streams unattached,
00206   * throw the connection over to get rewritten (which will
00207   * answer it immediately if it's in the cache, or completely bogus, or
00208   * automapped), and then attached to a circuit. */
00209   log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
00210            escaped_safe_str_client(name));
00211   q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */
00212   connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
00213   /* Now, the connection is marked if it was bad. */
00214 
00215   log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
00216            escaped_safe_str_client(q_name));
00217   tor_free(q_name);
00218   return 0;
00219 }
00220 
00223 void
00224 dnsserv_reject_request(entry_connection_t *conn)
00225 {
00226   if (conn->dns_server_request) {
00227     evdns_server_request_respond(conn->dns_server_request,
00228                                  DNS_ERR_SERVERFAILED);
00229     conn->dns_server_request = NULL;
00230   }
00231 }
00232 
00236 static const char *
00237 evdns_get_orig_address(const struct evdns_server_request *req,
00238                        int rtype, const char *addr)
00239 {
00240   int i, type;
00241 
00242   switch (rtype) {
00243   case RESOLVED_TYPE_IPV4:
00244     type = EVDNS_TYPE_A;
00245     break;
00246   case RESOLVED_TYPE_HOSTNAME:
00247     type = EVDNS_TYPE_PTR;
00248     break;
00249   case RESOLVED_TYPE_IPV6:
00250     type = EVDNS_TYPE_AAAA;
00251     break;
00252   default:
00253     tor_fragile_assert();
00254     return addr;
00255   }
00256 
00257   for (i = 0; i < req->nquestions; ++i) {
00258     const struct evdns_server_question *q = req->questions[i];
00259     if (q->type == type && !strcasecmp(q->name, addr))
00260       return q->name;
00261   }
00262   return addr;
00263 }
00264 
00269 void
00270 dnsserv_resolved(entry_connection_t *conn,
00271                  int answer_type,
00272                  size_t answer_len,
00273                  const char *answer,
00274                  int ttl)
00275 {
00276   struct evdns_server_request *req = conn->dns_server_request;
00277   const char *name;
00278   int err = DNS_ERR_NONE;
00279   if (!req)
00280     return;
00281   name = evdns_get_orig_address(req, answer_type,
00282                                 conn->socks_request->address);
00283 
00284   /* XXXX Re-do; this is dumb. */
00285   if (ttl < 60)
00286     ttl = 60;
00287 
00288   /* The evdns interface is: add a bunch of reply items (corresponding to one
00289    * or more of the questions in the request); then, call
00290    * evdns_server_request_respond. */
00291   if (answer_type == RESOLVED_TYPE_IPV6) {
00292     log_info(LD_APP, "Got an IPv6 answer; that's not implemented.");
00293     err = DNS_ERR_NOTIMPL;
00294   } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 &&
00295              conn->socks_request->command == SOCKS_COMMAND_RESOLVE) {
00296     evdns_server_request_add_a_reply(req,
00297                                      name,
00298                                      1, answer, ttl);
00299   } else if (answer_type == RESOLVED_TYPE_HOSTNAME &&
00300              answer_len < 256 &&
00301              conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) {
00302     char *ans = tor_strndup(answer, answer_len);
00303     evdns_server_request_add_ptr_reply(req, NULL,
00304                                        name,
00305                                        ans, ttl);
00306     tor_free(ans);
00307   } else if (answer_type == RESOLVED_TYPE_ERROR) {
00308     err = DNS_ERR_NOTEXIST;
00309   } else { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */
00310     err = DNS_ERR_SERVERFAILED;
00311   }
00312 
00313   evdns_server_request_respond(req, err);
00314 
00315   conn->dns_server_request = NULL;
00316 }
00317 
00320 void
00321 dnsserv_configure_listener(connection_t *conn)
00322 {
00323   listener_connection_t *listener_conn;
00324   tor_assert(conn);
00325   tor_assert(SOCKET_OK(conn->s));
00326   tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
00327 
00328   listener_conn = TO_LISTENER_CONN(conn);
00329   listener_conn->dns_server_port =
00330     tor_evdns_add_server_port(conn->s, 0, evdns_server_callback,
00331                               listener_conn);
00332 }
00333 
00336 void
00337 dnsserv_close_listener(connection_t *conn)
00338 {
00339   listener_connection_t *listener_conn;
00340   tor_assert(conn);
00341   tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
00342 
00343   listener_conn = TO_LISTENER_CONN(conn);
00344 
00345   if (listener_conn->dns_server_port) {
00346     evdns_close_server_port(listener_conn->dns_server_port);
00347     listener_conn->dns_server_port = NULL;
00348   }
00349 }
00350