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 }