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