Bladeren bron

Merge branch 'leaf-protect-telnet'

* leaf-protect-telnet:
  * Add note that this branch fixes #19
  * Disable user-host match requirement for now
  * Suggest hostname to add with .newleaf
  * Telnet/DCC now checks both forward/reverse to ensure they match.
  * Protect bot linking with hostname matching

Conflicts:
	src/dcc.c
Bryan Drewery 16 jaren geleden
bovenliggende
commit
ba4760d5b4
2 gewijzigde bestanden met toevoegingen van 93 en 16 verwijderingen
  1. 2 0
      doc/UPDATES
  2. 91 16
      src/dcc.c

+ 2 - 0
doc/UPDATES

@@ -60,6 +60,8 @@
   * Fix cmd_slowjoin not working on backup bots correctly.
   * Fix cmd_slowjoin not working on backup bots correctly.
   * Fix a crash from long hubnicks.
   * Fix a crash from long hubnicks.
 * Misc changes
 * Misc changes
+  * Bots must have a matching host to be able to link now.
+  * Telnet/DCC now checks both forward/reverse to ensure they match. (fixes #19)
   * Added pseudo-channel 'default' which can be modified with 'chanset' and 'chaninfo'.
   * Added pseudo-channel 'default' which can be modified with 'chanset' and 'chaninfo'.
     This is used to modify what the default channel options will be for new channels.
     This is used to modify what the default channel options will be for new channels.
   * Removed 'set chanset' as it has been replaced by 'chanset default'
   * Removed 'set chanset' as it has been replaced by 'chanset default'

+ 91 - 16
src/dcc.c

@@ -1363,6 +1363,7 @@ detect_telnet_flood(char *floodhost)
 }
 }
 
 
 static void dcc_telnet_dns_callback(int, void *, const char *, bd::Array<bd::String>);
 static void dcc_telnet_dns_callback(int, void *, const char *, bd::Array<bd::String>);
+static void dcc_telnet_dns_forward_callback(int, void *, const char *, bd::Array<bd::String>);
 
 
 static void
 static void
 dcc_telnet(int idx, char *buf, int ii)
 dcc_telnet(int idx, char *buf, int ii)
@@ -1409,6 +1410,7 @@ dcc_telnet(int idx, char *buf, int ii)
 
 
   putlog(LOG_DEBUG, "*", "Telnet connection: %s/%d", s, port);
   putlog(LOG_DEBUG, "*", "Telnet connection: %s/%d", s, port);
 
 
