challenger-admin.c (8565B)
1 /* 2 This file is part of Challenger 3 Copyright (C) 2023 Taler Systems SA 4 5 Challenger is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Challenger is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file challenger/challenger-admin.c 18 * @brief Administer clients of a challenger service 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <gnunet/gnunet_db_lib.h> 24 #include "challenger_util.h" 25 #include "challenger_database_lib.h" 26 #include "challenger-database/client_delete.h" 27 #include "challenger-database/client_check.h" 28 #include "challenger-database/client_modify.h" 29 #include "challenger-database/client_add.h" 30 #include "challenger-database/preflight.h" 31 32 33 /** 34 * Prefix required for all Bearer tokens. 35 */ 36 #define RFC_8959_PREFIX "secret-token:" 37 38 39 /** 40 * Return value from main(). 41 */ 42 static int global_ret; 43 44 /** 45 * -a option: client secret 46 */ 47 static char *client_secret; 48 49 /** 50 * -m option: client ID 51 */ 52 static char *client_id; 53 54 /** 55 * -d option: delete client 56 */ 57 static int del_flag; 58 59 /** 60 * -q option: be quiet 61 */ 62 static int be_quiet; 63 64 65 /** 66 * Main function that will be run. 67 * 68 * @param cls closure 69 * @param args remaining command-line arguments 70 * @param cfgfile name of the configuration file used (for saving, can be NULL!) 71 * @param cfg configuration 72 */ 73 static void 74 run (void *cls, 75 char *const *args, 76 const char *cfgfile, 77 const struct GNUNET_CONFIGURATION_Handle *cfg) 78 { 79 const char *redirect_uri = args[0]; 80 struct CHALLENGERDB_PostgresContext *db; 81 82 (void) cls; 83 (void) cfgfile; 84 if (NULL == redirect_uri) 85 { 86 fprintf (stderr, 87 "challenger-admin must be invoked with the client REDIRECT URI as first argument\n"); 88 global_ret = EXIT_INVALIDARGUMENT; 89 return; 90 } 91 if ( (NULL != client_secret) && 92 (0 != strncasecmp (client_secret, 93 RFC_8959_PREFIX, 94 strlen (RFC_8959_PREFIX))) ) 95 { 96 fprintf (stderr, 97 "CLIENT_SECRET must begin with `%s'\n", 98 RFC_8959_PREFIX); 99 global_ret = EXIT_INVALIDARGUMENT; 100 return; 101 } 102 if (NULL == 103 (db = CHALLENGERDB_connect (cfg, 104 false))) 105 { 106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 107 "Failed to initialize database connection.\n"); 108 global_ret = EXIT_NOTINSTALLED; 109 return; 110 } 111 if (del_flag) 112 { 113 enum GNUNET_DB_QueryStatus qs; 114 115 if (NULL != client_id) 116 { 117 fprintf (stderr, 118 "'-m' and '-d' options cannot be used at the same time\n"); 119 global_ret = EXIT_INVALIDARGUMENT; 120 goto cleanup; 121 } 122 qs = CHALLENGERDB_client_delete (db, 123 redirect_uri); 124 switch (qs) 125 { 126 case GNUNET_DB_STATUS_SOFT_ERROR: 127 case GNUNET_DB_STATUS_HARD_ERROR: 128 GNUNET_break (0); 129 global_ret = EXIT_FAILURE; 130 goto cleanup; 131 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 132 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 133 "Client with this CLIENT_REDIRECT_URI is not known.\n"); 134 global_ret = EXIT_FAILURE; 135 goto cleanup; 136 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 137 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 138 "Client deleted\n"); 139 break; 140 } 141 goto cleanup; 142 } 143 if (NULL != client_id) 144 { 145 enum GNUNET_DB_QueryStatus qs; 146 unsigned long long row_id; 147 char dummy; 148 149 if (1 != 150 sscanf (client_id, 151 "%llu%c", 152 &row_id, 153 &dummy)) 154 { 155 fprintf (stderr, 156 "CLIENT_ID must be a positive number\n"); 157 global_ret = EXIT_INVALIDARGUMENT; 158 goto cleanup; 159 } 160 161 qs = CHALLENGERDB_client_modify (db, 162 row_id, 163 redirect_uri, 164 client_secret); 165 switch (qs) 166 { 167 case GNUNET_DB_STATUS_SOFT_ERROR: 168 case GNUNET_DB_STATUS_HARD_ERROR: 169 GNUNET_break (0); 170 global_ret = EXIT_FAILURE; 171 goto cleanup; 172 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 173 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 174 "Client %llu not found.\n", 175 row_id); 176 global_ret = EXIT_FAILURE; 177 goto cleanup; 178 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 179 if (! be_quiet) 180 fprintf (stdout, 181 "Client modified.\n"); 182 break; 183 } 184 goto cleanup; 185 } 186 if (NULL != client_secret) 187 { 188 enum GNUNET_DB_QueryStatus qs; 189 uint64_t row_id; 190 191 qs = CHALLENGERDB_client_check2 (db, 192 redirect_uri, 193 client_secret, 194 &row_id); 195 switch (qs) 196 { 197 case GNUNET_DB_STATUS_SOFT_ERROR: 198 case GNUNET_DB_STATUS_HARD_ERROR: 199 GNUNET_break (0); 200 global_ret = EXIT_FAILURE; 201 goto cleanup; 202 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 203 break; 204 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 205 if (be_quiet) 206 fprintf (stdout, 207 "%llu\n", 208 (unsigned long long) row_id); 209 else 210 fprintf (stdout, 211 "Client added. Client ID is: %llu\n", 212 (unsigned long long) row_id); 213 goto cleanup; 214 } 215 qs = CHALLENGERDB_client_add (db, 216 redirect_uri, 217 client_secret, 218 &row_id); 219 switch (qs) 220 { 221 case GNUNET_DB_STATUS_SOFT_ERROR: 222 case GNUNET_DB_STATUS_HARD_ERROR: 223 GNUNET_break (0); 224 global_ret = EXIT_FAILURE; 225 goto cleanup; 226 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 227 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 228 "Client with this CLIENT_REDIRECT_URI already exists.\n"); 229 global_ret = EXIT_FAILURE; 230 goto cleanup; 231 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 232 if (be_quiet) 233 fprintf (stdout, 234 "%llu\n", 235 (unsigned long long) row_id); 236 else 237 fprintf (stdout, 238 "Client added. Client ID is: %llu\n", 239 (unsigned long long) row_id); 240 break; 241 } 242 goto cleanup; 243 } 244 cleanup: 245 CHALLENGERDB_disconnect (db); 246 } 247 248 249 /** 250 * The main function of the client management tool. Used to add or 251 * remove clients from the Challenger' database. 252 * 253 * @param argc number of arguments from the command line 254 * @param argv command line arguments 255 * @return 0 ok, non-zero on error 256 */ 257 int 258 main (int argc, 259 char *const *argv) 260 { 261 struct GNUNET_GETOPT_CommandLineOption options[] = { 262 GNUNET_GETOPT_option_string ('a', 263 "add", 264 "CLIENT_SECRET", 265 "add client", 266 &client_secret), 267 GNUNET_GETOPT_option_flag ('d', 268 "delete", 269 "delete client", 270 &del_flag), 271 GNUNET_GETOPT_option_string ('m', 272 "modify-client", 273 "CLIENT_ID", 274 "modify existing client to use the given secret and redirect URL", 275 &client_id), 276 GNUNET_GETOPT_option_flag ('q', 277 "quiet", 278 "be less verbose in the output", 279 &be_quiet), 280 /* FIXME: add -s / --show option */ 281 GNUNET_GETOPT_OPTION_END 282 }; 283 enum GNUNET_GenericReturnValue ret; 284 285 ret = GNUNET_PROGRAM_run (CHALLENGER_project_data (), 286 argc, argv, 287 "challenger-admin CLIENT_REDIRECT_URI", 288 "Tool to add, modify or remove clients from challenger", 289 options, 290 &run, NULL); 291 if (GNUNET_SYSERR == ret) 292 return EXIT_INVALIDARGUMENT; 293 if (GNUNET_NO == ret) 294 return EXIT_SUCCESS; 295 return global_ret; 296 } 297 298 299 /* end of challenger-dbinit.c */