From: Michael Tremer Date: Sat, 21 Jun 2025 12:38:53 +0000 (+0000) Subject: jwt: Add some simple functions to parse JWTs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c3cd874893251a63667f98ddc2d37f988e0faba;p=pakfire.git jwt: Add some simple functions to parse JWTs Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 36c22e02..4ab7bfd1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -240,6 +240,8 @@ libpakfire_la_SOURCES = \ src/pakfire/job.h \ src/pakfire/json.c \ src/pakfire/json.h \ + src/pakfire/jwt.c \ + src/pakfire/jwt.h \ src/pakfire/key.c \ src/pakfire/key.h \ src/pakfire/linter.c \ diff --git a/src/pakfire/jwt.c b/src/pakfire/jwt.c new file mode 100644 index 00000000..21444ddd --- /dev/null +++ b/src/pakfire/jwt.c @@ -0,0 +1,122 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2025 Pakfire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include + +#include + +#include +#include +#include +#include + +static int pakfire_jwt_find_payload(const char* token, const char** payload, size_t* length) { + const char* p = NULL; + size_t l = 0; + + // Walk through the token character by character... + while (token && *token) { + switch (*token++) { + case '.': + // If we have found the first dot, the payload starts right after it + if (!p) { + p = token; + + // If we have hit the second dot, we have found the end of the payload + } else { + // Determine the length + l = token - p - 1; + + // Terminate the loop + token = NULL; + } + break; + } + } + + // If the payload is empty, we return an error + if (!p || !l) + return -EINVAL; + + // Return the values + *payload = p; + *length = l; + + return 0; +} + +static int pakfire_jwt_decode_payload(char** payload, size_t* length, const char* token) { + const char* p = NULL; + size_t l = 0; + int r; + + // Find the payload + r = pakfire_jwt_find_payload(token, &p, &l); + if (r < 0) + return r; + + // Decode the payload + return pakfire_b64decode((unsigned char**)payload, length, p, l); +} + +int pakfire_jwt_payload(struct pakfire_ctx* ctx, const char* token, struct json_object** payload) { + char* p = NULL; + size_t l = 0; + int r; + + // Decode the payload + r = pakfire_jwt_decode_payload(&p, &l, token); + if (r < 0) { + ERROR(ctx, "Failed to decode the JWT payload: %s\n", strerror(-r)); + return r; + } + + // Parse the JSON + *payload = pakfire_json_parse(ctx, p, l); + if (!*payload) + return -EINVAL; + + return 0; +} + +time_t pakfire_jwt_expires_at(struct pakfire_ctx* ctx, const char* token) { + struct json_object* payload = NULL; + time_t expires_at = -1; + int r; + + // Parse the payload + r = pakfire_jwt_payload(ctx, token, &payload); + if (r < 0) + goto ERROR; + + // Fetch the expiry time + r = pakfire_json_get_int64(payload, "exp", &expires_at); + if (r < 0) + goto ERROR; + + // Return the expiry time + r = expires_at; + +ERROR: + if (payload) + json_object_put(payload); + + return r; +} diff --git a/src/pakfire/jwt.h b/src/pakfire/jwt.h new file mode 100644 index 00000000..1d4f6f27 --- /dev/null +++ b/src/pakfire/jwt.h @@ -0,0 +1,33 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2025 Pakfire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef PAKFIRE_JWT_H +#define PAKFIRE_JWT_H + +#include + +#include + +int pakfire_jwt_payload(struct pakfire_ctx* ctx, + const char* token, struct json_object** payload); + +time_t pakfire_jwt_expires_at(struct pakfire_ctx* ctx, const char* token); + +#endif /* PAKFIRE_JWT_H */