diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-08-15 10:11:17 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-08-15 10:11:17 +0200 |
commit | 3d7de36cdd35fbfe95ba20c30b37cd81249b076b (patch) | |
tree | e466ac66b7ad9d388ff4c1e72d28e8372c68cb3c | |
parent | 6f0432ed839d1f5a7a1e880f492ce162073b680b (diff) | |
download | anastasis-3d7de36cdd35fbfe95ba20c30b37cd81249b076b.tar.gz anastasis-3d7de36cdd35fbfe95ba20c30b37cd81249b076b.zip |
expand database plugin with logic to store wire transfer data made for authentication
-rw-r--r-- | src/include/anastasis_database_plugin.h | 64 | ||||
-rw-r--r-- | src/stasis/plugin_anastasis_postgres.c | 194 | ||||
-rw-r--r-- | src/stasis/stasis-0001.sql | 29 |
3 files changed, 287 insertions, 0 deletions
diff --git a/src/include/anastasis_database_plugin.h b/src/include/anastasis_database_plugin.h index 44f6b55..ae414dc 100644 --- a/src/include/anastasis_database_plugin.h +++ b/src/include/anastasis_database_plugin.h | |||
@@ -142,6 +142,23 @@ typedef void | |||
142 | 142 | ||
143 | 143 | ||
144 | /** | 144 | /** |
145 | * Function called to test if a given wire transfer | ||
146 | * satisfied the authentication requirement of the | ||
147 | * IBAN plugin. | ||
148 | * | ||
149 | * @param cls closure | ||
150 | * @param credit amount that was transferred | ||
151 | * @param wire_subject subject provided in the wire transfer | ||
152 | * @return true if this wire transfer satisfied the authentication check | ||
153 | */ | ||
154 | typedef bool | ||
155 | (*ANASTASIS_DB_AuthIbanTransfercheck)( | ||
156 | void *cls, | ||
157 | const struct TALER_Amount *credit, | ||
158 | const char *wire_subject); | ||
159 | |||
160 | |||
161 | /** | ||
145 | * Handle to interact with the database. | 162 | * Handle to interact with the database. |
146 | * | 163 | * |
147 | * Functions ending with "_TR" run their OWN transaction scope | 164 | * Functions ending with "_TR" run their OWN transaction scope |
@@ -715,6 +732,53 @@ struct ANASTASIS_DatabasePlugin | |||
715 | 732 | ||
716 | 733 | ||
717 | /** | 734 | /** |
735 | * Store inbound IBAN payment made for authentication. | ||
736 | * | ||
737 | * @param cls closure | ||
738 | * @param wire_reference unique identifier inside LibEuFin/Nexus | ||
739 | * @param wire_subject subject of the wire transfer | ||
740 | * @param amount how much was transferred | ||
741 | * @param debit_account account that was debited | ||
742 | * @param credit_account Anastasis operator account credited | ||
743 | * @param execution_date when was the transfer made | ||
744 | * @return transaction status | ||
745 | */ | ||
746 | enum GNUNET_DB_QueryStatus | ||
747 | (*record_auth_iban_payment)( | ||
748 | void *cls, | ||
749 | uint64_t wire_reference, | ||
750 | const char *wire_subject, | ||
751 | const struct TALER_Amount *amount, | ||
752 | const char *debit_account, | ||
753 | const char *credit_account, | ||
754 | struct GNUNET_TIME_Absolute execution_date); | ||
755 | |||
756 | |||
757 | /** | ||
758 | * Function to check if we are aware of a wire transfer | ||
759 | * that satisfies the IBAN plugin's authentication check. | ||
760 | * | ||
761 | * @param cls closure | ||
762 | * @param debit_account which debit account to check | ||
763 | * @param earliest_date earliest date to check | ||
764 | * @param cb function to call on all entries found | ||
765 | * @param cb_cls closure for @a cb | ||
766 | * @return transaction status, | ||
767 | * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb | ||
768 | * returned 'true' once | ||
769 | * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no | ||
770 | * wire transfers existed for which @a cb returned true | ||
771 | */ | ||
772 | enum GNUNET_DB_QueryStatus | ||
773 | (*test_auth_iban_payment)( | ||
774 | void *cls, | ||
775 | const char *debit_account, | ||
776 | struct GNUNET_TIME_Absolute earliest_date, | ||
777 | ANASTASIS_DB_AuthIbanTransfercheck cb, | ||
778 | void *cb_cls); | ||
779 | |||
780 | |||
781 | /** | ||
718 | * Function called to remove all expired codes from the database. | 782 | * Function called to remove all expired codes from the database. |
719 | * | 783 | * |
720 | * @return transaction status | 784 | * @return transaction status |
diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c index 25c4dd3..1544367 100644 --- a/src/stasis/plugin_anastasis_postgres.c +++ b/src/stasis/plugin_anastasis_postgres.c | |||
@@ -1122,6 +1122,174 @@ postgres_record_challenge_refund ( | |||
1122 | 1122 | ||
1123 | 1123 | ||
1124 | /** | 1124 | /** |
1125 | * Store inbound IBAN payment made for authentication. | ||
1126 | * | ||
1127 | * @param cls closure | ||
1128 | * @param wire_reference unique identifier inside LibEuFin/Nexus | ||
1129 | * @param wire_subject subject of the wire transfer | ||
1130 | * @param amount how much was transferred | ||
1131 | * @param debit_account account that was debited | ||
1132 | * @param credit_account Anastasis operator account credited | ||
1133 | * @param execution_date when was the transfer made | ||
1134 | * @return transaction status | ||
1135 | */ | ||
1136 | static enum GNUNET_DB_QueryStatus | ||
1137 | postgres_record_auth_iban_payment ( | ||
1138 | void *cls, | ||
1139 | uint64_t wire_reference, | ||
1140 | const char *wire_subject, | ||
1141 | const struct TALER_Amount *amount, | ||
1142 | const char *debit_account, | ||
1143 | const char *credit_account, | ||
1144 | struct GNUNET_TIME_Absolute execution_date) | ||
1145 | { | ||
1146 | struct PostgresClosure *pg = cls; | ||
1147 | struct GNUNET_PQ_QueryParam params[] = { | ||
1148 | GNUNET_PQ_query_param_uint64 (&wire_reference), | ||
1149 | GNUNET_PQ_query_param_string (wire_subject), | ||
1150 | TALER_PQ_query_param_amount (amount), | ||
1151 | GNUNET_PQ_query_param_string (debit_account), | ||
1152 | GNUNET_PQ_query_param_string (credit_account), | ||
1153 | GNUNET_PQ_query_param_absolute_time (&execution_date), | ||
1154 | GNUNET_PQ_query_param_end | ||
1155 | }; | ||
1156 | |||
1157 | check_connection (pg); | ||
1158 | return GNUNET_PQ_eval_prepared_non_select (pg->conn, | ||
1159 | "store_auth_iban_payment_details", | ||
1160 | params); | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | /** | ||
1165 | * Closure for #test_auth_cb. | ||
1166 | */ | ||
1167 | struct TestIbanContext | ||
1168 | { | ||
1169 | |||
1170 | /** | ||
1171 | * Plugin context. | ||
1172 | */ | ||
1173 | struct PostgresClosure *pg; | ||
1174 | |||
1175 | /** | ||
1176 | * Function to call on each wire transfer found. | ||
1177 | */ | ||
1178 | ANASTASIS_DB_AuthIbanTransfercheck cb; | ||
1179 | |||
1180 | /** | ||
1181 | * Closure for @a cb. | ||
1182 | */ | ||
1183 | void *cb_cls; | ||
1184 | |||
1185 | /** | ||
1186 | * Value to return. | ||
1187 | */ | ||
1188 | enum GNUNET_DB_QueryStatus qs; | ||
1189 | }; | ||
1190 | |||
1191 | |||
1192 | /** | ||
1193 | * Helper function for #postgres_test_auth_iban_payment(). | ||
1194 | * To be called with the results of a SELECT statement | ||
1195 | * that has returned @a num_results results. | ||
1196 | * | ||
1197 | * @param cls closure of type `struct TestIbanContext *` | ||
1198 | * @param result the postgres result | ||
1199 | * @param num_results the number of results in @a result | ||
1200 | */ | ||
1201 | static void | ||
1202 | test_auth_cb (void *cls, | ||
1203 | PGresult *result, | ||
1204 | unsigned int num_results) | ||
1205 | { | ||
1206 | struct TestIbanContext *tic = cls; | ||
1207 | struct PostgresClosure *pg = tic->pg; | ||
1208 | |||
1209 | for (unsigned int i = 0; i<num_results; i++) | ||
1210 | { | ||
1211 | struct TALER_Amount credit; | ||
1212 | char *wire_subject; | ||
1213 | struct GNUNET_PQ_ResultSpec rs[] = { | ||
1214 | TALER_PQ_result_spec_amount ("credit", | ||
1215 | pg->currency, | ||
1216 | &credit), | ||
1217 | GNUNET_PQ_result_spec_string ("wire_subject", | ||
1218 | &wire_subject), | ||
1219 | GNUNET_PQ_result_spec_end | ||
1220 | }; | ||
1221 | |||
1222 | if (GNUNET_OK != | ||
1223 | GNUNET_PQ_extract_result (result, | ||
1224 | rs, | ||
1225 | i)) | ||
1226 | { | ||
1227 | GNUNET_break (0); | ||
1228 | tic->qs = GNUNET_DB_STATUS_HARD_ERROR; | ||
1229 | return; | ||
1230 | } | ||
1231 | if (tic->cb (tic->cb_cls, | ||
1232 | &credit, | ||
1233 | wire_subject)) | ||
1234 | { | ||
1235 | GNUNET_free (wire_subject); | ||
1236 | tic->qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; | ||
1237 | return; | ||
1238 | } | ||
1239 | GNUNET_free (wire_subject); | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Function to check if we are aware of a wire transfer | ||
1246 | * that satisfies the IBAN plugin's authentication check. | ||
1247 | * | ||
1248 | * @param cls closure | ||
1249 | * @param debit_account which debit account to check | ||
1250 | * @param earliest_date earliest date to check | ||
1251 | * @param cb function to call on all entries found | ||
1252 | * @param cb_cls closure for @a cb | ||
1253 | * @return transaction status, | ||
1254 | * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb | ||
1255 | * returned 'true' once | ||
1256 | * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no | ||
1257 | * wire transfers existed for which @a cb returned true | ||
1258 | */ | ||
1259 | static enum GNUNET_DB_QueryStatus | ||
1260 | postgres_test_auth_iban_payment ( | ||
1261 | void *cls, | ||
1262 | const char *debit_account, | ||
1263 | struct GNUNET_TIME_Absolute earliest_date, | ||
1264 | ANASTASIS_DB_AuthIbanTransfercheck cb, | ||
1265 | void *cb_cls) | ||
1266 | { | ||
1267 | struct PostgresClosure *pg = cls; | ||
1268 | struct TestIbanContext tic = { | ||
1269 | .cb = cb, | ||
1270 | .cb_cls = cb_cls, | ||
1271 | .pg = pg | ||
1272 | }; | ||
1273 | struct GNUNET_PQ_QueryParam params[] = { | ||
1274 | GNUNET_PQ_query_param_string (debit_account), | ||
1275 | TALER_PQ_query_param_absolute_time (&earliest_date), | ||
1276 | GNUNET_PQ_query_param_end | ||
1277 | }; | ||
1278 | enum GNUNET_DB_QueryStatus qs; | ||
1279 | |||
1280 | check_connection (pg); | ||
1281 | qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, | ||
1282 | "test_auth_iban_payment", | ||
1283 | params, | ||
1284 | &test_auth_cb, | ||
1285 | &tic); | ||
1286 | if (qs < 0) | ||
1287 | return qs; | ||
1288 | return tic.qs; | ||
1289 | } | ||
1290 | |||
1291 | |||
1292 | /** | ||
1125 | * Check payment identifier. Used to check if a payment identifier given by | 1293 | * Check payment identifier. Used to check if a payment identifier given by |
1126 | * the user is valid (existing and paid). | 1294 | * the user is valid (existing and paid). |
1127 | * | 1295 | * |
@@ -2210,6 +2378,30 @@ libanastasis_plugin_db_postgres_init (void *cls) | |||
2210 | ") VALUES " | 2378 | ") VALUES " |
2211 | "($1, $2, $3, $4, $5, $6);", | 2379 | "($1, $2, $3, $4, $5, $6);", |
2212 | 6), | 2380 | 6), |
2381 | |||
2382 | GNUNET_PQ_make_prepare ("test_auth_iban_payment", | ||
2383 | "SELECT" | ||
2384 | " credit_val" | ||
2385 | ",credit_frac" | ||
2386 | ",wire_subject" | ||
2387 | " FROM anastasis_auth_iban_in" | ||
2388 | " WHERE debit_account_details=$1" | ||
2389 | " AND execution_date>=$2;", | ||
2390 | 2), | ||
2391 | GNUNET_PQ_make_prepare ("store_auth_iban_payment_details", | ||
2392 | "INSERT INTO anastasis_auth_iban_in " | ||
2393 | "(wire_reference" | ||
2394 | ",wire_subject" | ||
2395 | ",credit_val" | ||
2396 | ",credit_frac" | ||
2397 | ",debit_account_details" | ||
2398 | ",credit_account_details" | ||
2399 | ",execution_date" | ||
2400 | ") VALUES " | ||
2401 | "($1, $2, $3, $4, $5, $6, $7);", | ||
2402 | 7), | ||
2403 | |||
2404 | |||
2213 | GNUNET_PQ_make_prepare ("recovery_document_insert", | 2405 | GNUNET_PQ_make_prepare ("recovery_document_insert", |
2214 | "INSERT INTO anastasis_recoverydocument " | 2406 | "INSERT INTO anastasis_recoverydocument " |
2215 | "(user_id" | 2407 | "(user_id" |
@@ -2410,6 +2602,8 @@ libanastasis_plugin_db_postgres_init (void *cls) | |||
2410 | plugin->check_challenge_payment = &postgres_check_challenge_payment; | 2602 | plugin->check_challenge_payment = &postgres_check_challenge_payment; |
2411 | plugin->lookup_challenge_payment = &postgres_lookup_challenge_payment; | 2603 | plugin->lookup_challenge_payment = &postgres_lookup_challenge_payment; |
2412 | plugin->update_challenge_payment = &postgres_update_challenge_payment; | 2604 | plugin->update_challenge_payment = &postgres_update_challenge_payment; |
2605 | plugin->record_auth_iban_payment = &postgres_record_auth_iban_payment; | ||
2606 | plugin->test_auth_iban_payment = &postgres_test_auth_iban_payment; | ||
2413 | return plugin; | 2607 | return plugin; |
2414 | } | 2608 | } |
2415 | 2609 | ||
diff --git a/src/stasis/stasis-0001.sql b/src/stasis/stasis-0001.sql index 87dde94..e0ebfa6 100644 --- a/src/stasis/stasis-0001.sql +++ b/src/stasis/stasis-0001.sql | |||
@@ -193,5 +193,34 @@ COMMENT ON INDEX anastasis_challengecode_expiration_index | |||
193 | IS 'for challenge garbage collection'; | 193 | IS 'for challenge garbage collection'; |
194 | 194 | ||
195 | 195 | ||
196 | CREATE TABLE IF NOT EXISTS anastasis_auth_iban_in | ||
197 | (auth_in_serial_id BIGSERIAL UNIQUE | ||
198 | ,wire_reference INT8 NOT NULL PRIMARY KEY | ||
199 | ,wire_subject TEXT NOT NULL | ||
200 | ,credit_val INT8 NOT NULL | ||
201 | ,credit_frac INT4 NOT NULL | ||
202 | ,debit_account_details TEXT NOT NULL | ||
203 | ,credit_account_details TEXT NOT NULL | ||
204 | ,execution_date INT8 NOT NULL | ||
205 | ); | ||
206 | COMMENT ON TABLE anastasis_auth_iban_in | ||
207 | IS 'list of IBAN wire transfers for authentication using the IBAN plugin'; | ||
208 | COMMENT ON COLUMN anastasis_auth_iban_in.wire_reference | ||
209 | IS 'Unique number identifying the wire transfer in LibEuFin/Nexus'; | ||
210 | COMMENT ON COLUMN anastasis_auth_iban_in.wire_subject | ||
211 | IS 'For authentication, this contains the code, but also additional text'; | ||
212 | COMMENT ON COLUMN anastasis_auth_iban_in.execution_date | ||
213 | IS 'Used both for (theoretical) garbage collection and to see if the transfer happened on time'; | ||
214 | COMMENT ON COLUMN anastasis_auth_iban_in.credit_account_details | ||
215 | IS 'Identifies the bank account of the Anastasis provider, which could change over time'; | ||
216 | COMMENT ON COLUMN anastasis_auth_iban_in.debit_account_details | ||
217 | IS 'Identifies the bank account of the customer, which must match what was given in the truth'; | ||
218 | |||
219 | CREATE INDEX IF NOT EXISTS anastasis_auth_iban_in_lookup_index | ||
220 | ON anastasis_auth_iban_in | ||
221 | (debit_account_details | ||
222 | ,execution_date | ||
223 | ); | ||
224 | |||
196 | -- Complete transaction | 225 | -- Complete transaction |
197 | COMMIT; | 226 | COMMIT; |