do_solve_challenge.sql (4406B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2024 Taler Systems SA 4 -- 5 -- TALER is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 -- 16 17 DROP FUNCTION IF EXISTS challenger_do_validate_and_solve_pin; 18 CREATE FUNCTION challenger_do_validate_and_solve_pin ( 19 IN in_nonce BYTEA, 20 IN in_new_pin INT4, 21 IN in_now INT8, 22 OUT out_not_found BOOLEAN, 23 OUT out_exhausted BOOLEAN, -- set to TRUE if attempts were already exhausted 24 -- TRUE if the validation failed permanently: no address change, TAN 25 -- transmission or TAN attempt is left, now or from an earlier call. 26 OUT out_failed BOOLEAN, 27 OUT out_no_challenge BOOLEAN, 28 OUT out_solved BOOLEAN, 29 OUT out_state TEXT, 30 OUT out_address_attempts_left INT4, 31 OUT out_auth_attempts_left INT4, 32 OUT out_pin_transmissions_left INT4, 33 OUT out_client_redirect_uri TEXT) 34 LANGUAGE plpgsql 35 AS $$ 36 DECLARE 37 my_status RECORD; 38 my_fixed_address BOOLEAN; 39 BEGIN 40 41 SELECT auth_attempts_left 42 ,address_attempts_left 43 ,address 44 ,failed 45 ,pin_transmissions_left 46 ,last_pin 47 ,client_redirect_uri 48 ,client_state 49 INTO my_status 50 FROM validations 51 WHERE nonce=in_nonce 52 AND expiration_time > in_now 53 FOR UPDATE; 54 55 IF NOT FOUND 56 THEN 57 out_not_found=TRUE; 58 out_no_challenge=TRUE; 59 out_exhausted=FALSE; 60 out_failed=FALSE; 61 out_solved=FALSE; 62 out_address_attempts_left=0; 63 out_auth_attempts_left=0; 64 out_pin_transmissions_left=0; 65 out_client_redirect_uri=NULL; 66 out_state=NULL; 67 RETURN; 68 END IF; 69 out_not_found=FALSE; 70 out_address_attempts_left=my_status.address_attempts_left; 71 out_pin_transmissions_left=my_status.pin_transmissions_left; 72 out_client_redirect_uri=my_status.client_redirect_uri; 73 out_state=my_status.client_state; 74 out_failed=FALSE; 75 76 -- The user cannot move to another address if they used up their address 77 -- changes or if the client marked the address as read-only. 78 my_fixed_address = ( (0 = my_status.address_attempts_left) OR 79 COALESCE (my_status.address::JSONB->'read_only' 80 = 'true'::JSONB, FALSE) ); 81 82 -- Checked before 'last_pin', as a validation where every transmission 83 -- failed has no TAN but has failed nevertheless. A validation can end up 84 -- out of options without a /solve, e.g. if the helper failed on the last 85 -- transmission after the guesses on the previous TAN were spent; hence 86 -- the counters are checked here, too, and not just the flag. 87 IF ( my_status.failed OR 88 ( (0 = my_status.auth_attempts_left) AND 89 (0 = my_status.pin_transmissions_left) AND 90 my_fixed_address ) ) 91 THEN 92 IF NOT my_status.failed 93 THEN 94 UPDATE validations 95 SET failed=TRUE 96 WHERE nonce=in_nonce; 97 END IF; 98 out_failed=TRUE; 99 out_solved=FALSE; 100 out_exhausted=TRUE; 101 out_no_challenge=FALSE; 102 out_auth_attempts_left=0; 103 RETURN; 104 END IF; 105 106 IF (my_status.last_pin IS NULL) 107 THEN 108 out_solved=FALSE; 109 out_exhausted=FALSE; 110 out_auth_attempts_left=0; 111 out_no_challenge=TRUE; 112 RETURN; 113 END IF; 114 out_no_challenge=FALSE; 115 116 IF (0 > my_status.auth_attempts_left) 117 THEN 118 out_solved=TRUE; 119 out_exhausted=TRUE; 120 out_auth_attempts_left=0; 121 RETURN; 122 END IF; 123 124 IF (0 = my_status.auth_attempts_left) 125 THEN 126 out_solved=FALSE; 127 out_exhausted=TRUE; 128 out_auth_attempts_left=0; 129 RETURN; 130 END IF; 131 out_exhausted=FALSE; 132 out_solved = (my_status.last_pin = in_new_pin); 133 134 IF NOT out_solved 135 THEN 136 out_auth_attempts_left=my_status.auth_attempts_left-1; 137 -- That was the last chance if no retransmission or address change can 138 -- bring a fresh TAN. 139 out_failed = ( (0 = out_auth_attempts_left) AND 140 (0 = my_status.pin_transmissions_left) AND 141 my_fixed_address ); 142 ELSE 143 out_auth_attempts_left=-1; -- solved: no more attempts 144 END IF; 145 146 UPDATE validations 147 SET auth_attempts_left=out_auth_attempts_left 148 ,failed=out_failed 149 WHERE nonce=in_nonce; 150 151 RETURN; 152 153 END $$;