[pve-devel] [PATCH v2 u2f-server] initial release
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Apr 2 12:22:10 CEST 2019
Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
.gitignore | 7 +++
Makefile | 81 +++++++++++++++++++++++++
PVE/U2F.pm | 155 +++++++++++++++++++++++++++++++++++++++++++++++
U2F.xs | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
debian/changelog | 5 ++
debian/compat | 1 +
debian/control | 17 ++++++
debian/copyright | 16 +++++
debian/rules | 8 +++
9 files changed, 469 insertions(+)
create mode 100644 .gitignore
create mode 100644 Makefile
create mode 100644 PVE/U2F.pm
create mode 100644 U2F.xs
create mode 100644 debian/changelog
create mode 100644 debian/compat
create mode 100644 debian/control
create mode 100644 debian/copyright
create mode 100755 debian/rules
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9ef3233
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+build
+ppport.h
+U2F.so
+U2F.xsc
+*.deb
+*.1.pod
+*.1.gz
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..22b5020
--- /dev/null
+++ b/Makefile
@@ -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 at repo.proxmox.com -- upload --product pve --dist stretch --arch $(ARCH)
diff --git a/PVE/U2F.pm b/PVE/U2F.pm
new file mode 100644
index 0000000..acc9348
--- /dev/null
+++ b/PVE/U2F.pm
@@ -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 at proxmox.com>
+
+=cut
diff --git a/U2F.xs b/U2F.xs
new file mode 100644
index 0000000..2e167d2
--- /dev/null
+++ b/U2F.xs
@@ -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
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..1950d15
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+libpve-u2f-server-perl (1.0-1) unstable; urgency=low
+
+ * initial package
+
+ -- Proxmox Support Team <support at proxmox.com> Tue, 02 Apr 2019 10:45:19 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+10
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..ca09ba8
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,17 @@
+Source: libpve-u2f-server-perl
+Section: perl
+Priority: optional
+Maintainer: Proxmox Support Team <support at 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.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..ae43835
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,16 @@
+Copyright (C) 2019 Proxmox Server Solutions GmbH
+
+This software is written by Proxmox Server Solutions GmbH <support at 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/>.
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..218df65
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,8 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+%:
+ dh $@
--
2.11.0
More information about the pve-devel
mailing list