fakebank_bank_post_accounts_token.c (6242B)
1 /* 2 This file is part of TALER 3 (C) 2016-2023 Taler Systems SA 4 5 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 3, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, 11 but 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 TALER; see the file COPYING. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file bank-lib/fakebank_bank_post_accounts_token.c 21 * @brief implementation of the bank API's POST /accounts/AID/token endpoint 22 * @author Christian Grothoff <christian@grothoff.org> 23 */ 24 #include <pthread.h> 25 #include "taler/taler_fakebank_lib.h" 26 #include "taler/taler_bank_service.h" 27 #include "taler/taler_mhd_lib.h" 28 #include <gnunet/gnunet_mhd_compat.h> 29 #include <gnunet/gnunet_mhd_lib.h> 30 #include "fakebank.h" 31 #include "fakebank_bank_post_accounts_token.h" 32 #include "fakebank_common_lookup.h" 33 34 35 /** 36 * Execute POST /accounts/$account_name/token request. 37 * 38 * @param h our fakebank handle 39 * @param connection the connection 40 * @param account_name name of the account 41 * @param scope_s scope of the token (as a string) 42 * @param refreshable true if the token can be refreshed 43 * @param duration how long should the token be valid 44 * @return MHD result code 45 */ 46 static MHD_RESULT 47 do_post_account_token ( 48 struct TALER_FAKEBANK_Handle *h, 49 struct MHD_Connection *connection, 50 const char *account_name, 51 const char *scope_s, 52 bool refreshable, 53 struct GNUNET_TIME_Relative duration) 54 { 55 struct Account *acc; 56 char *tok; 57 struct GNUNET_TIME_Absolute expiration; 58 MHD_RESULT res; 59 60 expiration = GNUNET_TIME_relative_to_absolute (duration); 61 GNUNET_assert (0 == 62 pthread_mutex_lock (&h->big_lock)); 63 acc = TALER_FAKEBANK_lookup_account_ (h, 64 account_name, 65 NULL); 66 if (NULL == acc) 67 { 68 GNUNET_assert (0 == 69 pthread_mutex_unlock (&h->big_lock)); 70 return TALER_MHD_reply_with_error (connection, 71 MHD_HTTP_NOT_FOUND, 72 TALER_EC_BANK_UNKNOWN_ACCOUNT, 73 account_name); 74 } 75 GNUNET_assert (0 == 76 pthread_mutex_unlock (&h->big_lock)); 77 /* We keep it simple and encode everything explicitly in the token, 78 no real security here => no need to actually track tokens! 79 (Note: this also means we cannot implement the token 80 deletion/revocation or list APIs.) */ 81 GNUNET_asprintf (&tok, 82 "%s-%s-%s-%llu", 83 account_name, 84 scope_s, 85 refreshable ? "r" : "n", 86 (unsigned long long) expiration.abs_value_us); 87 res = TALER_MHD_REPLY_JSON_PACK ( 88 connection, 89 MHD_HTTP_OK, 90 GNUNET_JSON_pack_string ("access_token", 91 tok), 92 GNUNET_JSON_pack_timestamp ("expiration", 93 GNUNET_TIME_absolute_to_timestamp (expiration))) 94 ; 95 GNUNET_free (tok); 96 return res; 97 } 98 99 100 /** 101 * Handle POST /accounts/$account_name/token request. 102 * 103 * @param h our fakebank handle 104 * @param connection the connection 105 * @param account_name name of the account 106 * @param upload_data request data 107 * @param upload_data_size size of @a upload_data in bytes 108 * @param con_cls closure for request 109 * @return MHD result code 110 */ 111 MHD_RESULT 112 TALER_FAKEBANK_bank_post_accounts_token_ ( 113 struct TALER_FAKEBANK_Handle *h, 114 struct MHD_Connection *connection, 115 const char *account_name, 116 const void *upload_data, 117 size_t *upload_data_size, 118 void **con_cls) 119 { 120 struct ConnectionContext *cc = *con_cls; 121 enum GNUNET_MHD_PostResult pr; 122 json_t *json; 123 MHD_RESULT res; 124 125 if (NULL == cc) 126 { 127 cc = GNUNET_new (struct ConnectionContext); 128 cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup; 129 *con_cls = cc; 130 } 131 pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX, 132 connection, 133 &cc->ctx, 134 upload_data, 135 upload_data_size, 136 &json); 137 switch (pr) 138 { 139 case GNUNET_MHD_PR_OUT_OF_MEMORY: 140 GNUNET_break (0); 141 return MHD_NO; 142 case GNUNET_MHD_PR_CONTINUE: 143 return MHD_YES; 144 case GNUNET_MHD_PR_REQUEST_TOO_LARGE: 145 GNUNET_break (0); 146 return MHD_NO; 147 case GNUNET_MHD_PR_JSON_INVALID: 148 GNUNET_break (0); 149 return MHD_NO; 150 case GNUNET_MHD_PR_SUCCESS: 151 break; 152 } 153 154 { 155 const char *scope_s; 156 struct GNUNET_TIME_Relative duration 157 = GNUNET_TIME_UNIT_HOURS; /* default */ 158 bool refreshable = false; 159 const char *description = NULL; 160 enum GNUNET_GenericReturnValue ret; 161 struct GNUNET_JSON_Specification spec[] = { 162 GNUNET_JSON_spec_string ("scope", 163 &scope_s), 164 GNUNET_JSON_spec_mark_optional ( 165 GNUNET_JSON_spec_relative_time ("duration", 166 &duration), 167 NULL), 168 GNUNET_JSON_spec_mark_optional ( 169 GNUNET_JSON_spec_bool ("refreshable", 170 &refreshable), 171 NULL), 172 GNUNET_JSON_spec_mark_optional ( 173 GNUNET_JSON_spec_string ("description", 174 &description), 175 NULL), 176 GNUNET_JSON_spec_end () 177 }; 178 179 if (GNUNET_OK != 180 (ret = TALER_MHD_parse_json_data (connection, 181 json, 182 spec))) 183 { 184 GNUNET_break_op (0); 185 json_decref (json); 186 return (GNUNET_NO == ret) ? MHD_YES : MHD_NO; 187 } 188 189 res = do_post_account_token (h, 190 connection, 191 account_name, 192 scope_s, 193 refreshable, 194 duration); 195 } 196 json_decref (json); 197 return res; 198 }