paivana

HTTP paywall reverse proxy
Log | Files | Refs | Submodules | README | LICENSE

paivana-httpd_cookie.c (5299B)


      1 /*
      2   This file is part of GNU Taler
      3   Copyright (C) 2026 Taler Systems SA
      4 
      5   GNU Taler is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License
      7   as published by the Free Software Foundation; either version
      8   3, or (at your option) any later version.
      9 
     10   GNU Taler is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with GNU Taler; see the file COPYING.  If not,
     17   write to the Free Software Foundation, Inc., 51 Franklin
     18   Street, Fifth Floor, Boston, MA 02110-1301, USA.
     19 */
     20 
     21 /**
     22  * @author Christian Grothoff
     23  * @file src/backend/paivana-httpd_cookie.c
     24  * @brief Cookie computation logic for paivana
     25  */
     26 #include "platform.h"
     27 #include <curl/curl.h>
     28 #include <gcrypt.h>
     29 #include <gnunet/gnunet_util_lib.h>
     30 #include <taler/taler_mhd_lib.h>
     31 #include "paivana-httpd_cookie.h"
     32 
     33 
     34 /**
     35  * Secret for the cookie generation.
     36  */
     37 struct GNUNET_HashCode paivana_secret;
     38 
     39 
     40 /**
     41  * Compute access cookie hash for the given @a cur_time, the
     42  * @a website and @a ca.
     43  *
     44  * @param cur_time current time used in the cookie
     45  * @param website URL the cookie is valid for
     46  * @param ca_len number of bytes in @a ca
     47  * @param ca client (IP) address
     48  * @param[out] c set to the cookie hash
     49  */
     50 static void
     51 compute_cookie_hash (struct GNUNET_TIME_Timestamp cur_time,
     52                      const char *website,
     53                      size_t ca_len,
     54                      const void *ca,
     55                      struct GNUNET_HashCode *c)
     56 {
     57   struct GNUNET_TIME_AbsoluteNBO e;
     58 
     59   e = GNUNET_TIME_absolute_hton (cur_time.abs_time);
     60   GNUNET_assert (GNUNET_YES ==
     61                  GNUNET_CRYPTO_hkdf_gnunet (
     62                    c,            /* result */
     63                    sizeof (c),
     64                    &e,          /* salt */
     65                    sizeof (e),
     66                    &paivana_secret, /* source key material */
     67                    sizeof (paivana_secret),
     68                    GNUNET_CRYPTO_kdf_arg (ca,
     69                                           ca_len)));
     70 }
     71 
     72 
     73 bool
     74 PAIVANA_HTTPD_check_cookie (const char *cookie,
     75                             const char *website,
     76                             size_t ca_len,
     77                             const void *ca)
     78 {
     79   const char *dash;
     80   unsigned long long u;
     81   struct GNUNET_HashCode h;
     82   struct GNUNET_HashCode c;
     83   struct GNUNET_TIME_Timestamp a;
     84 
     85   dash = strchr (cookie,
     86                  '-');
     87   if (NULL == dash)
     88     return false;
     89   dash++;
     90   if (1 !=
     91       sscanf (cookie,
     92               "%llu-",
     93               &u))
     94     return false;
     95   a.abs_time.abs_value_us = u * 1000LLU * 1000LLU;
     96   if (GNUNET_TIME_absolute_is_past (a.abs_time))
     97     return false;
     98   if (GNUNET_OK !=
     99       GNUNET_STRINGS_string_to_data (dash,
    100                                      strlen (dash),
    101                                      &c,
    102                                      sizeof (c)))
    103     return false;
    104   compute_cookie_hash (a,
    105                        website,
    106                        ca_len,
    107                        ca,
    108                        &h);
    109   return (0 ==
    110           GNUNET_memcmp (&c,
    111                          &h));
    112 }
    113 
    114 
    115 char *
    116 PAIVANA_HTTPD_compute_cookie (struct GNUNET_TIME_Timestamp cur_time,
    117                               const char *website,
    118                               size_t ca_len,
    119                               const void *ca)
    120 {
    121   struct GNUNET_HashCode h;
    122   char *end;
    123   char cstr[128];
    124   char *res;
    125 
    126   compute_cookie_hash (cur_time,
    127                        website,
    128                        ca_len,
    129                        ca,
    130                        &h);
    131   end = GNUNET_STRINGS_data_to_string (&h,
    132                                        sizeof (h),
    133                                        cstr,
    134                                        sizeof (cstr));
    135   *end = '\0';
    136   GNUNET_asprintf (
    137     &res,
    138     "%llu-%s",
    139     (unsigned long long) (cur_time.abs_time.abs_value_us / 1000LLU / 1000LLU),
    140     cstr);
    141   return res;
    142 }
    143 
    144 
    145 char *
    146 PAIVANA_HTTPD_compute_paivana_id (struct GNUNET_TIME_Timestamp cur_time,
    147                                   const char *website,
    148                                   const struct PAIVANA_Nonce *nonce)
    149 {
    150   struct GNUNET_TIME_AbsoluteNBO e;
    151   char *res;
    152   gcry_md_hd_t hd;
    153   const void *sha256;
    154   char *cstr;
    155   size_t clen;
    156 
    157   e = GNUNET_TIME_absolute_hton (cur_time.abs_time);
    158   GNUNET_assert (0 ==
    159                  gcry_md_open (&hd,
    160                                GCRY_MD_SHA256,
    161                                0));
    162   gcry_md_write (hd,
    163                  nonce,
    164                  sizeof (*nonce));
    165   gcry_md_write (hd,
    166                  website,
    167                  strlen (website) + 1);
    168   gcry_md_write (hd,
    169                  &e,
    170                  sizeof (e));
    171   sha256 = gcry_md_read (hd,
    172                          0);
    173   cstr = NULL;
    174   clen = GNUNET_STRINGS_base64url_encode (sha256,
    175                                           256 / 8,
    176                                           &cstr);
    177   GNUNET_asprintf (
    178     &res,
    179     "%llu-%.*s",
    180     (unsigned long long) (cur_time.abs_time.abs_value_us / 1000LLU / 1000LLU),
    181     (int) clen,
    182     cstr);
    183   GNUNET_free (cstr);
    184   return res;
    185 }