[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