/* This file is part of GNU Taler (C) 2021 Taler Systems SA GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file taler-merchant-httpd_private-post-instances-ID-auth.c * @brief implementing POST /instances/$ID/auth request handling * @author Christian Grothoff * @author Florian Dold */ #include "platform.h" #include "taler-merchant-httpd_private-post-instances-ID-auth.h" #include /** * How often do we retry the simple INSERT database transaction? */ #define MAX_RETRIES 3 /** * Change the authentication settings of an instance. * * @param mi instance to modify settings of * @param connection the MHD connection to handle * @param[in,out] hc context with further information about the request * @return MHD result code */ static MHD_RESULT post_instances_ID_auth (struct TMH_MerchantInstance *mi, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TALER_MERCHANTDB_InstanceAuthSettings ias; const char *auth_token = NULL; json_t *jauth = hc->request_body; { bool auth_ok = false; const char *auth_method = json_string_value (json_object_get (jauth, "method")); if (NULL == auth_method) GNUNET_break_op (0); else if (0 == strcmp (auth_method, "external")) { auth_token = NULL; auth_ok = true; } else if (0 == strcmp (auth_method, "token")) { auth_token = json_string_value (json_object_get (jauth, "token")); if (NULL != auth_token) { if (0 != strncasecmp (RFC_8959_PREFIX, auth_token, strlen (RFC_8959_PREFIX))) GNUNET_break_op (0); else auth_ok = true; } else GNUNET_break_op (0); } if (! auth_ok) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH, "bad authentication config"); } } if (NULL == auth_token) { memset (&ias.auth_salt, 0, sizeof (ias.auth_salt)); memset (&ias.auth_hash, 0, sizeof (ias.auth_hash)); } else { TMH_compute_auth (auth_token, &ias.auth_salt, &ias.auth_hash); } { enum GNUNET_DB_QueryStatus qs; for (unsigned int i = 0; istart (TMH_db->cls, "post /instances/$ID/auth")) { return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_START_FAILED, NULL); } qs = TMH_db->update_instance_auth (TMH_db->cls, mi->settings.id, &ias); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); TMH_db->rollback (TMH_db->cls); goto retry; } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); TMH_db->rollback (TMH_db->cls); goto retry; } qs = TMH_db->commit (TMH_db->cls); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; retry: if (GNUNET_DB_STATUS_SOFT_ERROR != qs) break; /* success! -- or hard failure */ } /* for .. MAX_RETRIES */ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) { return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_COMMIT_FAILED, NULL); } /* Finally, also update our running process */ mi->auth = ias; } if (0 == strcmp (mi->settings.id, "default")) GNUNET_free (TMH_default_auth); /* clear after it was manually set */ return TALER_MHD_reply_static (connection, MHD_HTTP_NO_CONTENT, NULL, NULL, 0); } MHD_RESULT TMH_private_post_instances_ID_auth (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TMH_MerchantInstance *mi = hc->instance; return post_instances_ID_auth (mi, connection, hc); } MHD_RESULT TMH_private_post_instances_default_ID_auth (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TMH_MerchantInstance *mi; mi = TMH_lookup_instance (hc->infix); if (NULL == mi) { return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN, hc->infix); } return post_instances_ID_auth (mi, connection, hc); } /* end of taler-merchant-httpd_private-post-instances-ID-auth.c */