Line data Source code
1 : /* ------------------------------------------------------------------------- 2 : * 3 : * auth_delay.c 4 : * 5 : * Copyright (c) 2010-2025, PostgreSQL Global Development Group 6 : * 7 : * IDENTIFICATION 8 : * contrib/auth_delay/auth_delay.c 9 : * 10 : * ------------------------------------------------------------------------- 11 : */ 12 : #include "postgres.h" 13 : 14 : #include <limits.h> 15 : 16 : #include "libpq/auth.h" 17 : #include "utils/guc.h" 18 : 19 0 : PG_MODULE_MAGIC_EXT( 20 : .name = "auth_delay", 21 : .version = PG_VERSION 22 : ); 23 : 24 : /* GUC Variables */ 25 : static int auth_delay_milliseconds = 0; 26 : 27 : /* Original Hook */ 28 : static ClientAuthentication_hook_type original_client_auth_hook = NULL; 29 : 30 : /* 31 : * Check authentication 32 : */ 33 : static void 34 0 : auth_delay_checks(Port *port, int status) 35 : { 36 : /* 37 : * Any other plugins which use ClientAuthentication_hook. 38 : */ 39 0 : if (original_client_auth_hook) 40 0 : original_client_auth_hook(port, status); 41 : 42 : /* 43 : * Inject a short delay if authentication failed. 44 : */ 45 0 : if (status != STATUS_OK) 46 : { 47 0 : pg_usleep(1000L * auth_delay_milliseconds); 48 : } 49 0 : } 50 : 51 : /* 52 : * Module Load Callback 53 : */ 54 : void 55 0 : _PG_init(void) 56 : { 57 : /* Define custom GUC variables */ 58 0 : DefineCustomIntVariable("auth_delay.milliseconds", 59 : "Milliseconds to delay before reporting authentication failure", 60 : NULL, 61 : &auth_delay_milliseconds, 62 : 0, 63 : 0, INT_MAX / 1000, 64 : PGC_SIGHUP, 65 : GUC_UNIT_MS, 66 : NULL, 67 : NULL, 68 : NULL); 69 : 70 0 : MarkGUCPrefixReserved("auth_delay"); 71 : 72 : /* Install Hooks */ 73 0 : original_client_auth_hook = ClientAuthentication_hook; 74 0 : ClientAuthentication_hook = auth_delay_checks; 75 0 : }