+  // Are they ignored by IP?
   simple_snprintf(x, sizeof(x), "-telnet!telnet@%s", iptostr(htonl(ip)));
   simple_snprintf(x, sizeof(x), "-telnet!telnet@%s", iptostr(htonl(ip)));
 
 
   if (match_ignore(x) || detect_telnet_flood(x)) {
   if (match_ignore(x) || detect_telnet_flood(x)) {
@@ -1449,6 +1451,41 @@ static void dcc_telnet_dns_callback(int id, void *client_data, const char *ip, b
   long data = (long) client_data;
   long data = (long) client_data;
   int i = (int) data;
   int i = (int) data;
 
 
+  if (!valid_dns_id(i, id))
+    return;
+
+  int idx = dcc[i].u.dns->ibuf;
+
+  if (!valid_idx(idx)) {
+    putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s", dcc[i].host);
+    killsock(dcc[i].sock);
+    lostdcc(i);
+    return;
+  }
+
+  //Reset timer
+  dcc[i].timeval = now;
+
+  //Clear the ip (still saved in dcc[i].addr)
+  dcc[i].host[0] = 0;
+  if (hosts.size()) {
+    strlcpy(dcc[i].host, bd::String(hosts[0]).c_str(), UHOSTLEN);
+
+    //Check forward
+    int dns_id = egg_dns_lookup(bd::String(hosts[0]).c_str(), 20, dcc_telnet_dns_forward_callback, (void *) (long) i);
+    if (dns_id >= 0)
+      dcc[i].dns_id = dns_id;
+  } else {
+    bd::Array<bd::String> empty;
+    dcc_telnet_dns_forward_callback(id, client_data, ip, empty);
+  }
+}
+
+static void dcc_telnet_dns_forward_callback(int id, void *client_data, const char *host, bd::Array<bd::String> ips) {
+  // 64bit hacks
+  long data = (long) client_data;
+  int i = (int) data;
+
   if (!valid_dns_id(i, id))
   if (!valid_dns_id(i, id))
     return;
     return;
 
 
@@ -1458,22 +1495,30 @@ static void dcc_telnet_dns_callback(int id, void *client_data, const char *ip, b
   if (valid_idx(i))
   if (valid_idx(i))
     idx = dcc[i].u.dns->ibuf;
     idx = dcc[i].u.dns->ibuf;
 
 
-  strlcpy(dcc[i].host, hosts.size() ? bd::String(hosts[0]).c_str() : ip, UHOSTLEN);
-
-  simple_snprintf(s2, sizeof(s2), "-telnet!telnet@%s", dcc[i].host);
-
-  if (match_ignore(s2)) {
-    putlog(LOG_DEBUG, "*", "Ignored telnet connection from: %s", s2);
+  if (!valid_idx(idx)) {
+    putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s", iptostr(htonl(dcc[i].addr)));
     killsock(dcc[i].sock);
     killsock(dcc[i].sock);
     lostdcc(i);
     lostdcc(i);
     return;
     return;
   }
   }
 
 
-  if (!valid_idx(idx)) {
-    putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s", dcc[i].host);
-    killsock(dcc[i].sock);
-    lostdcc(i);
-    return;
+  bool forward_matched = true;
+  // If the forward did not match, replace the saved host with the ip
+  if (!(ips.size() && !strcmp(bd::String(ips[0]).c_str(), iptostr(htonl(dcc[i].addr))))) {
+    forward_matched = false;
+    strlcpy(dcc[i].host, iptostr(htonl(dcc[i].addr)), UHOSTLEN);
+  }
+
+  if (forward_matched) {
+    // Are they ignored by host?
+    simple_snprintf(s2, sizeof(s2), "-telnet!telnet@%s", dcc[i].host);
+
+    if (match_ignore(s2)) {
+      putlog(LOG_DEBUG, "*", "Ignored telnet connection from: %s", s2);
+      killsock(dcc[i].sock);
+      lostdcc(i);
+      return;
+    }
   }
   }
 
 
   if (dcc[idx].host[0] == '@') {
   if (dcc[idx].host[0] == '@') {
@@ -1493,12 +1538,12 @@ static void dcc_telnet_dns_callback(int id, void *client_data, const char *ip, b
   if (!dcc[i].user)
   if (!dcc[i].user)
     dcc[i].user = get_user_by_host(s2);		/* check for matching -telnet!telnet@host */
     dcc[i].user = get_user_by_host(s2);		/* check for matching -telnet!telnet@host */
   
   
-  if (hosts.size())
-    putlog(LOG_MISC, "*", "Telnet connection: %s[%s]/%d", dcc[i].host, ip, dcc[i].port);
+  if (forward_matched)
+    putlog(LOG_MISC, "*", "Telnet connection: %s[%s]/%d", dcc[i].host, iptostr(htonl(dcc[i].addr)), dcc[i].port);
   else
   else
-    putlog(LOG_MISC, "*", "Telnet connection: %s/%d", dcc[i].host, dcc[i].port);
+    putlog(LOG_MISC, "*", "Telnet connection: %s/%d", iptostr(htonl(dcc[i].addr)), dcc[i].port);
 
 
-  sock = open_telnet((char *) ip, 113, 0);
+  sock = open_telnet((char *) iptostr(htonl(dcc[i].addr)), 113, 0);
 
 
   char s[UHOSTLEN] = "";
   char s[UHOSTLEN] = "";
 
 
@@ -1684,7 +1729,7 @@ dcc_telnet_id(int idx, char *buf, int atr)
     if (dcc[idx].user)
     if (dcc[idx].user)
       putlog(LOG_BOTS, "*", "%s: %s!%s", ischanhub() ? "Refused DCC chat (no access)" : "Refused DCC chat (I'm not a chathub (+c))", nick, dcc[idx].host);
       putlog(LOG_BOTS, "*", "%s: %s!%s", ischanhub() ? "Refused DCC chat (no access)" : "Refused DCC chat (I'm not a chathub (+c))", nick, dcc[idx].host);
     else if (dcc[idx].bot)
     else if (dcc[idx].bot)
-      putlog(LOG_BOTS, "*", "Refused %s (invalid bot handle: %s) (Add with '%snewleaf %s')", dcc[idx].host, nick, settings.dcc_prefix, nick);
+      putlog(LOG_BOTS, "*", "Refused %s (invalid bot handle: %s) (Add with '%snewleaf %s -telnet!%s')", dcc[idx].host, nick, settings.dcc_prefix, nick, dcc[idx].host);
     else
     else
       putlog(LOG_BOTS, "*", "Refused %s (invalid handle: %s)", dcc[idx].host, nick);
       putlog(LOG_BOTS, "*", "Refused %s (invalid handle: %s)", dcc[idx].host, nick);
     killsock(dcc[idx].sock);
     killsock(dcc[idx].sock);
@@ -1712,6 +1757,36 @@ dcc_telnet_id(int idx, char *buf, int atr)
   } else {
   } else {
   }
   }
 
 
+  if (dcc[idx].bot) {
+    char shost[UHOSTLEN + 20] = "", sip[UHOSTLEN + 20] = "", user[30] = "";
+    simple_snprintf(shost, sizeof(shost), "-telnet!%s", dcc[idx].host);
+    char *p = strchr(dcc[idx].host, '@');
+    strlcpy(user, dcc[idx].host, p - dcc[idx].host + 1);
+    simple_snprintf(sip, sizeof(sip), "-telnet!%s@%s", user, iptostr(htonl(dcc[idx].addr)));
+
+    struct userrec *u = NULL;
+    ok = 1;
+
+    if (!u)
+      u = get_user_by_host(sip);			/* Check for -telnet!ident@ip */
+    if (!u)
+      u = get_user_by_host(shost);		/* Check for -telnet!ident@host */
+    if (!u)
+      ok = 0;
+
+//    // Restrict connect to matching the user who they claim to be
+//    if (u && strcasecmp(nick, u->handle))
+//      ok = 0;
+
+    if (!ok) {
+      putlog(LOG_BOTS, "*", "Denied link to '%s': Host not recognized: %s", nick, dcc[idx].host);
+      putlog(LOG_BOTS, "*", "If this host/bot is trusted: %s+host %s %s", settings.dcc_prefix, nick, shost);
+      killsock(dcc[idx].sock);
+      lostdcc(idx);
+      return;
+    }
+  }
+
   dcc_telnet_pass(idx, atr);
   dcc_telnet_pass(idx, atr);
 }
 }