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; 20 : 21 : /* GUC Variables */ 22 : static int auth_delay_milliseconds = 0; 23 : 24 : /* Original Hook */ 25 : static ClientAuthentication_hook_type original_client_auth_hook = NULL; 26 : 27 : /* 28 : * Check authentication 29 : */ 30 : static void 31 0 : auth_delay_checks(Port *port, int status) 32 : { 33 : /* 34 : * Any other plugins which use ClientAuthentication_hook. 35 : */ 36 0 : if (original_client_auth_hook) 37 0 : original_client_auth_hook(port, status); 38 : 39 : /* 40 : * Inject a short delay if authentication failed. 41 : */ 42 0 : if (status != STATUS_OK) 43 : { 44 0 : pg_usleep(1000L * auth_delay_milliseconds); 45 : } 46 0 : } 47 : 48 : /* 49 : * Module Load Callback 50 : */ 51 : void 52 0 : _PG_init(void) 53 : { 54 : /* Define custom GUC variables */ 55 0 : DefineCustomIntVariable("auth_delay.milliseconds", 56 : "Milliseconds to delay before reporting authentication failure", 57 : NULL, 58 : &auth_delay_milliseconds, 59 : 0, 60 : 0, INT_MAX / 1000, 61 : PGC_SIGHUP, 62 : GUC_UNIT_MS, 63 : NULL, 64 : NULL, 65 : NULL); 66 : 67 0 : MarkGUCPrefixReserved("auth_delay"); 68 : 69 : /* Install Hooks */ 70 0 : original_client_auth_hook = ClientAuthentication_hook; 71 0 : ClientAuthentication_hook = auth_delay_checks; 72 0 : }