unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
jumpserver.c (7153B)
1 /* 2 * JumpServer: This module can redirect clients to another server. 3 * (C) Copyright 2004-2016 Bram Matthys (Syzop). 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 1, or (at your option) 8 * any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20 #include "unrealircd.h" 21 22 ModuleHeader MOD_HEADER 23 = { 24 "jumpserver", 25 "1.1", 26 "/jumpserver command", 27 "UnrealIRCd Team", 28 "unrealircd-6", 29 }; 30 31 /* Forward declarations */ 32 CMD_FUNC(cmd_jumpserver); 33 int jumpserver_preconnect(Client *); 34 void jumpserver_free_jss(ModData *m); 35 36 /* Jumpserver status struct */ 37 typedef struct JSS JSS; 38 struct JSS 39 { 40 char *reason; 41 char *server; 42 int port; 43 char *tls_server; 44 int tls_port; 45 }; 46 47 JSS *jss=NULL; /**< JumpServer Status. NULL=disabled. */ 48 49 MOD_INIT() 50 { 51 MARK_AS_OFFICIAL_MODULE(modinfo); 52 LoadPersistentPointer(modinfo, jss, jumpserver_free_jss); 53 CommandAdd(modinfo->handle, "JUMPSERVER", cmd_jumpserver, 3, CMD_USER); 54 HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0, jumpserver_preconnect); 55 return MOD_SUCCESS; 56 } 57 58 MOD_LOAD() 59 { 60 return MOD_SUCCESS; 61 } 62 63 MOD_UNLOAD() 64 { 65 SavePersistentPointer(modinfo, jss); 66 return MOD_SUCCESS; 67 } 68 69 static void do_jumpserver_exit_client(Client *client) 70 { 71 if (IsSecure(client) && jss->tls_server) 72 sendnumeric(client, RPL_REDIR, jss->tls_server, jss->tls_port); 73 else 74 sendnumeric(client, RPL_REDIR, jss->server, jss->port); 75 exit_client(client, NULL, jss->reason); 76 } 77 78 static void redirect_all_clients(void) 79 { 80 int count = 0; 81 Client *client, *next; 82 83 list_for_each_entry_safe(client, next, &lclient_list, lclient_node) 84 { 85 if (IsUser(client) && !IsOper(client)) 86 { 87 do_jumpserver_exit_client(client); 88 count++; 89 } 90 } 91 unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_REPORT", NULL, 92 "[jumpserver] Redirected $num_clients client(s)", 93 log_data_integer("num_clients", count)); 94 } 95 96 int jumpserver_preconnect(Client *client) 97 { 98 if (jss) 99 { 100 do_jumpserver_exit_client(client); 101 return HOOK_DENY; 102 } 103 return HOOK_CONTINUE; 104 } 105 106 void free_jss(void) 107 { 108 if (jss) 109 { 110 safe_free(jss->server); 111 safe_free(jss->reason); 112 safe_free(jss->tls_server); 113 safe_free(jss); 114 jss = NULL; 115 } 116 } 117 118 void jumpserver_free_jss(ModData *m) 119 { 120 free_jss(); 121 } 122 123 CMD_FUNC(cmd_jumpserver) 124 { 125 char *serv, *tlsserv=NULL, *p; 126 const char *reason; 127 int all=0, port=6667, sslport=6697; 128 char request[BUFSIZE]; 129 char logbuf[512]; 130 131 if (!IsOper(client)) 132 { 133 sendnumeric(client, ERR_NOPRIVILEGES); 134 return; 135 } 136 137 if ((parc < 2) || BadPtr(parv[1])) 138 { 139 if (jss && jss->tls_server) 140 sendnotice(client, "JumpServer is \002ENABLED\002 to %s:%d (TLS: %s:%d) with reason '%s'", 141 jss->server, jss->port, jss->tls_server, jss->tls_port, jss->reason); 142 else 143 if (jss) 144 sendnotice(client, "JumpServer is \002ENABLED\002 to %s:%d with reason '%s'", 145 jss->server, jss->port, jss->reason); 146 else 147 sendnotice(client, "JumpServer is \002DISABLED\002"); 148 return; 149 } 150 151 if ((parc > 1) && (!strcasecmp(parv[1], "OFF") || !strcasecmp(parv[1], "STOP"))) 152 { 153 if (!jss) 154 { 155 sendnotice(client, "JUMPSERVER: No redirect active (already OFF)"); 156 return; 157 } 158 free_jss(); 159 unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_DISABLED", client, 160 "[jumpserver] $client.details turned jumpserver OFF"); 161 return; 162 } 163 164 if (parc < 4) 165 { 166 /* Waah, pretty verbose usage info ;) */ 167 sendnotice(client, "Use: /JUMPSERVER <server>[:port] <NEW|ALL> <reason>"); 168 sendnotice(client, " Or: /JUMPSERVER <server>[:port]/<tlsserver>[:port] <NEW|ALL> <reason>"); 169 sendnotice(client, "if 'NEW' is chosen then only new (incoming) connections will be redirected"); 170 sendnotice(client, "if 'ALL' is chosen then all clients except opers will be redirected immediately (+incoming connections)"); 171 sendnotice(client, "Example: /JUMPSERVER irc2.test.net NEW This server will be upgraded, please use irc2.test.net for now"); 172 sendnotice(client, "And then for example 10 minutes later..."); 173 sendnotice(client, " /JUMPSERVER irc2.test.net ALL This server will be upgraded, please use irc2.test.net for now"); 174 sendnotice(client, "Use: '/JUMPSERVER OFF' to turn off any redirects"); 175 return; 176 } 177 178 /* Parsing code follows... */ 179 180 strlcpy(request, parv[1], sizeof(request)); 181 serv = request; 182 183 p = strchr(serv, '/'); 184 if (p) 185 { 186 *p = '\0'; 187 tlsserv = p+1; 188 } 189 190 p = strchr(serv, ':'); 191 if (p) 192 { 193 *p++ = '\0'; 194 port = atoi(p); 195 if ((port < 1) || (port > 65535)) 196 { 197 sendnotice(client, "Invalid serverport specified (%d)", port); 198 return; 199 } 200 } 201 if (tlsserv) 202 { 203 p = strchr(tlsserv, ':'); 204 if (p) 205 { 206 *p++ = '\0'; 207 sslport = atoi(p); 208 if ((sslport < 1) || (sslport > 65535)) 209 { 210 sendnotice(client, "Invalid TLS serverport specified (%d)", sslport); 211 return; 212 } 213 } 214 if (!*tlsserv) 215 tlsserv = NULL; 216 } 217 if (!strcasecmp(parv[2], "new")) 218 all = 0; 219 else if (!strcasecmp(parv[2], "all")) 220 all = 1; 221 else { 222 sendnotice(client, "ERROR: Invalid action '%s', should be 'NEW' or 'ALL' (see /jumpserver help for usage)", parv[2]); 223 return; 224 } 225 226 reason = parv[3]; 227 228 /* Free any old stuff (needed!) */ 229 if (jss) 230 free_jss(); 231 232 jss = safe_alloc(sizeof(JSS)); 233 234 /* Set it */ 235 safe_strdup(jss->server, serv); 236 jss->port = port; 237 if (tlsserv) 238 { 239 safe_strdup(jss->tls_server, tlsserv); 240 jss->tls_port = sslport; 241 } 242 safe_strdup(jss->reason, reason); 243 244 /* Broadcast/log */ 245 if (tlsserv) 246 { 247 unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_ENABLED", client, 248 "[jumpserver] $client.details turned jumpserver ON for $jumpserver_who " 249 "to $jumpserver_server:$jumpserver_port " 250 "[TLS: $jumpserver_tls_server:$jumpserver_tls_port] " 251 "($reason)", 252 log_data_string("jumpserver_who", all ? "ALL CLIENTS" : "all new clients"), 253 log_data_string("jumpserver_server", jss->server), 254 log_data_integer("jumpserver_port", jss->port), 255 log_data_string("jumpserver_tls_server", jss->tls_server), 256 log_data_integer("jumpserver_tls_port", jss->tls_port), 257 log_data_string("reason", jss->reason)); 258 } else { 259 unreal_log(ULOG_INFO, "jumpserver", "JUMPSERVER_ENABLED", client, 260 "[jumpserver] $client.details turned jumpserver ON for $jumpserver_who " 261 "to $jumpserver_server:$jumpserver_port " 262 "($reason)", 263 log_data_string("jumpserver_who", all ? "ALL CLIENTS" : "all new clients"), 264 log_data_string("jumpserver_server", jss->server), 265 log_data_integer("jumpserver_port", jss->port), 266 log_data_string("reason", jss->reason)); 267 } 268 269 if (all) 270 redirect_all_clients(); 271 }