1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 /***************************************************************************
21 * Copyright (C) 2017-2021 ZmartZone Holding BV
22 * Copyright (C) 2013-2017 Ping Identity Corporation
23 * All rights reserved.
24 *
25 * DISCLAIMER OF WARRANTIES:
26 *
27 * THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
28 * ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
29 * WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
30 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. NOR ARE THERE ANY
31 * WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
32 * USAGE. FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
33 * YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
34 * WILL BE UNINTERRUPTED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * @Author: Hans Zandbelt - hans.zandbelt@zmartzone.eu
42 *
43 **************************************************************************/
44
45 #include <stdio.h>
46 #include <string.h>
47
48 #include <apr_file_io.h>
49 #include <apr_base64.h>
50
51 #include <openssl/rsa.h>
52 #include <openssl/pem.h>
53
54 #include <cjose/header.h>
55 #include <cjose/jws.h>
56
57 #include <mod_auth_openidc.h>
58
usage(int argc,char ** argv,const char * msg)59 int usage(int argc, char **argv, const char *msg) {
60 fprintf(stderr, "Usage: %s %s\n", argv[0],
61 msg ? msg : "[ sign | verify | decrypt | jwk2cert | key2jwk | enckey | hash_base64url | timestamp | uuid ] <options>");
62 return -1;
63 }
64
file_read(apr_pool_t * pool,const char * path,char ** rbuf)65 int file_read(apr_pool_t *pool, const char *path, char **rbuf) {
66 apr_file_t *fd = NULL;
67 char s_err[128];
68 int rc;
69 apr_size_t bytes_read = 0;
70 apr_finfo_t finfo;
71 apr_size_t len;
72
73 rc = apr_file_open(&fd, path, APR_FOPEN_READ | APR_FOPEN_BUFFERED,
74 APR_OS_DEFAULT, pool);
75 if (rc != APR_SUCCESS) {
76 fprintf(stderr, "could not open file %s: %s", path,
77 apr_strerror(rc, s_err, sizeof(s_err)));
78 return -1;
79 }
80
81 apr_file_info_get(&finfo, APR_FINFO_NORM, fd);
82 len = (apr_size_t) finfo.size;
83 *rbuf = apr_pcalloc(pool, len + 1);
84
85 rc = apr_file_read_full(fd, *rbuf, len, &bytes_read);
86 if (rc != APR_SUCCESS) {
87 fprintf(stderr, "could not read file %s: %s", path,
88 apr_strerror(rc, s_err, sizeof(s_err)));
89 return -1;
90 }
91
92 (*rbuf)[bytes_read] = '\0';
93
94 bytes_read--;
95 while ((*rbuf)[bytes_read] == '\n') {
96 (*rbuf)[bytes_read] = '\0';
97 bytes_read--;
98 }
99
100 apr_file_close(fd);
101
102 return 0;
103 }
104
sign(int argc,char ** argv,apr_pool_t * pool)105 int sign(int argc, char **argv, apr_pool_t *pool) {
106
107 if (argc <= 4)
108 return usage(argc, argv, "sign <algo> <jwt-file> <jwk-file>");
109
110 char *s_jwt = NULL, *s_jwk = NULL;
111 const char *cser = NULL;
112
113 if (file_read(pool, argv[3], &s_jwt) != 0)
114 return -1;
115 if (file_read(pool, argv[4], &s_jwk) != 0)
116 return -1;
117
118 cjose_err cjose_err;
119
120 cjose_header_t *hdr = cjose_header_new(&cjose_err);
121 cjose_header_set(hdr, "alg", argv[2], &cjose_err);
122
123 cjose_jwk_t *jwk = cjose_jwk_import(s_jwk, strlen(s_jwk), &cjose_err);
124 if (jwk == NULL) {
125 fprintf(stderr,
126 "could not import JWK: %s [file: %s, function: %s, line: %ld]\n",
127 cjose_err.message, cjose_err.file, cjose_err.function,
128 cjose_err.line);
129 return -1;
130 }
131
132 cjose_jws_t *jws = cjose_jws_sign(jwk, hdr, (const uint8_t *) s_jwt,
133 strlen(s_jwt), &cjose_err);
134 if (jws == NULL) {
135 fprintf(stderr,
136 "could not sign JWS: %s [file: %s, function: %s, line: %ld]\n",
137 cjose_err.message, cjose_err.file, cjose_err.function,
138 cjose_err.line);
139 return -1;
140 }
141
142 if (cjose_jws_export(jws, &cser, &cjose_err) == FALSE) {
143 fprintf(stderr,
144 "could not serialize JWS: %s [file: %s, function: %s, line: %ld]\n",
145 cjose_err.message, cjose_err.file, cjose_err.function,
146 cjose_err.line);
147 return -1;
148 }
149
150 fprintf(stdout, "%s", cser);
151
152 cjose_jws_release(jws);
153 cjose_jwk_release(jwk);
154
155 return 0;
156 }
157
verify(int argc,char ** argv,apr_pool_t * pool)158 int verify(int argc, char **argv, apr_pool_t *pool) {
159
160 if (argc <= 3)
161 return usage(argc, argv, "verify <serialized-jwt-file> <jwk-file>");
162
163 char *s_jwt = NULL, *s_jwk = NULL;
164
165 if (file_read(pool, argv[2], &s_jwt) != 0)
166 return -1;
167 if (file_read(pool, argv[3], &s_jwk) != 0)
168 return -1;
169
170 cjose_err cjose_err;
171
172 cjose_jws_t *jws = cjose_jws_import(s_jwt, strlen(s_jwt), &cjose_err);
173 if (jws == NULL) {
174 fprintf(stderr,
175 "could not import JWS: %s [file: %s, function: %s, line: %ld]\n",
176 cjose_err.message, cjose_err.file, cjose_err.function,
177 cjose_err.line);
178 return -1;
179 }
180
181 oidc_jose_error_t oidc_err;
182 oidc_jwk_t *jwk = oidc_jwk_parse(pool, s_jwk, &oidc_err);
183 if (jwk == NULL) {
184 fprintf(stderr,
185 "could not import JWK: %s [file: %s, function: %s, line: %d]\n",
186 oidc_err.text, oidc_err.source, oidc_err.function,
187 oidc_err.line);
188 return -1;
189 }
190
191 if (cjose_jws_verify(jws, jwk->cjose_jwk, &cjose_err) == FALSE) {
192 fprintf(stderr,
193 "could not verify JWS: %s [file: %s, function: %s, line: %ld]\n",
194 cjose_err.message, cjose_err.file, cjose_err.function,
195 cjose_err.line);
196 return -1;
197 }
198
199 uint8_t *plaintext = NULL;
200 size_t plaintext_len = 0;
201 if (cjose_jws_get_plaintext(jws, &plaintext, &plaintext_len,
202 &cjose_err) == FALSE) {
203 fprintf(stderr,
204 "could not get plaintext: %s [file: %s, function: %s, line: %ld]\n",
205 cjose_err.message, cjose_err.file, cjose_err.function,
206 cjose_err.line);
207 return -1;
208 }
209
210 fprintf(stdout, "%s", plaintext);
211
212 cjose_jws_release(jws);
213 oidc_jwk_destroy(jwk);
214
215 return 0;
216 }
217
decrypt(int argc,char ** argv,apr_pool_t * pool)218 int decrypt(int argc, char **argv, apr_pool_t *pool) {
219
220 if (argc <= 3)
221 return usage(argc, argv, "decrypt <serialized-jwt-file> <jwk-file>");
222
223 char *s_jwt = NULL, *s_jwk = NULL;
224
225 if (file_read(pool, argv[2], &s_jwt) != 0)
226 return -1;
227 if (file_read(pool, argv[3], &s_jwk) != 0)
228 return -1;
229
230
231 apr_hash_t *keys = apr_hash_make(pool);
232 oidc_jose_error_t oidc_err;
233
234 oidc_jwk_t *jwk = oidc_jwk_parse(pool, s_jwk, &oidc_err);
235 if (jwk == NULL) {
236 fprintf(stderr,
237 "could not import JWK: %s [file: %s, function: %s, line: %d]\n",
238 oidc_err.text, oidc_err.source, oidc_err.function,
239 oidc_err.line);
240 return -1;
241 }
242
243 apr_hash_set(keys, jwk->kid ? jwk->kid : "dummy", APR_HASH_KEY_STRING, jwk);
244
245 char *plaintext = NULL;
246 if (oidc_jwe_decrypt(pool, s_jwt, keys, &plaintext, &oidc_err, TRUE) == FALSE) {
247 fprintf(stderr,
248 "oidc_jwe_decrypt failed: %s [file: %s, function: %s, line: %d]\n",
249 oidc_err.text, oidc_err.source, oidc_err.function,
250 oidc_err.line);
251 return -1;
252 }
253
254 fprintf(stdout, "%s", plaintext);
255 oidc_jwk_destroy(jwk);
256
257 return 0;
258 }
259
260
mkcert(RSA * rsa,X509 ** x509p,EVP_PKEY ** pkeyp,int serial,int days)261 int mkcert(RSA *rsa, X509 **x509p, EVP_PKEY **pkeyp, int serial, int days) {
262 X509 *x;
263 EVP_PKEY *pk;
264 X509_NAME *name = NULL;
265
266 if ((pkeyp == NULL) || (*pkeyp == NULL)) {
267 if ((pk = EVP_PKEY_new()) == NULL)
268 return -1;
269 } else
270 pk = *pkeyp;
271
272 if ((x509p == NULL) || (*x509p == NULL)) {
273 if ((x = X509_new()) == NULL)
274 return -1;
275 } else
276 x = *x509p;
277
278 if (!EVP_PKEY_assign_RSA(pk, rsa))
279 return -1;
280
281 X509_set_version(x, 2);
282 ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
283 X509_gmtime_adj(X509_get_notBefore(x), 0);
284 X509_gmtime_adj(X509_get_notAfter(x), (long) 60 * 60 * 24 * days);
285 X509_set_pubkey(x, pk);
286
287 name = X509_get_subject_name(x);
288
289 X509_NAME_add_entry_by_txt(name, "C",
290 MBSTRING_ASC, (const unsigned char *) "NL", -1, -1, 0);
291 X509_NAME_add_entry_by_txt(name, "CN",
292 MBSTRING_ASC, (const unsigned char *) "Ping Identity", -1, -1, 0);
293
294 X509_set_issuer_name(x, name);
295
296 if (!X509_sign(x, pk, EVP_md5()))
297 return -1;
298
299 *x509p = x;
300 *pkeyp = pk;
301
302 return 0;
303 }
304
jwk2cert(int argc,char ** argv,apr_pool_t * pool)305 int jwk2cert(int argc, char **argv, apr_pool_t *pool) {
306
307 if (argc <= 2)
308 return usage(argc, argv, "jwk2cert <jwk-file>");
309
310 char *s_jwk = NULL;
311
312 if (file_read(pool, argv[2], &s_jwk) != 0)
313 return -1;
314
315 cjose_err cjose_err;
316
317 cjose_jwk_t *jwk = cjose_jwk_import(s_jwk, strlen(s_jwk), &cjose_err);
318 if (jwk == NULL) {
319 fprintf(stderr,
320 "could not import JWK: %s [file: %s, function: %s, line: %ld]\n",
321 cjose_err.message, cjose_err.file, cjose_err.function,
322 cjose_err.line);
323 return -1;
324 }
325
326 if (cjose_jwk_get_kty(jwk, &cjose_err) != CJOSE_JWK_KTY_RSA) {
327 fprintf(stderr, "wrong key type");
328 return -1;
329 }
330
331 RSA *rsa = cjose_jwk_get_keydata(jwk, &cjose_err);
332 //PEM_write_RSAPublicKey(stdout, rsa);
333 PEM_write_RSA_PUBKEY(stdout, rsa);
334
335 X509 *x509 = NULL;
336 EVP_PKEY *pkey = NULL;
337
338 if (mkcert(rsa, &x509, &pkey, 0, 365) != 0)
339 return -1;
340
341 //RSA_print_fp(stdout,pkey->pkey.rsa,0);
342 //X509_print_fp(stdout,x509);
343
344 //PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL);
345 PEM_write_X509(stdout, x509);
346
347 X509_free(x509);
348 EVP_PKEY_free(pkey);
349
350 return 0;
351 }
352
key2jwk(int argc,char ** argv,apr_pool_t * pool)353 int key2jwk(int argc, char **argv, apr_pool_t *pool) {
354
355 if (argc <= 2)
356 return usage(argc, argv, "key2jwk <pem-file> <is_private_key>");
357
358 oidc_jwk_t *jwk = NULL;
359 oidc_jose_error_t err;
360
361 int is_private_key = (argc > 3);
362
363 if (is_private_key) {
364 if (oidc_jwk_parse_rsa_private_key(pool, NULL, argv[2], &jwk,
365 &err) == FALSE) {
366 fprintf(stderr, "oidc_jwk_parse_rsa_private_key failed: %s",
367 oidc_jose_e2s(pool, err));
368 return -1;
369 }
370 } else {
371 if (oidc_jwk_parse_rsa_public_key(pool, NULL, argv[2], &jwk,
372 &err) == FALSE) {
373 fprintf(stderr, "oidc_jwk_parse_rsa_public_key failed: %s",
374 oidc_jose_e2s(pool, err));
375 return -1;
376 }
377 }
378
379 char *s_json = NULL;
380 if (oidc_jwk_to_json(pool, jwk, &s_json, &err) == FALSE) {
381 fprintf(stderr, "oidc_jwk_to_json failed: %s",
382 oidc_jose_e2s(pool, err));
383 return -1;
384 }
385
386 fprintf(stdout, "%s", s_json);
387
388 oidc_jwk_destroy(jwk);
389
390 return 0;
391 }
392
393 extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
394
395 typedef struct oidc_dir_cfg oidc_dir_cfg;
396
request_setup(apr_pool_t * pool)397 static request_rec * request_setup(apr_pool_t *pool) {
398 const unsigned int kIdx = 0;
399 const unsigned int kEls = kIdx + 1;
400 request_rec *request = (request_rec *) apr_pcalloc(pool,
401 sizeof(request_rec));
402
403 request->pool = pool;
404
405 request->headers_in = apr_table_make(request->pool, 0);
406 request->headers_out = apr_table_make(request->pool, 0);
407 request->err_headers_out = apr_table_make(request->pool, 0);
408
409 apr_table_set(request->headers_in, "Host", "www.example.com");
410 apr_table_set(request->headers_in, "OIDC_foo", "some-value");
411 apr_table_set(request->headers_in, "Cookie", "foo=bar; "
412 "mod_auth_openidc_session" "=0123456789abcdef; baz=zot");
413
414 request->server = apr_pcalloc(request->pool, sizeof(struct server_rec));
415 request->server->process = apr_pcalloc(request->pool,
416 sizeof(struct process_rec));
417 request->server->process->pool = request->pool;
418 request->connection = apr_pcalloc(request->pool, sizeof(struct conn_rec));
419 request->connection->local_addr = apr_pcalloc(request->pool,
420 sizeof(apr_sockaddr_t));
421
422 apr_pool_userdata_set("https", "scheme", NULL, request->pool);
423 request->server->server_hostname = "www.example.com";
424 request->connection->local_addr->port = 443;
425 request->unparsed_uri = "/bla?foo=bar¶m1=value1";
426 request->args = "foo=bar¶m1=value1";
427 apr_uri_parse(request->pool,
428 "https://www.example.com/bla?foo=bar¶m1=value1",
429 &request->parsed_uri);
430
431 auth_openidc_module.module_index = kIdx;
432 oidc_cfg *cfg = oidc_create_server_config(request->pool, request->server);
433 cfg->provider.issuer = "https://idp.example.com";
434 cfg->provider.authorization_endpoint_url =
435 "https://idp.example.com/authorize";
436 cfg->provider.scope = "openid";
437 cfg->provider.client_id = "client_id";
438 cfg->redirect_uri = "https://www.example.com/protected/";
439
440 oidc_dir_cfg *d_cfg = oidc_create_dir_config(request->pool, NULL);
441
442 request->server->module_config = apr_pcalloc(request->pool,
443 sizeof(ap_conf_vector_t *) * kEls);
444 request->per_dir_config = apr_pcalloc(request->pool,
445 sizeof(ap_conf_vector_t *) * kEls);
446 ap_set_module_config(request->server->module_config, &auth_openidc_module,
447 cfg);
448 ap_set_module_config(request->per_dir_config, &auth_openidc_module, d_cfg);
449
450 cfg->cache = &oidc_cache_shm;
451 cfg->cache_cfg = NULL;
452 cfg->cache_shm_size_max = 500;
453 cfg->cache_shm_entry_size_max = 16384 + 255 + 17;
454 if (cfg->cache->post_config(request->server) != OK) {
455 printf("cfg->cache->post_config failed!\n");
456 exit(-1);
457 }
458
459 return request;
460 }
461
enckey(int argc,char ** argv,apr_pool_t * pool)462 int enckey(int argc, char **argv, apr_pool_t *pool) {
463
464 if (argc <= 2)
465 return usage(argc, argv, "enckey <secret> [hash] [key-length]");
466
467 request_rec *r = request_setup(pool);
468
469 oidc_jwk_t *jwk = NULL;
470 if (oidc_util_create_symmetric_key(r, argv[2], argc > 4 ? atoi(argv[4]) : 0,
471 argc > 3 ? argv[3] : NULL, FALSE, &jwk) == FALSE) {
472 fprintf(stderr, "oidc_util_create_symmetric_key failed");
473 return -1;
474 }
475
476 oidc_jose_error_t err;
477 char *s_json = NULL;
478 if (oidc_jwk_to_json(pool, jwk, &s_json, &err) == FALSE) {
479 fprintf(stderr, "oidc_jwk_to_json failed");
480 return -1;
481 }
482
483 cjose_err cjose_err;
484 int src_len = cjose_jwk_get_keysize(jwk->cjose_jwk, &cjose_err) / 8;
485 int enc_len = apr_base64_encode_len(src_len);
486 char *b64 = apr_palloc(r->pool, enc_len);
487 apr_base64_encode(b64,
488 (const char *) cjose_jwk_get_keydata(jwk->cjose_jwk, &cjose_err),
489 src_len);
490
491 fprintf(stdout, "\nJWK:\n%s\n\nbase64:\n%s\n\n", s_json, b64);
492
493 return 0;
494 }
495
hash_base64url(int argc,char ** argv,apr_pool_t * pool)496 int hash_base64url(int argc, char **argv, apr_pool_t *pool) {
497 if (argc <= 2)
498 return usage(argc, argv,
499 "hash_base64url <string> [algo] [base64url-decode-first]");
500
501 char *algo = argc > 3 ? argv[3] : "sha256";
502 int base64url_decode_first = argc > 4 ? (strcmp(argv[4], "yes") == 0) : 0;
503 char *output = NULL;
504
505 request_rec *r = request_setup(pool);
506
507 if (base64url_decode_first) {
508
509 uint8_t *bytes = NULL;
510 size_t outlen = 0;
511 cjose_err err;
512 if (cjose_base64url_decode(argv[2], strlen(argv[2]), &bytes, &outlen,
513 &err) == FALSE) {
514 fprintf(stderr, "cjose_base64_decode failed: %s", err.message);
515 return -1;
516 }
517 if (oidc_jose_hash_and_base64url_encode(r->pool, algo,
518 (const char *) bytes, outlen, &output) == FALSE) {
519 fprintf(stderr, "oidc_jose_hash_and_base64url_encode failed");
520 return -1;
521 }
522 } else {
523 if (oidc_util_hash_string_and_base64url_encode(r, algo, argv[2],
524 &output) == FALSE) {
525 fprintf(stderr,
526 "oidc_util_hash_string_and_base64url_encode failed");
527 return -1;
528 }
529 }
530
531 fprintf(stdout, "%s\n", output);
532
533 return 0;
534 }
535
timestamp(int argc,char ** argv,apr_pool_t * pool)536 int timestamp(int argc, char **argv, apr_pool_t *pool) {
537 if (argc <= 2)
538 return usage(argc, argv, "timestamp <seconds>");
539 long delta = strtol(argv[2], NULL, 10);
540 apr_time_t t1 = apr_time_now() + apr_time_from_sec(delta);
541 char *s = apr_psprintf(pool, "%" APR_TIME_T_FMT, t1);
542 fprintf(stderr, "timestamp (1) = %s\n", s);
543
544 apr_time_t t2;
545 sscanf(s, "%" APR_TIME_T_FMT, &t2);
546 fprintf(stderr, "timestamp (2) = %" APR_TIME_T_FMT "\n", t2);
547
548 char buf[APR_RFC822_DATE_LEN + 1];
549 apr_rfc822_date(buf, t2);
550 fprintf(stderr, "timestamp (3): %s (%" APR_TIME_T_FMT " secs from now)\n",
551 buf, apr_time_sec(t2 - apr_time_now()));
552
553 return 0;
554 }
555
uuid(int argc,char ** argv,apr_pool_t * pool)556 int uuid(int argc, char **argv, apr_pool_t *pool) {
557 char s_uuid[APR_UUID_FORMATTED_LENGTH + 1];
558 const unsigned long e = 1000000;
559 unsigned long n = 10000000;
560 unsigned long i = 0;
561
562 if (argc > 2)
563 n = atoi(argv[2]);
564
565 apr_hash_t *entries = apr_hash_make(pool);
566 apr_uuid_t *uuid;
567 while (i < n) {
568 uuid = (apr_uuid_t *) apr_pcalloc(pool, sizeof(apr_uuid_t));
569 apr_uuid_get(uuid);
570 if (apr_hash_get(entries, (const void *) uuid,
571 sizeof(apr_uuid_t)) != NULL) {
572 apr_uuid_format((char *) &s_uuid, uuid);
573 fprintf(stderr, "duplicate found: %s\n", s_uuid);
574 exit(-1);
575 } else {
576 apr_hash_set(entries, (const void *) uuid, sizeof(apr_uuid_t),
577 (const void *) 1);
578 }
579 i++;
580 if (i % e == 0)
581 fprintf(stderr, "\r %lu ", i / e);
582 }
583 fprintf(stderr, "\n");
584 return 0;
585 }
586
main(int argc,char ** argv,char ** env)587 int main(int argc, char **argv, char **env) {
588
589 if (argc <= 1)
590 return usage(argc, argv, NULL);
591
592 if (apr_app_initialize(&argc, (const char * const **) argv,
593 (const char * const **) env) != APR_SUCCESS) {
594 printf("apr_app_initialize failed\n");
595 return -1;
596 }
597
598 OpenSSL_add_all_algorithms();
599
600 apr_pool_t *pool = NULL;
601 apr_pool_create(&pool, NULL);
602
603 if (strcmp(argv[1], "sign") == 0)
604 return sign(argc, argv, pool);
605
606 if (strcmp(argv[1], "verify") == 0)
607 return verify(argc, argv, pool);
608
609 if (strcmp(argv[1], "decrypt") == 0)
610 return decrypt(argc, argv, pool);
611
612 if (strcmp(argv[1], "jwk2cert") == 0)
613 return jwk2cert(argc, argv, pool);
614
615 if (strcmp(argv[1], "key2jwk") == 0)
616 return key2jwk(argc, argv, pool);
617
618 if (strcmp(argv[1], "enckey") == 0)
619 return enckey(argc, argv, pool);
620
621 if (strcmp(argv[1], "hash_base64url") == 0)
622 return hash_base64url(argc, argv, pool);
623
624 if (strcmp(argv[1], "timestamp") == 0)
625 return timestamp(argc, argv, pool);
626
627 if (strcmp(argv[1], "uuid") == 0)
628 return uuid(argc, argv, pool);
629
630 apr_pool_destroy(pool);
631 apr_terminate();
632
633 return usage(argc, argv, NULL);
634 }
635