mirror of
https://git.proxmox.com/git/libpve-u2f-server-perl
synced 2025-08-15 23:03:59 +00:00

One *mustn't* treat the publicKey as common string, it it's effectively binary data, and thus can contain 0 at any position. If we pass it to perl via setpv (PV being string), things may get cutoff and a wrong pubKey may get saved, thus locking an user out as it cannot get verified anymore! Use a simple & fast base64 encoding immediately at the source, using the correct keylength (U2FS_PUBLIC_KEY_LEN) we can use that. Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
184 lines
3.7 KiB
Plaintext
184 lines
3.7 KiB
Plaintext
#define PERL_NO_GET_CONTEXT
|
|
#include "EXTERN.h"
|
|
#include "perl.h"
|
|
#include "XSUB.h"
|
|
|
|
#include "ppport.h"
|
|
|
|
#include <u2f-server.h>
|
|
|
|
#include "base64.h"
|
|
|
|
MODULE = PVE::U2F PACKAGE = PVE::U2F
|
|
|
|
#// Context creation and destruction
|
|
|
|
void
|
|
do_global_init()
|
|
CODE:
|
|
u2fs_global_init(0);
|
|
|
|
void
|
|
do_global_done()
|
|
CODE:
|
|
u2fs_global_done();
|
|
|
|
SV*
|
|
new_impl()
|
|
CODE:
|
|
u2fs_ctx_t *ctx = NULL;
|
|
if (u2fs_init(&ctx) != U2FS_OK) {
|
|
RETVAL = &PL_sv_undef;
|
|
} else {
|
|
RETVAL = newSVpv((char*)&ctx, sizeof(ctx));
|
|
}
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
void
|
|
done_impl(ctx)
|
|
SV *ctx
|
|
CODE:
|
|
if (ctx == &PL_sv_undef) {
|
|
croak("u2fs xs: double free");
|
|
} else {
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
u2fs_done(*pctx);
|
|
sv_setsv(ctx, &PL_sv_undef);
|
|
}
|
|
|
|
#// Context initialization before registration/authentication
|
|
|
|
int
|
|
set_origin_impl(ctx, origin)
|
|
SV *ctx
|
|
char *origin
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
RETVAL = u2fs_set_origin(*pctx, origin);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
set_appid_impl(ctx, appid)
|
|
SV *ctx
|
|
char *appid
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
RETVAL = u2fs_set_appid(*pctx, appid);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
set_challenge_impl(ctx, challenge)
|
|
SV *ctx
|
|
char *challenge
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
RETVAL = u2fs_set_challenge(*pctx, challenge);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
set_keyHandle_impl(ctx, keyHandle)
|
|
SV *ctx
|
|
char *keyHandle
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
RETVAL = u2fs_set_keyHandle(*pctx, keyHandle);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
set_publicKey_impl(ctx, publicKey)
|
|
SV *ctx
|
|
unsigned char *publicKey
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
RETVAL = u2fs_set_publicKey(*pctx, publicKey);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
#// Registration functions
|
|
|
|
int
|
|
registration_challenge_impl(ctx, outref=&PL_sv_undef)
|
|
SV *ctx
|
|
SV *outref
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
char *output = NULL;
|
|
u2fs_rc rc = u2fs_registration_challenge(*pctx, &output);
|
|
if (rc == U2FS_OK) {
|
|
sv_setpv(outref, output);
|
|
}
|
|
RETVAL = rc;
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
registration_verify_impl(ctx, response, kh=&PL_sv_undef, pk=&PL_sv_undef)
|
|
SV *ctx
|
|
char *response
|
|
SV *kh
|
|
SV *pk
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
u2fs_reg_res_t *result = NULL;
|
|
u2fs_rc rc = u2fs_registration_verify(*pctx, response, &result);
|
|
if (rc == U2FS_OK) {
|
|
const char *keyHandle = u2fs_get_registration_keyHandle(result);
|
|
const char *publicKey_raw = u2fs_get_registration_publicKey(result);
|
|
char *publicKey = base64(publicKey_raw, U2FS_PUBLIC_KEY_LEN);
|
|
sv_setpv(kh, keyHandle);
|
|
sv_setpv(pk, publicKey);
|
|
free(publicKey); publicKey = NULL;
|
|
u2fs_free_reg_res(result);
|
|
}
|
|
RETVAL = rc;
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
#// Authentication functions
|
|
int
|
|
auth_challenge_impl(ctx, outref=&PL_sv_undef)
|
|
SV *ctx
|
|
SV *outref
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
char *output = NULL;
|
|
u2fs_rc rc = u2fs_authentication_challenge(*pctx, &output);
|
|
if (rc == U2FS_OK) {
|
|
sv_setpv(outref, output);
|
|
}
|
|
RETVAL = rc;
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
int
|
|
auth_verify_impl(ctx, response, verified=&PL_sv_undef, counter=&PL_sv_undef, presence=&PL_sv_undef)
|
|
SV *ctx
|
|
char *response
|
|
SV *verified
|
|
SV *counter
|
|
SV *presence
|
|
CODE:
|
|
u2fs_ctx_t **pctx = (u2fs_ctx_t**)SvPV_nolen(ctx);
|
|
u2fs_auth_res_t *result = NULL;
|
|
u2fs_rc rc = u2fs_authentication_verify(*pctx, response, &result);
|
|
if (rc == U2FS_OK) {
|
|
u2fs_rc a_verified = 0;
|
|
uint32_t a_count = 0;
|
|
uint8_t a_presence = 0;
|
|
rc = u2fs_get_authentication_result(result, &a_verified, &a_count, &a_presence);
|
|
if (rc == U2FS_OK) {
|
|
sv_setiv(verified, a_verified);
|
|
sv_setuv(counter, a_count);
|
|
sv_setuv(presence, a_presence);
|
|
}
|
|
u2fs_free_auth_res(result);
|
|
}
|
|
RETVAL = rc;
|
|
OUTPUT:
|
|
RETVAL
|