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