challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

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 $$;