diff options
Diffstat (limited to 'src/stasis/plugin_anastasis_postgres.c')
-rw-r--r-- | src/stasis/plugin_anastasis_postgres.c | 154 |
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; | ||
2170 | retry: | ||
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 | */ | ||
2194 | static enum GNUNET_DB_QueryStatus | ||
2195 | postgres_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; |