unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

webredir.c (4685B)

      1 /*
      2  * webredir UnrealIRCd module
      3  * (C) Copyright 2019 i <info@servx.org> and the UnrealIRCd team
      4  *
      5  * This module will 301-redirect any clients issuing GET's/POST's during pre-connect stage.
      6  *
      7  * This program is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 1, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this program; if not, write to the Free Software
     19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     20  */
     21 
     22 #include "unrealircd.h"
     23 
     24 CMD_FUNC(webredir);
     25 
     26 ModuleHeader MOD_HEADER
     27   = {
     28 	"webredir",
     29 	"1.0",
     30 	"Do 301 redirect for HEAD/GET/POST/PUT commands", 
     31 	"UnrealIRCd Team",
     32 	"unrealircd-6",
     33     };
     34 
     35 struct {
     36 	char *url;
     37 } cfg;
     38 
     39 static int nowebredir = 1;
     40 
     41 static void free_config(void);
     42 static void init_config(void);
     43 int webredir_config_posttest(int *errs);
     44 int webredir_config_test(ConfigFile *, ConfigEntry *, int, int *);
     45 int webredir_config_run(ConfigFile *, ConfigEntry *, int);
     46 
     47 MOD_TEST()
     48 {
     49 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, webredir_config_test);
     50 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, webredir_config_posttest);
     51 	return MOD_SUCCESS;
     52 }
     53 
     54 MOD_INIT()
     55 {
     56 	MARK_AS_OFFICIAL_MODULE(modinfo);
     57 	init_config();
     58 	CommandAdd(modinfo->handle, "HEAD", webredir, MAXPARA, CMD_UNREGISTERED);
     59 	CommandAdd(modinfo->handle, "GET", webredir, MAXPARA, CMD_UNREGISTERED);
     60 	CommandAdd(modinfo->handle, "POST", webredir, MAXPARA, CMD_UNREGISTERED);
     61 	CommandAdd(modinfo->handle, "PUT", webredir, MAXPARA, CMD_UNREGISTERED);
     62 	HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, webredir_config_run);
     63 	return MOD_SUCCESS;
     64 }
     65 
     66 MOD_LOAD()
     67 {
     68 	if (SHOWCONNECTINFO)
     69 	{
     70 		config_warn("I'm disabling set::options::show-connect-info for you "
     71 			    "as this setting is incompatible with the webredir module.");
     72 		SHOWCONNECTINFO = 0;
     73 	}
     74 	return MOD_SUCCESS;
     75 }
     76 
     77 MOD_UNLOAD()
     78 {
     79 	free_config();
     80 	return MOD_SUCCESS;
     81 }
     82 
     83 static void init_config(void)
     84 {
     85 	memset(&cfg, 0, sizeof(cfg));
     86 }
     87 
     88 static void free_config(void)
     89 {
     90 	safe_free(cfg.url);
     91 
     92 	memset(&cfg, 0, sizeof(cfg)); /* needed! */
     93 }
     94 
     95 int webredir_config_posttest(int *errs)
     96 {
     97 	int errors = 0;
     98 
     99 	if (nowebredir)
    100 	{
    101 		config_error("set::webredir is missing!");
    102 		errors++;
    103 	}
    104 
    105 	*errs = errors;
    106 	return errors ? -1 : 1;
    107 }
    108 
    109 int webredir_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
    110 {
    111 	int errors = 0;
    112 	int has_url = 0;
    113 	ConfigEntry *cep;
    114 
    115 	if (type != CONFIG_SET)
    116 		return 0;
    117 
    118 	/* We are only interrested in set::webredir... */
    119 	if (!ce || !ce->name || strcmp(ce->name, "webredir"))
    120 		return 0;
    121 
    122 	nowebredir = 0;
    123 	for (cep = ce->items; cep; cep = cep->next)
    124 	{
    125 		if (!cep->value)
    126 		{
    127 			config_error("%s:%i: set::webredir::%s with no value",
    128 				cep->file->filename, cep->line_number, cep->name);
    129 			errors++;
    130 		}
    131 		else if (!strcmp(cep->name, "url"))
    132 		{
    133 			if (!*cep->value || strchr(cep->value, ' '))
    134 			{
    135 				config_error("%s:%i: set::webredir::%s with empty value",
    136 					cep->file->filename, cep->line_number, cep->name);
    137 				errors++;
    138 			}
    139 			if (!strstr(cep->value, "://") || !strcmp(cep->value, "https://..."))
    140 			{
    141 				config_error("%s:%i: set::webredir::url needs to be a valid URL",
    142 					cep->file->filename, cep->line_number);
    143 				errors++;
    144 			}
    145 			if (has_url)
    146 			{
    147 				config_warn_duplicate(cep->file->filename,
    148 					cep->line_number, "set::webredir::url");
    149 				continue;
    150 			}
    151 			has_url = 1;
    152 		}
    153 		else
    154 		{
    155 			config_error("%s:%i: unknown directive set::webredir::%s",
    156 				cep->file->filename, cep->line_number, cep->name);
    157 			errors++;
    158 		}
    159 	}
    160 
    161 	if (!has_url)
    162 	{
    163 		config_error_missing(ce->file->filename, ce->line_number,
    164 			"set::webredir::url");
    165 		errors++;
    166 	}
    167 
    168 	*errs = errors;
    169 	return errors ? -1 : 1;
    170 }
    171 
    172 int webredir_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
    173 {
    174 	ConfigEntry *cep;
    175 
    176 	if (type != CONFIG_SET)
    177 		return 0;
    178 	
    179 	/* We are only interrested in set::webredir... */
    180 	if (!ce || !ce->name || strcmp(ce->name, "webredir"))
    181 		return 0;
    182 	
    183 	for (cep = ce->items; cep; cep = cep->next)
    184 	{
    185 		if (!strcmp(cep->name, "url"))
    186 		{
    187 			safe_strdup(cfg.url, cep->value);
    188 		}
    189 	}
    190 	return 1;
    191 }
    192 
    193 CMD_FUNC(webredir)
    194 {
    195 	if (!MyConnect(client))
    196 		return;
    197 
    198 	sendto_one(client, NULL, "HTTP/1.1 301 Moved Permanently");
    199 	sendto_one(client, NULL, "Location: %s\r\n\r\n", cfg.url);
    200 	dead_socket(client, "Connection closed");
    201 }