aboutsummaryrefslogtreecommitdiff
path: root/src/stasis/plugin_anastasis_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stasis/plugin_anastasis_postgres.c')
-rw-r--r--src/stasis/plugin_anastasis_postgres.c154
1 files changed, 23 insertions, 131 deletions
diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c
index 506c304..8ee16ad 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -1763,6 +1763,11 @@ struct CheckValidityContext
1763 struct PostgresClosure *pg; 1763 struct PostgresClosure *pg;
1764 1764
1765 /** 1765 /**
1766 * Set to the matching challenge code (if @e valid).
1767 */
1768 uint64_t code;
1769
1770 /**
1766 * Set to true if a code matching @e hashed_code was found. 1771 * Set to true if a code matching @e hashed_code was found.
1767 */ 1772 */
1768 bool valid; 1773 bool valid;
@@ -1828,6 +1833,7 @@ check_valid_code (void *cls,
1828 cvc->hashed_code)) 1833 cvc->hashed_code))
1829 { 1834 {
1830 cvc->valid = true; 1835 cvc->valid = true;
1836 cvc->code = server_code;
1831 cvc->satisfied = (0 != sat); 1837 cvc->satisfied = (0 != sat);
1832 } 1838 }
1833 else 1839 else
@@ -1862,6 +1868,7 @@ check_valid_code (void *cls,
1862 * @param cls closure 1868 * @param cls closure
1863 * @param truth_uuid identification of the challenge which the code corresponds to 1869 * @param truth_uuid identification of the challenge which the code corresponds to
1864 * @param hashed_code code which the user provided and wants to verify 1870 * @param hashed_code code which the user provided and wants to verify
1871 * @param[out] code set to the original numeric code
1865 * @param[out] satisfied set to true if the challenge is set to satisfied 1872 * @param[out] satisfied set to true if the challenge is set to satisfied
1866 * @return code validity status 1873 * @return code validity status
1867 */ 1874 */
@@ -1870,6 +1877,7 @@ postgres_verify_challenge_code (
1870 void *cls, 1877 void *cls,
1871 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, 1878 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
1872 const struct GNUNET_HashCode *hashed_code, 1879 const struct GNUNET_HashCode *hashed_code,
1880 uint64_t *code,
1873 bool *satisfied) 1881 bool *satisfied)
1874{ 1882{
1875 struct PostgresClosure *pg = cls; 1883 struct PostgresClosure *pg = cls;
@@ -1897,6 +1905,7 @@ postgres_verify_challenge_code (
1897 if ( (qs < 0) || 1905 if ( (qs < 0) ||
1898 (cvc.db_failure) ) 1906 (cvc.db_failure) )
1899 return ANASTASIS_DB_CODE_STATUS_HARD_ERROR; 1907 return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
1908 *code = cvc.code;
1900 if (cvc.valid) 1909 if (cvc.valid)
1901 { 1910 {
1902 *satisfied = cvc.satisfied; 1911 *satisfied = cvc.satisfied;
@@ -2059,7 +2068,7 @@ postgres_create_challenge_code (
2059 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, 2068 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
2060 struct GNUNET_TIME_Relative rotation_period, 2069 struct GNUNET_TIME_Relative rotation_period,
2061 struct GNUNET_TIME_Relative validity_period, 2070 struct GNUNET_TIME_Relative validity_period,
2062 unsigned int retry_counter, 2071 uint32_t retry_counter,
2063 struct GNUNET_TIME_Absolute *retransmission_date, 2072 struct GNUNET_TIME_Absolute *retransmission_date,
2064 uint64_t *code) 2073 uint64_t *code)
2065{ 2074{
@@ -2117,15 +2126,22 @@ postgres_create_challenge_code (
2117 case GNUNET_DB_STATUS_SOFT_ERROR: 2126 case GNUNET_DB_STATUS_SOFT_ERROR:
2118 goto retry; 2127 goto retry;
2119 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 2128 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
2120 /* no active challenge, create fresh one (below) */ 2129 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2130 "No active challenge found, creating a fresh one\n");
2121 break; 2131 break;
2122 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2132 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
2123 if (0 == old_retry_counter) 2133 if (0 == old_retry_counter)
2124 { 2134 {
2125 rollback (pg); 2135 rollback (pg);
2136 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2137 "Active challenge %llu has zero tries left, refusing to create another one\n",
2138 (unsigned long long) code);
2126 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 2139 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
2127 } 2140 }
2128 rollback (pg); 2141 rollback (pg);
2142 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2143 "Active challenge has %u tries left, returning old challenge\n",
2144 (unsigned int) old_retry_counter);
2129 return qs; 2145 return qs;
2130 } 2146 }
2131 } 2147 }
@@ -2158,132 +2174,9 @@ postgres_create_challenge_code (
2158 rollback (pg); 2174 rollback (pg);
2159 return GNUNET_DB_STATUS_HARD_ERROR; 2175 return GNUNET_DB_STATUS_HARD_ERROR;
2160 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 2176 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
2161 break; 2177 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2162 } 2178 "Created fresh challenge with %u tries left\n",
2163 } 2179 (unsigned int) retry_counter);
2164 qs = commit_transaction (pg);
2165 if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
2166 goto retry;
2167 if (qs < 0)
2168 return qs;
2169 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
2170retry:
2171 rollback (pg);
2172 }
2173 return GNUNET_DB_STATUS_SOFT_ERROR;
2174}
2175
2176
2177/**
2178 * Setup challenge code for a given challenge identified by the
2179 * challenge public key. The function will first check if there is
2180 * already a valid code for this challenge present and won't insert
2181 * a new one in this case. This variant is not rate-limited, will
2182 * return the existing challenge if it has not yet expired and will
2183 * simply create new challenges when the old ones need to be
2184 * rotated.
2185 *
2186 * @param cls closure
2187 * @param truth_uuid the identifier for the challenge
2188 * @param rotation_period for how long is the code available
2189 * @param validity_period for how long is the code available
2190 * @param[out] code set to the code which will be checked for later
2191 * @return transaction status,
2192 * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a code is now in the DB
2193 */
2194static enum GNUNET_DB_QueryStatus
2195postgres_get_unlimited_challenge_code (
2196 void *cls,
2197 const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
2198 struct GNUNET_TIME_Relative rotation_period,
2199 struct GNUNET_TIME_Relative validity_period,
2200 uint64_t *code)
2201{
2202 struct PostgresClosure *pg = cls;
2203 enum GNUNET_DB_QueryStatus qs;
2204 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
2205 struct GNUNET_TIME_Absolute expiration_date;
2206 struct GNUNET_TIME_Absolute ex_rot;
2207
2208 check_connection (pg);
2209 GNUNET_TIME_round_abs (&now);
2210 expiration_date = GNUNET_TIME_absolute_add (now,
2211 validity_period);
2212 ex_rot = GNUNET_TIME_absolute_subtract (now,
2213 rotation_period);
2214 for (unsigned int retries = 0; retries<MAX_RETRIES; retries++)
2215 {
2216 if (GNUNET_OK !=
2217 begin_transaction (pg,
2218 "get_unlimited_challenge_code"))
2219 {
2220 GNUNET_break (0);
2221 return GNUNET_DB_STATUS_HARD_ERROR;
2222 }
2223
2224 {
2225 struct GNUNET_PQ_QueryParam params[] = {
2226 GNUNET_PQ_query_param_auto_from_type (truth_uuid),
2227 TALER_PQ_query_param_absolute_time (&now),
2228 TALER_PQ_query_param_absolute_time (&ex_rot),
2229 GNUNET_PQ_query_param_end
2230 };
2231 struct GNUNET_PQ_ResultSpec rs[] = {
2232 GNUNET_PQ_result_spec_uint64 ("code",
2233 code),
2234 GNUNET_PQ_result_spec_end
2235 };
2236 enum GNUNET_DB_QueryStatus qs;
2237
2238 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
2239 "challengecode_select_meta",
2240 params,
2241 rs);
2242 switch (qs)
2243 {
2244 case GNUNET_DB_STATUS_HARD_ERROR:
2245 GNUNET_break (0);
2246 rollback (pg);
2247 return qs;
2248 case GNUNET_DB_STATUS_SOFT_ERROR:
2249 goto retry;
2250 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
2251 /* no active challenge, create fresh one (below) */
2252 break;
2253 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
2254 rollback (pg);
2255 return qs;
2256 }
2257 }
2258
2259 *code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
2260 NONCE_MAX_VALUE);
2261 {
2262 uint32_t retry_counter = UINT32_MAX;
2263 struct GNUNET_PQ_QueryParam params[] = {
2264 GNUNET_PQ_query_param_auto_from_type (truth_uuid),
2265 GNUNET_PQ_query_param_uint64 (code),
2266 TALER_PQ_query_param_absolute_time (&now),
2267 TALER_PQ_query_param_absolute_time (&expiration_date),
2268 GNUNET_PQ_query_param_uint32 (&retry_counter),
2269 GNUNET_PQ_query_param_end
2270 };
2271
2272 qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
2273 "challengecode_insert",
2274 params);
2275 switch (qs)
2276 {
2277 case GNUNET_DB_STATUS_HARD_ERROR:
2278 rollback (pg);
2279 return GNUNET_DB_STATUS_HARD_ERROR;
2280 case GNUNET_DB_STATUS_SOFT_ERROR:
2281 goto retry;
2282 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
2283 GNUNET_break (0);
2284 rollback (pg);
2285 return GNUNET_DB_STATUS_HARD_ERROR;
2286 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
2287 break; 2180 break;
2288 } 2181 }
2289 } 2182 }
@@ -2675,7 +2568,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
2675 " FROM anastasis_challengecode" 2568 " FROM anastasis_challengecode"
2676 " WHERE truth_uuid=$1" 2569 " WHERE truth_uuid=$1"
2677 " AND expiration_date > $2" 2570 " AND expiration_date > $2"
2678 " AND retry_counter > 0;", 2571 " AND retry_counter != 0;",
2679 2), 2572 2),
2680 GNUNET_PQ_make_prepare ("challengecode_set_satisfied", 2573 GNUNET_PQ_make_prepare ("challengecode_set_satisfied",
2681 "UPDATE anastasis_challengecode" 2574 "UPDATE anastasis_challengecode"
@@ -2715,7 +2608,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
2715 " SET retry_counter=retry_counter - 1" 2608 " SET retry_counter=retry_counter - 1"
2716 " WHERE truth_uuid=$1" 2609 " WHERE truth_uuid=$1"
2717 " AND code=$2" 2610 " AND code=$2"
2718 " AND retry_counter > 0;", 2611 " AND retry_counter != 0;",
2719 1), 2612 1),
2720 GNUNET_PQ_make_prepare ("challengepayment_dec_counter", 2613 GNUNET_PQ_make_prepare ("challengepayment_dec_counter",
2721 "UPDATE anastasis_challenge_payment" 2614 "UPDATE anastasis_challenge_payment"
@@ -2807,7 +2700,6 @@ libanastasis_plugin_db_postgres_init (void *cls)
2807 plugin->test_challenge_code_satisfied = 2700 plugin->test_challenge_code_satisfied =
2808 &postgres_test_challenge_code_satisfied; 2701 &postgres_test_challenge_code_satisfied;
2809 plugin->create_challenge_code = &postgres_create_challenge_code; 2702 plugin->create_challenge_code = &postgres_create_challenge_code;
2810 plugin->get_unlimited_challenge_code = &postgres_get_unlimited_challenge_code;
2811 plugin->mark_challenge_sent = &postgres_mark_challenge_sent; 2703 plugin->mark_challenge_sent = &postgres_mark_challenge_sent;
2812 plugin->challenge_gc = &postgres_challenge_gc; 2704 plugin->challenge_gc = &postgres_challenge_gc;
2813 plugin->record_truth_upload_payment = &postgres_record_truth_upload_payment; 2705 plugin->record_truth_upload_payment = &postgres_record_truth_upload_payment;