initial src layout master
authorKonrad Rosenbaum <konrad@silmor.de>
Mon, 2 Feb 2015 07:09:31 +0000 (08:09 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Mon, 2 Feb 2015 07:09:31 +0000 (08:09 +0100)
14 files changed:
.gitignore [new file with mode: 0644]
COPYING.MIT [new file with mode: 0644]
README [new file with mode: 0644]
client/client.pro [new file with mode: 0644]
client/clientmain.cpp [new file with mode: 0644]
client/democonsts.h [new file with mode: 0644]
server/connection.cpp [new file with mode: 0644]
server/connection.h [new file with mode: 0644]
server/server.pro [new file with mode: 0644]
server/servermain.cpp [new file with mode: 0644]
server/servermain.h [new file with mode: 0644]
server/session.cpp [new file with mode: 0644]
server/session.h [new file with mode: 0644]
u2f-demo.pro [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..7643b02
--- /dev/null
@@ -0,0 +1,10 @@
+/u2f-client-demo*
+/u2f-server-demo*
+moc_*
+*.o
+*.obj
+*.bak
+*~
+Makefile*
+*.kdev4
+.kdev*
diff --git a/COPYING.MIT b/COPYING.MIT
new file mode 100644 (file)
index 0000000..bca296b
--- /dev/null
@@ -0,0 +1,19 @@
+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
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..263f127
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+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
diff --git a/client/client.pro b/client/client.pro
new file mode 100644 (file)
index 0000000..a9e9cb3
--- /dev/null
@@ -0,0 +1,15 @@
+#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
+
diff --git a/client/clientmain.cpp b/client/clientmain.cpp
new file mode 100644 (file)
index 0000000..5119b5a
--- /dev/null
@@ -0,0 +1,11 @@
+#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
diff --git a/client/democonsts.h b/client/democonsts.h
new file mode 100644 (file)
index 0000000..bb0b6ee
--- /dev/null
@@ -0,0 +1,10 @@
+#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
diff --git a/server/connection.cpp b/server/connection.cpp
new file mode 100644 (file)
index 0000000..4985d87
--- /dev/null
@@ -0,0 +1,21 @@
+#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;
+}
diff --git a/server/connection.h b/server/connection.h
new file mode 100644 (file)
index 0000000..805da56
--- /dev/null
@@ -0,0 +1,38 @@
+#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
diff --git a/server/server.pro b/server/server.pro
new file mode 100644 (file)
index 0000000..5820ed6
--- /dev/null
@@ -0,0 +1,19 @@
+#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 
+
diff --git a/server/servermain.cpp b/server/servermain.cpp
new file mode 100644 (file)
index 0000000..59793c7
--- /dev/null
@@ -0,0 +1,52 @@
+#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
diff --git a/server/servermain.h b/server/servermain.h
new file mode 100644 (file)
index 0000000..628f262
--- /dev/null
@@ -0,0 +1,23 @@
+#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
diff --git a/server/session.cpp b/server/session.cpp
new file mode 100644 (file)
index 0000000..d38fcbd
--- /dev/null
@@ -0,0 +1,51 @@
+#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);
+}
diff --git a/server/session.h b/server/session.h
new file mode 100644 (file)
index 0000000..502ea42
--- /dev/null
@@ -0,0 +1,51 @@
+#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
diff --git a/u2f-demo.pro b/u2f-demo.pro
new file mode 100644 (file)
index 0000000..f3cf3d8
--- /dev/null
@@ -0,0 +1,2 @@
+TEMPLATE=subdirs
+SUBDIRS = server client