--- /dev/null
+/u2f-client-demo*
+/u2f-server-demo*
+moc_*
+*.o
+*.obj
+*.bak
+*~
+Makefile*
+*.kdev4
+.kdev*
--- /dev/null
+Copyright (c) 2014 Konrad Rosenbaum <konrad@silmor.de>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
--- /dev/null
+README for U2F Demo
+====================
+
+(c) Konrad Rosenbaum <konrad@silmor.de>, 2015
+this demo is protected under the MIT license, see COPYING.MIT for details
+
+
+This is some demo code to show how to integrate FIDO U2F into your own code.
+Apart from this it does not have a useful purpose.
+
+
+Pre-Requisites and Building
+----------------------------
+
+You need for the Qt based client/server:
+* GIT to retrieve the U2F libs
+* PKG-Config
+* a working C/C++ compiler (e.g. gcc, clang)
+* libu2f-host (https://github.com/Yubico/libu2f-host.git), which itself
+ requires:
+ - GNU autotools
+ - GTK-doc (optional for building documentation)
+ - HIDAPI (use HIDAPI-hidraw under Linux!)
+* libu2f-server (https://github.com/Yubico/libu2f-server.git), which itsel
+ requires:
+ - GNU autotools
+ - GTK-doc (optional for building documentation)
+ - OpenSSL (for cryptography)
+* Qt (>=5.3) for the graphical server and client demo
+
+For the PHP based server demo:
+* PHP >= 5.x
+ - with the OpenSSL extension enabled (the web server does not need to use HTTPS)
+
+Compile and install libu2f-host and libu2f-server first - see the README files
+of those libraries for details.
+
+Call "qmake && make" in the main directory - normally it should work out of the
+box as long as qmake is in the $PATH. If pkg-config cannot find the two libu2f
+libraries, then you may have to set the PKG_CONFIG_PATH variable to point to
+the directory where the *.pc files for libu2f-* are installed (per default
+/usr/local/lib/pkgconfig - if you set another --prefix before installing them
+it is $PREFIX/lib/pkgconfig).
+
+The PHP demo does not need to be built: just copy the directory to a path that can
+be served by a PHP-enabled web server.
+
+Using the Demo Server and Client
+---------------------------------
+
+
+Using the Web Demo
+-------------------
+
+TBD
\ No newline at end of file
--- /dev/null
+#U2F Demo Client
+
+# make it a normal GUI app, so we can interact
+TEMPLATE = app
+TARGET = u2f-client-demo
+DESTDIR = ..
+QT += widgets network
+
+# make sure u2f-host lib is linked - needed for USB-to-token-access
+CONFIG += link_pkgconfig
+PKGCONFIG += u2f-host
+
+# source files...
+SOURCES += clientmain.cpp
+
--- /dev/null
+#include <QApplication>
+#include <QPushButton>
+
+
+int main(int ac,char**av)
+{
+ QApplication app(ac,av);
+ QPushButton p("hello");
+ p.show();
+ return app.exec();
+}
\ No newline at end of file
--- /dev/null
+#ifndef U2F_QT_DEMO_CONSTANTS_H
+#define U2F_QT_DEMO_CONSTANTS_H
+
+//network TCP port to be used for the demo protocol
+#define DEMOPORT 29682
+
+//URI scheme for the demo protocol
+#define DEMOSCHEME "demo"
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "connection.h"
+
+#include <QTcpSocket>
+
+DConnection::DConnection(QTcpSocket*sock, QObject* parent): QObject(parent), msocket(sock)
+{
+}
+
+DConnection::State DConnection::state() const
+{
+ //unconnected?
+ if(msocket==nullptr || !msocket->isOpen())
+ return Invalid;
+ //we are connected, check details
+ //are we authenticating?
+ if(mkeys.size()>0)return Authenticating;
+ //done authenticating?
+ if(!muser.isEmpty())return Authenticated;
+ //not authenticated yet
+ return Connected;
+}
--- /dev/null
+#ifndef DEMO_CONNECTION_H
+#define DEMO_CONNECTION_H
+
+
+#include <QObject>
+#include <QStringList>
+
+class QTcpSocket;
+
+class DConnection:public QObject
+{
+ Q_OBJECT
+public:
+ explicit DConnection(QTcpSocket*,QObject* parent = 0);
+
+ ///Represents the current state of this connection.
+ enum State {
+ ///The connection is invalid or disconnected.
+ Invalid,
+ ///It is connected, but not authenticated.
+ Connected,
+ ///It is currently authenticating the user.
+ ///When finished it will either revert to Connected (failed)
+ ///or advance to Authenticated (success).
+ Authenticating,
+ ///Authentication was successful. The user may request data
+ ///or change his/her token associations.
+ Authenticated,
+ };
+ State state()const;
+ QString userName()const{return muser;}
+private:
+ QTcpSocket*msocket;
+ QString muser;
+ QStringList mkeys;
+};
+
+#endif
--- /dev/null
+#U2F Demo Server
+
+# make it a normal GUI app, so we can see what is happening
+TEMPLATE = app
+TARGET = u2f-server-demo
+DESTDIR = ..
+QT += widgets network
+
+# allow C++11 keywords
+CONFIG += c++11
+
+# make sure the u2f-server lib is linked: needed for the crypto
+CONFIG += link_pkgconfig
+PKGCONFIG += u2f-server
+
+# source files
+SOURCES += servermain.cpp session.cpp connection.cpp
+HEADERS += servermain.h session.h connection.h
+
--- /dev/null
+#include "servermain.h"
+#include "session.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QDialog>
+#include <QHostInfo>
+#include <QInputDialog>
+#include <QMenu>
+#include <QMenuBar>
+#include <QPushButton>
+#include <QStatusBar>
+
+void DMainWindow::choseHost()
+{
+ QStringList hosts;
+ hosts<<"localhost"<<QHostInfo::localHostName();
+ bool ok=false;
+ const QString host=QInputDialog::getItem(0,"Chose Host","Please chose the host to use:",hosts,0,false,&ok);
+ if(!ok || host.isEmpty()){
+ qApp->quit();
+ return;
+ }
+ DSession*sess;
+ if(host==hosts[0])
+ sess=DSession::createLocalSession();
+ else
+ sess=DSession::createDefaultSession();
+ minstance=new DMainWindow(sess);
+ minstance->show();
+}
+
+QPointer<DMainWindow> DMainWindow::minstance;
+
+DMainWindow::DMainWindow(DSession*s)
+ :msession(s)
+{
+ setWindowTitle("Demo Server: "+s->hostname());
+ statusBar()->setSizeGripEnabled(true);
+
+ QMenu*m=menuBar()->addMenu("Session");
+ m->addAction("Quit",qApp,SLOT(quit()));
+}
+
+
+
+int main(int ac,char**av)
+{
+ QApplication app(ac,av);
+ DMainWindow::choseHost();
+ return app.exec();
+}
\ No newline at end of file
--- /dev/null
+#ifndef DEMO_SERVERMAIN_H
+#define DEMO_SERVERMAIN_H
+
+#include <QMainWindow>
+#include <QPointer>
+
+class DSession;
+
+class DMainWindow:public QMainWindow
+{
+ Q_OBJECT
+public:
+ static void choseHost();
+ static DMainWindow* instance(){return minstance;}
+private:
+ DMainWindow(DSession*);
+
+ static QPointer<DMainWindow>minstance;
+ QPointer<DSession>msession;
+};
+
+
+#endif
--- /dev/null
+#include "session.h"
+
+#include <QHostInfo>
+#include <QTcpServer>
+#include <QTcpSocket>
+
+#include "connection.h"
+#include "../client/democonsts.h"
+
+DSession::DSession(QHostAddress addr, QString host): QObject(), mhost(host)
+{
+ mserver=new QTcpServer(this);
+ mserver->listen(addr,DEMOPORT);
+ connect(mserver,SIGNAL(newConnection()),this,SLOT(handleConnect()));
+}
+
+bool DSession::isValid() const
+{
+ return mserver!=nullptr && mserver->isListening();
+}
+
+QString DSession::url() const
+{
+ if(isValid())
+ return QString(DEMOSCHEME "://%1").arg(mhost);
+ else
+ return QString();
+}
+
+
+void DSession::handleConnect()
+{
+ while(mserver->hasPendingConnections()){
+ QTcpSocket*sock=mserver->nextPendingConnection();
+ if(sock)
+ emit newConnection(new DConnection(sock));
+ }
+}
+
+DSession* DSession::createLocalSession()
+{
+ return new DSession(QHostAddress::LocalHost, "localhost");
+}
+
+DSession* DSession::createDefaultSession()
+{
+ QString host=QHostInfo::localHostName();
+ if(!host.contains('.'))
+ host+="."+QHostInfo::localDomainName();
+ return new DSession(QHostAddress::Any, host);
+}
--- /dev/null
+#ifndef DEMO_SESSION_H
+#define DEMO_SESSION_H
+
+#include <QHostAddress>
+#include <QObject>
+#include <QString>
+
+class QTcpServer;
+class QTcpSocket;
+class DConnection;
+
+
+///This class represents the server session.
+///The server session holds all important data and main objects together:
+/// the server socket, URL, data directory, etc.
+class DSession:public QObject
+{
+ Q_OBJECT
+public:
+ ///returns true if the session was correctly constructed
+ bool isValid()const;
+
+ ///returns the host name of the session
+ QString hostname()const{return mhost;}
+ ///returns the URL the client needs
+ QString url()const;
+
+ /// Creates a session for localhost
+ static DSession* createLocalSession();
+ /// Creates a session for the default hostname
+ static DSession* createDefaultSession();
+
+signals:
+ ///emitted when a new connection is established
+ void newConnection(DConnection*);
+
+private slots:
+ ///handles TCP connections
+ void handleConnect();
+
+private:
+ ///creates a new session, called by create*Session()
+ DSession(QHostAddress addr, QString host);
+
+
+ QTcpServer*mserver;
+ QString mhost;
+};
+
+
+#endif
--- /dev/null
+TEMPLATE=subdirs
+SUBDIRS = server client