unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
server_ban.c (8422B)
1 /* server_ban.* RPC calls 2 * (C) Copyright 2022-.. Bram Matthys (Syzop) and the UnrealIRCd team 3 * License: GPLv2 or later 4 */ 5 6 #include "unrealircd.h" 7 8 ModuleHeader MOD_HEADER 9 = { 10 "rpc/server_ban", 11 "1.0.3", 12 "server_ban.* RPC calls", 13 "UnrealIRCd Team", 14 "unrealircd-6", 15 }; 16 17 /* Forward declarations */ 18 RPC_CALL_FUNC(rpc_server_ban_list); 19 RPC_CALL_FUNC(rpc_server_ban_get); 20 RPC_CALL_FUNC(rpc_server_ban_del); 21 RPC_CALL_FUNC(rpc_server_ban_add); 22 23 MOD_INIT() 24 { 25 RPCHandlerInfo r; 26 27 MARK_AS_OFFICIAL_MODULE(modinfo); 28 29 memset(&r, 0, sizeof(r)); 30 r.method = "server_ban.list"; 31 r.loglevel = ULOG_DEBUG; 32 r.call = rpc_server_ban_list; 33 if (!RPCHandlerAdd(modinfo->handle, &r)) 34 { 35 config_error("[rpc/server_ban] Could not register RPC handler"); 36 return MOD_FAILED; 37 } 38 r.method = "server_ban.get"; 39 r.loglevel = ULOG_DEBUG; 40 r.call = rpc_server_ban_get; 41 if (!RPCHandlerAdd(modinfo->handle, &r)) 42 { 43 config_error("[rpc/server_ban] Could not register RPC handler"); 44 return MOD_FAILED; 45 } 46 r.method = "server_ban.del"; 47 r.call = rpc_server_ban_del; 48 if (!RPCHandlerAdd(modinfo->handle, &r)) 49 { 50 config_error("[rpc/server_ban] Could not register RPC handler"); 51 return MOD_FAILED; 52 } 53 r.method = "server_ban.add"; 54 r.call = rpc_server_ban_add; 55 if (!RPCHandlerAdd(modinfo->handle, &r)) 56 { 57 config_error("[rpc/server_ban] Could not register RPC handler"); 58 return MOD_FAILED; 59 } 60 61 return MOD_SUCCESS; 62 } 63 64 MOD_LOAD() 65 { 66 return MOD_SUCCESS; 67 } 68 69 MOD_UNLOAD() 70 { 71 return MOD_SUCCESS; 72 } 73 74 RPC_CALL_FUNC(rpc_server_ban_list) 75 { 76 json_t *result, *list, *item; 77 int index, index2; 78 TKL *tkl; 79 80 result = json_object(); 81 list = json_array(); 82 json_object_set_new(result, "list", list); 83 84 for (index = 0; index < TKLIPHASHLEN1; index++) 85 { 86 for (index2 = 0; index2 < TKLIPHASHLEN2; index2++) 87 { 88 for (tkl = tklines_ip_hash[index][index2]; tkl; tkl = tkl->next) 89 { 90 if (TKLIsServerBan(tkl)) 91 { 92 item = json_object(); 93 json_expand_tkl(item, NULL, tkl, 1); 94 json_array_append_new(list, item); 95 } 96 } 97 } 98 } 99 for (index = 0; index < TKLISTLEN; index++) 100 { 101 for (tkl = tklines[index]; tkl; tkl = tkl->next) 102 { 103 if (TKLIsServerBan(tkl)) 104 { 105 item = json_object(); 106 json_expand_tkl(item, NULL, tkl, 1); 107 json_array_append_new(list, item); 108 } 109 } 110 } 111 112 rpc_response(client, request, result); 113 json_decref(result); 114 } 115 116 /** Shared code for selecting a server ban, for .add/.del/.get */ 117 int server_ban_select_criteria(Client *client, json_t *request, json_t *params, 118 const char **name, 119 const char **type_name, 120 char *tkl_type_char, 121 int *tkl_type_int, 122 char **usermask, 123 char **hostmask, 124 int *soft) 125 { 126 const char *error; 127 128 *name = json_object_get_string(params, "name"); 129 if (!*name) 130 { 131 rpc_error(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: 'name'"); 132 return 0; 133 } 134 135 *type_name = json_object_get_string(params, "type"); 136 if (!*type_name) 137 { 138 rpc_error(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Missing parameter: 'type'"); 139 return 0; 140 } 141 142 *tkl_type_char = tkl_configtypetochar(*type_name); 143 if (!*tkl_type_char) 144 { 145 rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Invalid type: '%s'", *type_name); 146 return 0; 147 } 148 *tkl_type_int = tkl_chartotype(*tkl_type_char); 149 if (!TKLIsServerBanType(*tkl_type_int)) 150 { 151 rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Invalid type: '%s' (type exists but is not valid for in server_ban.*)", *type_name); 152 return 0; 153 } 154 155 if (!server_ban_parse_mask(client, 0, *tkl_type_char, *name, usermask, hostmask, soft, &error)) 156 { 157 rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Error: %s", error); 158 return 0; 159 } 160 161 /* Hm, shouldn't this be done by server_ban_parse_mask() ? */ 162 if (*soft && (*usermask[0] == '%')) 163 *usermask = *usermask + 1; 164 165 return 1; 166 } 167 168 RPC_CALL_FUNC(rpc_server_ban_get) 169 { 170 json_t *result, *list, *item; 171 const char *name, *type_name; 172 char *usermask, *hostmask; 173 int soft; 174 TKL *tkl; 175 char tkl_type_char; 176 int tkl_type_int; 177 178 if (!server_ban_select_criteria(client, request, params, 179 &name, &type_name, 180 &tkl_type_char, &tkl_type_int, 181 &usermask, &hostmask, &soft)) 182 { 183 return; 184 } 185 186 if (!(tkl = find_tkl_serverban(tkl_type_int, usermask, hostmask, soft))) 187 { 188 rpc_error(client, request, JSON_RPC_ERROR_NOT_FOUND, "Ban not found"); 189 return; 190 } 191 192 result = json_object(); 193 json_expand_tkl(result, "tkl", tkl, 1); 194 rpc_response(client, request, result); 195 json_decref(result); 196 } 197 198 RPC_CALL_FUNC(rpc_server_ban_del) 199 { 200 json_t *result, *list, *item; 201 const char *name, *type_name; 202 const char *set_by; 203 char *usermask, *hostmask; 204 char usermask_mess[256]; 205 int soft; 206 TKL *tkl; 207 char tkl_type_char; 208 int tkl_type_int; 209 const char *tkllayer[10]; 210 char tkl_type_str[2]; 211 212 if (!server_ban_select_criteria(client, request, params, 213 &name, &type_name, 214 &tkl_type_char, &tkl_type_int, 215 &usermask, &hostmask, &soft)) 216 { 217 return; 218 } 219 220 tkl_type_str[0] = tkl_type_char; 221 tkl_type_str[1] = '\0'; 222 223 if (!(tkl = find_tkl_serverban(tkl_type_int, usermask, hostmask, soft))) 224 { 225 rpc_error(client, request, JSON_RPC_ERROR_NOT_FOUND, "Ban not found"); 226 return; 227 } 228 229 OPTIONAL_PARAM_STRING("set_by", set_by); 230 if (!set_by) 231 set_by = client->name; 232 233 result = json_object(); 234 json_expand_tkl(result, "tkl", tkl, 1); 235 236 tkllayer[1] = "-"; 237 tkllayer[2] = tkl_type_str; 238 if (soft) 239 { 240 /* I don't like this fiddling. 241 * It will be gone when we move from cmd_tkl() to a real function though. 242 */ 243 snprintf(usermask_mess, sizeof(usermask_mess), "%%%s", usermask); 244 tkllayer[3] = usermask_mess; 245 } else { 246 tkllayer[3] = usermask; 247 } 248 tkllayer[4] = hostmask; 249 tkllayer[5] = set_by; 250 tkllayer[6] = NULL; 251 cmd_tkl(&me, NULL, 6, tkllayer); 252 253 if (!find_tkl_serverban(tkl_type_int, usermask, hostmask, soft)) 254 { 255 rpc_response(client, request, result); 256 } else { 257 /* Actually this may not be an internal error, it could be an 258 * incorrect request, such as asking to remove a config-based ban. 259 */ 260 rpc_error(client, request, JSON_RPC_ERROR_INTERNAL_ERROR, "Unable to remove item"); 261 } 262 json_decref(result); 263 } 264 265 RPC_CALL_FUNC(rpc_server_ban_add) 266 { 267 json_t *result, *list, *item; 268 const char *name, *type_name; 269 const char *set_by; 270 char *usermask, *hostmask; 271 int soft; 272 TKL *tkl; 273 char tkl_type_char; 274 int tkl_type_int; 275 char tkl_type_str[2]; 276 const char *reason; 277 const char *str; 278 time_t tkl_expire_at; 279 time_t tkl_set_at = TStime(); 280 281 if (!server_ban_select_criteria(client, request, params, 282 &name, &type_name, 283 &tkl_type_char, &tkl_type_int, 284 &usermask, &hostmask, &soft)) 285 { 286 return; 287 } 288 289 tkl_type_str[0] = tkl_type_char; 290 tkl_type_str[1] = '\0'; 291 292 REQUIRE_PARAM_STRING("reason", reason); 293 294 /* Duration / expiry time */ 295 if ((str = json_object_get_string(params, "duration_string"))) 296 { 297 tkl_expire_at = config_checkval(str, CFG_TIME); 298 if (tkl_expire_at > 0) 299 tkl_expire_at = TStime() + tkl_expire_at; 300 } else 301 if ((str = json_object_get_string(params, "expire_at"))) 302 { 303 tkl_expire_at = server_time_to_unix_time(str); 304 } else 305 { 306 /* Never expire */ 307 tkl_expire_at = 0; 308 } 309 310 OPTIONAL_PARAM_STRING("set_by", set_by); 311 if (!set_by) 312 set_by = client->name; 313 314 if ((tkl_expire_at != 0) && (tkl_expire_at < TStime())) 315 { 316 rpc_error_fmt(client, request, JSON_RPC_ERROR_INVALID_PARAMS, "Error: the specified expiry time is before current time (before now)"); 317 return; 318 } 319 320 if (find_tkl_serverban(tkl_type_int, usermask, hostmask, soft)) 321 { 322 rpc_error(client, request, JSON_RPC_ERROR_ALREADY_EXISTS, "A ban with that mask already exists"); 323 return; 324 } 325 326 tkl = tkl_add_serverban(tkl_type_int, usermask, hostmask, reason, 327 set_by, tkl_expire_at, tkl_set_at, 328 soft, 0); 329 330 if (!tkl) 331 { 332 rpc_error(client, request, JSON_RPC_ERROR_INTERNAL_ERROR, "Unable to add item"); 333 return; 334 } 335 336 tkl_added(client, tkl); 337 338 result = json_object(); 339 json_expand_tkl(result, "tkl", tkl, 1); 340 rpc_response(client, request, result); 341 json_decref(result); 342 }