qca/include/QtCrypto/qca_securelayer.h
Justin Karneges 93b936d881 update tls/sasl api
svn path=/trunk/kdesupport/qca/; revision=440609
2005-07-31 01:27:27 +00:00

505 lines
14 KiB
C++

/*
* qca_securelayer.h - Qt Cryptographic Architecture
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef QCA_SECURELAYER_H
#define QCA_SECURELAYER_H
#include <QObject>
#include "qca_core.h"
#include "qca_publickey.h"
#include "qca_cert.h"
namespace QCA
{
/**
* Specify the lower-bound for acceptable TLS/SASL security layers
*/
enum SecurityLevel
{
SL_None, ///< indicates that no security is ok
SL_Integrity, ///< must at least get integrity protection
SL_Export, ///< must be export level bits or more
SL_Baseline, ///< must be 128 bit or more
SL_High, ///< must be more than 128 bit
SL_Highest ///< SL_High or max possible, whichever is greater
};
// generic interface to a security layer
class QCA_EXPORT SecureLayer : public QObject
{
Q_OBJECT
public:
SecureLayer(QObject *parent = 0);
virtual bool isClosable() const;
virtual int bytesAvailable() const = 0;
virtual int bytesOutgoingAvailable() const = 0;
virtual void close();
// plain (application side)
virtual void write(const QByteArray &a) = 0;
virtual QByteArray read() = 0;
// encoded (network side)
virtual void writeIncoming(const QByteArray &a) = 0;
virtual QByteArray readOutgoing(int *plainBytes = 0) = 0;
virtual QByteArray readUnprocessed();
signals:
void readyRead();
void readyReadOutgoing();
void closed();
void error();
};
class QCA_EXPORT TLS : public SecureLayer, public Algorithm
{
Q_OBJECT
public:
enum Mode
{
Stream,
Datagram
};
enum Version
{
TLS_v1,
SSL_v3,
SSL_v2,
DTLS_v1
};
enum Error
{
ErrorInit, ///< problem starting up TLS
ErrorHandshake, ///< problem during the negotiation
ErrorCrypt ///< problem at anytime after
};
enum IdentityResult
{
Valid, ///< identity is verified
HostMismatch, ///< valid cert provided, but wrong owner
InvalidCertificate, ///< invalid cert
NoCertificate ///< identity unknown
};
TLS(QObject *parent = 0, const QString &provider = QString());
TLS(Mode mode, QObject *parent = 0, const QString &provider = QString());
~TLS();
void reset();
static QStringList supportedCipherSuites(Mode mode = Stream, const QString &provider = QString());
void setCertificate(const CertificateChain &cert, const PrivateKey &key);
void setTrustedCertificates(const CertificateCollection &trusted);
void setConstraints(SecurityLevel s);
void setConstraints(int minSSF, int maxSSF);
void setConstraints(const QStringList &cipherSuiteList);
static bool canCompress(Mode mode = Stream, const QString &provider = QString());
void setCompressionEnabled(bool b);
void startClient(const QString &host = QString());
void startServer();
bool isHandshaken() const;
bool isCompressed() const;
Version version() const;
QString cipherSuite() const;
int cipherBits() const;
int cipherMaxBits() const;
Error errorCode() const;
IdentityResult peerIdentityResult() const;
Validity peerCertificateValidity() const;
CertificateChain localCertificateChain() const;
CertificateChain peerCertificateChain() const;
// reimplemented
virtual bool isClosable() const;
virtual int bytesAvailable() const;
virtual int bytesOutgoingAvailable() const;
virtual void close();
virtual void write(const QByteArray &a);
virtual QByteArray read();
virtual void writeIncoming(const QByteArray &a);
virtual QByteArray readOutgoing(int *plainBytes = 0);
virtual QByteArray readUnprocessed();
// for DTLS
int packetsAvailable() const;
int packetsOutgoingAvailable() const;
void setPacketMTU(int size) const;
signals:
void handshaken();
private:
class Private;
friend class Private;
Private *d;
};
/**
Simple Authentication and Security Layer protocol implementation
This class implements the Simple Authenication and Security Layer protocol,
which is described in RFC2222 - see <a href="http://www.ietf.org/rfc/rfc2222.txt">
http://www.ietf.org/rfc/rfc2222.txt</a>.
As the name suggests, %SASL provides authentication (eg, a "login" of some form), for
a connection oriented protocol, and can also provide protection for the subsequent
connection.
The %SASL protocol is designed to be extensible, through a range of "mechanisms", where
a mechanism is the actual authentication method. Example mechanisms include Anonymous,
LOGIN, Kerberos V4, and GSSAPI. Mechanisms can be added (potentially without restarting
the server application) by the system administrator.
It is important to understand that %SASL is neither "network aware" nor "protocol aware".
That means that %SASL does not understand how the client connects to the server, and %SASL
does not understand the actual application protocol.
*/
class QCA_EXPORT SASL : public SecureLayer, public Algorithm
{
Q_OBJECT
public:
/**
Possible errors that may occur when using SASL
*/
enum Error
{
ErrorInit, ///< problem starting up SASL
ErrorHandshake, ///< problem during the authentication process
ErrorCrypt ///< problem at anytime after
};
/**
Possible authentication error states
*/
enum AuthCondition
{
AuthFail, ///< Generic authentication failure
NoMech, ///< No compatible/appropriate authentication mechanism
BadProto, ///< Bad protocol or cancelled
BadServ, ///< Server failed mutual authentication (client side only)
BadAuth, ///< Authentication failure (server side only)
NoAuthzid, ///< Authorization failure (server side only)
TooWeak, ///< Mechanism too weak for this user (server side only)
NeedEncrypt, ///< Encryption is needed in order to use mechanism (server side only)
Expired, ///< Passphrase expired, has to be reset (server side only)
Disabled, ///< Account is disabled (server side only)
NoUser, ///< User not found (server side only)
RemoteUnavail ///< Remote service needed for auth is gone (server side only)
};
/**
Authentication requirement flag values
*/
enum AuthFlags
{
AllowPlain = 0x01,
AllowAnonymous = 0x02,
RequireForwardSecrecy = 0x04,
RequirePassCredentials = 0x08,
RequireMutualAuth = 0x10,
RequireAuthzidSupport = 0x20 // server-only
};
/**
Mode options for client side sending
*/
enum ClientSendMode
{
AllowClientSendFirst,
DisableClientSendFirst
};
/**
Mode options for server side sending
*/
enum ServerSendMode
{
AllowServerSendLast,
DisableServerSendLast
};
/**
Parameter status for the SASL authentication
This is used to track which parameters are currently held
*/
class Params
{
public:
/**
User is held
*/
bool user;
/**
Authorization ID is held
*/
bool authzid;
/**
Password is held
*/
bool pass;
/**
Realm is held
*/
bool realm;
};
/**
Standard constructor
\param parent the parent object for this SASL connection
\param provider if specified, the provider to use. If not
specified, or specified as empty, then any provider is
acceptable.
*/
SASL(QObject *parent = 0, const QString &provider = QString());
~SASL();
/**
Reset the SASL mechanism
*/
void reset();
// configuration
/**
Specify connection constraints
SASL supports a range of authentication requirements, and
a range of security levels. This method allows you to
specify the requirements for your connection.
\param f the authentication requirements, which you typically
build using a binary OR function (eg AllowPlain | AllowAnonymous)
\param s the security level of the encryption, if used. See
SecurityLevel for details of what each level provides.
*/
void setConstraints(AuthFlags f, SecurityLevel s = SL_None);
/**
\overload
Unless you have a specific reason for directly specifying a strength
factor, you probably should use the method above.
\param f the authentication requirements, which you typically
build using a binary OR function (eg AllowPlain | AllowAnonymous)
\param minSSF the minimum security strength factor that is required
\param maxSSF the maximum security strength factor that is required
\note Security strength factors are a rough approximation to key
length in the encryption function (eg if you are securing with plain
DES, the security strength factor would be 56).
*/
void setConstraints(AuthFlags f, int minSSF, int maxSSF);
/**
Specify the local address.
\param addr the address of the local part of the connection
\param port the port number of the local part of the connection
*/
void setLocalAddr(const QString &addr, quint16 port);
/**
Specify the peer address.
\param addr the address of the peer side of the connection
\param port the port number of the peer side of the connection
*/
void setRemoteAddr(const QString &addr, quint16 port);
/**
Specify the id of the externally secured connection
\param authid the id of the connection
*/
void setExternalAuthId(const QString &authid);
/**
Specify a security strength factor for an externally secured connection
\param strength the security strength factor of the connection
*/
void setExternalSSF(int strength);
// main
/**
Initialise the client side of the connection
startClient must be called on the client side of the connection.
clientStarted will be emitted when the operation is completed.
\param service the name of the service
\param host the client side host name
\param mechlist the list of mechanisms which can be used
\param ClientSendMode the mode to use on the client side
*/
void startClient(const QString &service, const QString &host, const QStringList &mechlist, enum ClientSendMode = AllowClientSendFirst);
/**
Initialise the server side of the connection
startServer must be called on the server side of the connection.
serverStarted will be emitted when the operation is completed.
\param service the name of the service
\param host the server side host name
\param realm the realm to use
\param mechlist the list of available mechanisms
\param ServerSendMode which mode to use on the server side
*/
void startServer(const QString &service, const QString &host, const QString &realm, enum ServerSendMode = DisableServerSendLast);
/**
Process the first step in server mode (server)
Call this with the mechanism selected by the client. If there
is initial client data, call the other version of this function
instead.
*/
void putServerFirstStep(const QString &mech);
/**
Process the first step in server mode (server)
Call this with the mechanism selected by the client, and initial
client data. If there is no initial client data, call the other
version of this function instead.
*/
void putServerFirstStep(const QString &mech, const QByteArray &clientInit);
/**
Process an authentication step
Call this with authentication data received from the network.
The only exception is the first step in server mode, in which
case putServerFirstStep must be called.
*/
void putStep(const QByteArray &stepData);
/**
Return the mechanism selected (client)
*/
QString mechanism() const;
/**
Return the mechanism list (server)
*/
QStringList mechanismList() const;
/**
Return the security strength factor of the connection
*/
int ssf() const;
/**
Return the error code
*/
Error errorCode() const;
/**
Return the reason for authentication failure
*/
AuthCondition authCondition() const;
// authentication
/**
Specify the username to use in authentication
\param user the username to use
*/
void setUsername(const QString &user);
/**
Specify the authorization identity to use in authentication
\param auth the authorization identity to use
*/
void setAuthzid(const QString &auth);
/**
Specify the password to use in authentication
\param pass the password to use
*/
void setPassword(const QSecureArray &pass);
/**
Specify the realm to use in authentication
\param realm the realm to use
*/
void setRealm(const QString &realm);
/**
Continue negotiation after parameters have been set (client)
*/
void continueAfterParams();
/**
Continue negotiation after auth ids have been checked (server)
*/
void continueAfterAuthCheck();
// reimplemented
/**
test how many (if any) bytes are available
*/
virtual int bytesAvailable() const;
/**
test how many bytes (if any) are available
*/
virtual int bytesOutgoingAvailable() const;
virtual void write(const QByteArray &a);
virtual QByteArray read();
virtual void writeIncoming(const QByteArray &a);
virtual QByteArray readOutgoing(int *plainBytes = 0);
signals:
void clientStarted(bool clientInit, const QByteArray &clientInitData); // (client)
void serverStarted(); // (server)
void nextStep(const QByteArray &stepData);
void needParams(const Params &params); // (client)
void authCheck(const QString &user, const QString &authzid); // (server)
void authenticated();
private:
class Private;
friend class Private;
Private *d;
};
}
#endif