Line data Source code
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 0 : 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 0 : expiration = GNUNET_TIME_relative_to_absolute (duration);
62 0 : GNUNET_assert (0 ==
63 : pthread_mutex_lock (&h->big_lock));
64 0 : acc = TALER_FAKEBANK_lookup_account_ (h,
65 : account_name,
66 : NULL);
67 0 : if (NULL == acc)
68 : {
69 0 : GNUNET_assert (0 ==
70 : pthread_mutex_unlock (&h->big_lock));
71 0 : return TALER_MHD_reply_with_error (connection,
72 : MHD_HTTP_NOT_FOUND,
73 : TALER_EC_BANK_UNKNOWN_ACCOUNT,
74 : account_name);
75 : }
76 0 : 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 0 : GNUNET_asprintf (&tok,
83 : "%s-%s-%s-%llu",
84 : account_name,
85 : scope_s,
86 : refreshable ? "r" : "n",
87 0 : (unsigned long long) expiration.abs_value_us);
88 0 : 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 0 : GNUNET_free (tok);
97 0 : 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 0 : 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 0 : struct ConnectionContext *cc = *con_cls;
122 : enum GNUNET_MHD_PostResult pr;
123 : json_t *json;
124 : MHD_RESULT res;
125 :
126 0 : if (NULL == cc)
127 : {
128 0 : cc = GNUNET_new (struct ConnectionContext);
129 0 : cc->ctx_cleaner = &GNUNET_MHD_post_parser_cleanup;
130 0 : *con_cls = cc;
131 : }
132 0 : pr = GNUNET_MHD_post_parser (REQUEST_BUFFER_MAX,
133 : connection,
134 : &cc->ctx,
135 : upload_data,
136 : upload_data_size,
137 : &json);
138 0 : switch (pr)
139 : {
140 0 : case GNUNET_MHD_PR_OUT_OF_MEMORY:
141 0 : GNUNET_break (0);
142 0 : return MHD_NO;
143 0 : case GNUNET_MHD_PR_CONTINUE:
144 0 : return MHD_YES;
145 0 : case GNUNET_MHD_PR_REQUEST_TOO_LARGE:
146 0 : GNUNET_break (0);
147 0 : return MHD_NO;
148 0 : case GNUNET_MHD_PR_JSON_INVALID:
149 0 : GNUNET_break (0);
150 0 : return MHD_NO;
151 0 : case GNUNET_MHD_PR_SUCCESS:
152 0 : break;
153 : }
154 :
155 : {
156 : const char *scope_s;
157 : struct GNUNET_TIME_Relative duration
158 0 : = GNUNET_TIME_UNIT_HOURS; /* default */
159 0 : bool refreshable = false;
160 0 : const char *description = NULL;
161 : enum GNUNET_GenericReturnValue ret;
162 : struct GNUNET_JSON_Specification spec[] = {
163 0 : GNUNET_JSON_spec_string ("scope",
164 : &scope_s),
165 0 : GNUNET_JSON_spec_mark_optional (
166 : GNUNET_JSON_spec_relative_time ("duration",
167 : &duration),
168 : NULL),
169 0 : GNUNET_JSON_spec_mark_optional (
170 : GNUNET_JSON_spec_bool ("refreshable",
171 : &refreshable),
172 : NULL),
173 0 : GNUNET_JSON_spec_mark_optional (
174 : GNUNET_JSON_spec_string ("description",
175 : &description),
176 : NULL),
177 0 : GNUNET_JSON_spec_end ()
178 : };
179 :
180 0 : if (GNUNET_OK !=
181 0 : (ret = TALER_MHD_parse_json_data (connection,
182 : json,
183 : spec)))
184 : {
185 0 : GNUNET_break_op (0);
186 0 : json_decref (json);
187 0 : return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
188 : }
189 :
190 0 : res = do_post_account_token (h,
191 : connection,
192 : account_name,
193 : scope_s,
194 : refreshable,
195 : duration);
196 : }
197 0 : json_decref (json);
198 0 : return res;
199 : }
|