mirror of
https://git.proxmox.com/git/libpve-u2f-server-perl
synced 2025-10-04 07:02:46 +00:00
initial release
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
commit
b8adb2d581
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
build
|
||||
ppport.h
|
||||
U2F.so
|
||||
U2F.xsc
|
||||
*.deb
|
||||
*.1.pod
|
||||
*.1.gz
|
81
Makefile
Normal file
81
Makefile
Normal file
@ -0,0 +1,81 @@
|
||||
include /usr/share/dpkg/pkg-info.mk
|
||||
include /usr/share/dpkg/architecture.mk
|
||||
|
||||
PACKAGE=libpve-u2f-server-perl
|
||||
|
||||
BUILDSRC := $(PACKAGE)-$(DEB_VERSION_UPSTREAM_REVISION)
|
||||
|
||||
DESTDIR=
|
||||
PREFIX=/usr
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
DOCDIR=$(PREFIX)/share/doc/$(PACKAGE)
|
||||
PERLDIR=$(PREFIX)/share/perl5
|
||||
|
||||
PERL_ARCHLIB != perl -MConfig -e 'print $$Config{archlib};'
|
||||
PERL_INSTALLVENDORARCH != perl -MConfig -e 'print $$Config{installvendorarch};'
|
||||
PERL_APIVER != perl -MConfig -e 'print $$Config{debian_abi}//$$Config{version};'
|
||||
PERL_CC != perl -MConfig -e 'print $$Config{cc};'
|
||||
PERLSODIR=$(PERL_INSTALLVENDORARCH)/auto
|
||||
CFLAGS := -shared -fPIC -O2 -Werror -Wtype-limits -Wall -Wl,-z,relro \
|
||||
-D_FORTIFY_SOURCE=2 -I$(PERL_ARCHLIB)/CORE -DXS_VERSION=\"1.0\"
|
||||
|
||||
CFLAGS += `pkg-config --cflags u2f-server`
|
||||
LIBS += `pkg-config --libs u2f-server`
|
||||
|
||||
DEB=$(PACKAGE)_$(DEB_VERSION_UPSTREAM_REVISION)_$(DEB_BUILD_ARCH).deb
|
||||
DSC=$(PACKAGE)_$(DEB_VERSION_UPSTREAM_REVISION).dsc
|
||||
|
||||
GITVERSION:=$(shell git rev-parse HEAD)
|
||||
|
||||
all:
|
||||
|
||||
ppport.h:
|
||||
perl -MDevel::PPPort -e 'Devel::PPPort::WriteFile();'
|
||||
|
||||
U2F.c: U2F.xs
|
||||
xsubpp U2F.xs > U2F.xsc
|
||||
mv U2F.xsc U2F.c
|
||||
|
||||
U2F.so: U2F.c ppport.h
|
||||
$(PERL_CC) $(CFLAGS) -o U2F.so U2F.c $(LIBS)
|
||||
|
||||
.PHONY: dinstall
|
||||
dinstall: deb
|
||||
dpkg -i $(DEB)
|
||||
|
||||
.PHONY: install
|
||||
install: PVE/U2F.pm U2F.so
|
||||
install -D -m 0644 PVE/U2F.pm $(DESTDIR)$(PERLDIR)/PVE/U2F.pm
|
||||
install -D -m 0644 -s U2F.so $(DESTDIR)$(PERLSODIR)/PVE/U2F/U2F.so
|
||||
|
||||
.PHONY: $(BUILDSRC)
|
||||
$(BUILDSRC):
|
||||
rm -rf $(BUILDSRC)
|
||||
mkdir $(BUILDSRC)
|
||||
rsync -a debian Makefile PVE U2F.xs $(BUILDSRC)/
|
||||
echo "git clone git://git.proxmox.com/git/libpve-u2f-server-perl.git\\ngit checkout $(GITVERSION)" > $(BUILDSRC)/debian/SOURCE
|
||||
|
||||
.PHONY: deb
|
||||
deb: $(DEB)
|
||||
$(DEB): $(BUILDSRC)
|
||||
cd $(BUILDSRC); dpkg-buildpackage -b -us -uc
|
||||
lintian $(DEB)
|
||||
|
||||
.PHONY: dsc
|
||||
dsc: $(DSC)
|
||||
$(DSC): $(BUILDSRC)
|
||||
cd $(BUILDSRC); dpkg-buildpackage -S -us -uc -d -nc
|
||||
lintian $(DSC)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *~ build *.deb *.changes *.buildinfo *.dsc *.tar.gz
|
||||
find . -name '*~' -exec rm {} ';'
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
|
||||
|
||||
.PHONY: upload
|
||||
upload: $$DEB)
|
||||
tar cf - $(DEB) | ssh repoman@repo.proxmox.com -- upload --product pve --dist stretch --arch $(ARCH)
|
155
PVE/U2F.pm
Normal file
155
PVE/U2F.pm
Normal file
@ -0,0 +1,155 @@
|
||||
package PVE::U2F;
|
||||
|
||||
use 5.024000;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
# Items to export into callers namespace by default. Note: do not export
|
||||
# names by default without a very good reason. Use EXPORT_OK instead.
|
||||
# Do not simply export all your public functions/methods/constants.
|
||||
|
||||
# This allows declaration use PVE::U2F::XS ':all';
|
||||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = ( 'all' => [] );
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||
our @EXPORT = ();
|
||||
our $VERSION = '1.0';
|
||||
|
||||
require XSLoader;
|
||||
XSLoader::load('PVE::U2F', $VERSION);
|
||||
|
||||
#### Context creation
|
||||
|
||||
my $global_init = 0;
|
||||
sub new($) {
|
||||
my ($class) = @_;
|
||||
if (!$global_init) {
|
||||
$global_init = 1;
|
||||
do_global_init();
|
||||
}
|
||||
if (my $lib = new_impl()) {
|
||||
return bless { ctx => $lib }, $class;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my ($self) = @_;
|
||||
done_impl($self->{ctx});
|
||||
}
|
||||
|
||||
#### Error handling
|
||||
|
||||
my @errcodes = (
|
||||
qw(memory json base64 crypto origin challenge signature format)
|
||||
);
|
||||
sub checkrc($) {
|
||||
my ($rc) = @_;
|
||||
return if $rc == 0;
|
||||
die "u2fs: $errcodes[-$rc-1] error\n" if $rc < 0 && $rc >= -8;
|
||||
die "u2fs: unknown error\n";
|
||||
}
|
||||
|
||||
#### Context initialization
|
||||
|
||||
sub origin($) { return $_[0]->{origin}; }
|
||||
sub set_origin($$) {
|
||||
my ($self, $origin) = @_;
|
||||
checkrc(set_origin_impl($self->{ctx}, $origin));
|
||||
return $self->{origin} = $origin;
|
||||
}
|
||||
|
||||
sub appid($) { return $_[0]->{appid}; }
|
||||
sub set_appid($$) {
|
||||
my ($self, $appid) = @_;
|
||||
checkrc(set_appid_impl($self->{ctx}, $appid));
|
||||
return $self->{appid} = $appid;
|
||||
}
|
||||
|
||||
sub challenge($) { return $_[0]->{challenge}; }
|
||||
sub set_challenge($$) {
|
||||
my ($self, $challenge) = @_;
|
||||
checkrc(set_challenge_impl($self->{ctx}, $challenge));
|
||||
return $self->{challenge} = $challenge;
|
||||
}
|
||||
|
||||
sub keyHandle($) { return $_[0]->{keyHandle}; }
|
||||
sub set_keyHandle($$) {
|
||||
my ($self, $keyHandle) = @_;
|
||||
checkrc(set_keyHandle_impl($self->{ctx}, $keyHandle));
|
||||
return $self->{keyHandle} = $keyHandle;
|
||||
}
|
||||
|
||||
sub publicKey($) { return $_[0]->{publicKey}; }
|
||||
sub set_publicKey($$) {
|
||||
my ($self, $publicKey) = @_;
|
||||
checkrc(set_publicKey_impl($self->{ctx}, $publicKey));
|
||||
return $self->{publicKey} = $publicKey;
|
||||
}
|
||||
|
||||
#### Registration
|
||||
|
||||
sub registration_challenge($) {
|
||||
my ($self) = @_;
|
||||
checkrc(registration_challenge_impl($self->{ctx}, my $challenge));
|
||||
return $challenge;
|
||||
}
|
||||
|
||||
sub registration_verify($$) {
|
||||
my ($self, $response) = @_;
|
||||
checkrc(registration_verify_impl($self->{ctx}, $response, my $kh, my $pk));
|
||||
return ($kh, $pk);
|
||||
}
|
||||
|
||||
#### Authentication
|
||||
|
||||
sub auth_challenge($) {
|
||||
my ($self) = @_;
|
||||
checkrc(auth_challenge_impl($self->{ctx}, my $challenge));
|
||||
return $challenge;
|
||||
}
|
||||
|
||||
sub auth_verify($$) {
|
||||
my ($self, $response) = @_;
|
||||
checkrc(auth_verify_impl($self->{ctx}, $response,
|
||||
my $verified,
|
||||
my $counter,
|
||||
my $presence));
|
||||
checkrc($verified);
|
||||
return wantarray ? ($counter, $presence) : 1;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
PVE::U2F - Perl bindings for libu2f-server
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use PVE::U2F;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Perl bindings for libu2f-server
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
None by default.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
TODO
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Proxmox Server Solutions GmbH <support@proxmox.com>
|
||||
|
||||
=cut
|
179
U2F.xs
Normal file
179
U2F.xs
Normal file
@ -0,0 +1,179 @@
|
||||
#define PERL_NO_GET_CONTEXT
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
|
||||
#include "ppport.h"
|
||||
|
||||
#include <u2f-server.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 = u2fs_get_registration_publicKey(result);
|
||||
sv_setpv(kh, keyHandle);
|
||||
sv_setpv(pk, publicKey);
|
||||
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
|
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
libpve-u2f-server-perl (1.0-1) unstable; urgency=low
|
||||
|
||||
* initial package
|
||||
|
||||
-- Proxmox Support Team <support@proxmox.com> Tue, 02 Apr 2019 10:45:19 +0200
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
||||
10
|
17
debian/control
vendored
Normal file
17
debian/control
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
Source: libpve-u2f-server-perl
|
||||
Section: perl
|
||||
Priority: optional
|
||||
Maintainer: Proxmox Support Team <support@proxmox.com>
|
||||
Build-Depends: debhelper (>= 10~),
|
||||
libu2f-server-dev,
|
||||
Standards-Version: 3.9.8
|
||||
Homepage: https://www.proxmox.com/
|
||||
|
||||
Package: libpve-u2f-server-perl
|
||||
Architecture: any
|
||||
Depends: perl (>= 5.20.1-5),
|
||||
${misc:Depends},
|
||||
${perl:Depends},
|
||||
${shlibs:Depends},
|
||||
Description: Perl bindings for libu2f-server
|
||||
This package contains libu2f-server perl binding used by Proxmox VE.
|
16
debian/copyright
vendored
Normal file
16
debian/copyright
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Copyright (C) 2019 Proxmox Server Solutions GmbH
|
||||
|
||||
This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
8
debian/rules
vendored
Executable file
8
debian/rules
vendored
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
%:
|
||||
dh $@
|
Loading…
Reference in New Issue
Block a user