gnutls-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [gnutls-dev] c++ interface to gnutls.h


From: Rupert Kittinger-Sereinig
Subject: Re: [gnutls-dev] c++ interface to gnutls.h
Date: Thu, 01 Jun 2006 23:22:41 +0200
User-agent: Thunderbird 1.5 (X11/20051201)

Hi Nikos,

I have thought a little about decomposing the session class. From the code I have looked at, all the state information is supposed to be stored inside the gnutls_session_t. so it would be quite easy to build a derived class that just acts as a wrapper that adds some more functions.

e.g. like this:

class minimal_session {

// maybe this class should do nothing but manage the gnutls_session_t
// object

public:

        minimal_session(gnutls_connection_end_t t) {
                //
                //   I would not use RETWRAP functions here since the
                //   constructor does not return anything
                //
                int ret = gnutls_init(&s_, t);
                if (ret != 0) throw(exception(ret));
        }

        virtual ~minimal_session() {
                gnutls_deinit(s_);
        }
                
protected:
        //
        //   all derived classes shall use the gnutls_session_t from
        //   an instance of minimal session
        //      
        minimal_session() : s_(0) {}
        //
        // adding this function will prevent derived classes from
        // messing with the pointer.
        //
        const gnutls_session& get_session() { return s; }

private:
        //
        //   disable copying by declaring, but not defining copy
        //   constructor and assignement operator
        //
        minimal_session(const minimal session &s);

        minimal session& operator=(const minimal session &s);   
        
        //
        // adding a trailing underscore to member variables is a
        // nice convention used by a lot of people nowadays
        //      
        gnutls_session_t s_;
};

//
//  this class provides the configuration functionality
//

class config_session : public minimal session {

public:
        config_session(const session& other) : s_(other.get_session())          
    {}

        // default destructor is fine

// copy ctor and assignement op are disabled because they are // private in the base class

        size_t get_max_size () const;

        void set_max_size(size_t size);

        ...

private:
        const gnutls_session_t s_;              
};

//
//  this class provides the configuration functionality
//

class io_session : public minimal session {

public:
        // same as above
        io_session(const session& other) : s_(other.get_session()){}

        ssize_t record_recv (void * data, size_t sizeofdata);

        ssize_t record_send (const void * data, size_t sizeofdata);

        ...

private:
         const gnutls_session_t s_;
};

Now if we move configuration, data transfer, etc in separarte functions, we can create the right "view" of the class at the function call border:

void configure_session(config_session &s) {
        s.set_max_size(4711);
        ...
}

void send_something(io_session &s) {
        std::string msg("hello world\n");
        s.record_send(msg.c_str(), msg.size());

        ...
}

These functions may be called like this:

int main() {
        minimal_session s(GNUTLS_CLIENT);

        // create a temporary for the function
        configure_session(config_session(s));

        send_something(io_session(s));

...
}


About coding in general: I do not have too much time either, but I think I will be able to do at least some detailed code reviewing.

greetings,
Rupert

PS: the CC should work now, I have updated my subscription data.

Nikos Mavrogiannopoulos schrieb:
On Wed 31 May 2006 21:39, Rupert Kittinger-Sereinig wrote:

I have not done a detailed review, but here are some points I
noticed:

Hello Rupert, thanks for the comments. I've already addressed some of them. (see below)

- exceptions for error handling: will all error conditions throw
exceptions?

Yes except for non fatal errors. The functions that only throw fatal
exceptions now have a void return type.

- I would like to be able to extract the error code from the
exception, not just a message string.
Indeed. Updated.

- I recommend removing all throw() specifications except where
required by the standard (i.e. exception::what()). See e.g. the boost
rationale:
http://www.boost.org/more/lib_guide.htm#Exception-specification
- All those get_ functions should get a const attribute.
done.

- most of the classes will need special treatment for copy and
assignement.

will address at a later time.

- The session class looks somewhat bloated to me. How about providing
a hierarchy of classes that present different subsets of the
functionality?

Indeed it could be cleaner. Any proposals?
- consistency: the c interface uses a mixture of gnutls_datum, char*,
unsigned char*, void*, paired with unsigned int, size_t. It would be
great if the c++ Interface would just stick to one variant, like
std::vector<unsigned char>.

Hmmm that's tricky to wrap in most of the cases, but it would provide a cleaner api, that's true. If you have any good suggestions on that they're welcome.

- I think there a session cache should be implemented as an object.
so it would be nice to provide a base class that provides member
functions equivalent to the gnutls_db_func types and handles the
installation of forwarding functions.

Yes this was my original idea. Now it's implemented. In general i've quite limited time for that so if you or anyone else is interested in that and more in hurry than me, I've put my current sources at:
http://members.hellug.gr/nmav/misc/gnutlsxx.h
http://members.hellug.gr/nmav/misc/gnutlsxx.cpp


cheers,
Rupert

-------------------------------------------------------------------
-----

#ifndef GNUTLSXX_H
# define GNUTLSXX_H

#include <exception>
#include <vector>
#include <gnutls.h>

namespace gnutls {

class exception: public std::exception
{
    public:
        exception( int x);
        const char* what() const throw();
    protected:
        int retcode;
};



class dh_params
{
    public:
        dh_params();
        ~dh_params();
        void import_raw( const gnutls_datum_t & prime,
                     const gnutls_datum_t & generator);
        void import_pkcs3( const gnutls_datum_t & pkcs3_params,
                           gnutls_x509_crt_fmt_t format);
        void generate( unsigned int bits);

        void export_pkcs3( gnutls_x509_crt_fmt_t format, unsigned
char *params_data, size_t * params_data_size); void export_raw(
gnutls_datum_t& prime, gnutls_datum_t &generator);

        gnutls_dh_params_t get_params_t() const;
        dh_params & operator=(const dh_params& src);
    protected:
        gnutls_dh_params_t params;
};


class rsa_params
{
    public:
        rsa_params();
        ~rsa_params();
        void import_raw( const gnutls_datum_t & m,
                     const gnutls_datum_t & e,
                     const gnutls_datum_t & d,
                     const gnutls_datum_t & p,
                     const gnutls_datum_t & q,
                     const gnutls_datum_t & u);
        void import_pkcs1( const gnutls_datum_t & pkcs1_params,
                           gnutls_x509_crt_fmt_t format);
        void generate( unsigned int bits);

        void export_pkcs1( gnutls_x509_crt_fmt_t format, unsigned
char *params_data, size_t * params_data_size); void export_raw( gnutls_datum_t & m, gnutls_datum_t & e, gnutls_datum_t & d,
gnutls_datum_t & p, gnutls_datum_t & q, gnutls_datum_t & u);
gnutls_rsa_params_t get_params_t() const;
        rsa_params & operator=(const rsa_params& src);

    protected:
        gnutls_rsa_params_t params;
};

enum priority_flag { ALL_CIPHERS, EXPORT_CIPHERS };

class session
{
    protected:
        gnutls_session_t s;

    public:
        session( gnutls_connection_end_t);
        virtual ~session();

        int bye( gnutls_close_request_t how);
        int handshake ();

        gnutls_alert_description_t get_alert() throw();

        int send_alert ( gnutls_alert_level_t level,
                         gnutls_alert_description_t desc);
        int send_appropriate_alert (int err);

        gnutls_cipher_algorithm_t get_cipher() throw();
        gnutls_kx_algorithm_t get_kx () throw();
        gnutls_mac_algorithm_t get_mac () throw();
        gnutls_compression_method_t get_compression () throw();
        gnutls_certificate_type_t get_certificate_type() throw();

        // for the handshake
        void set_private_extensions ( bool allow) throw();

        gnutls_handshake_description_t get_handshake_last_out()
throw(); gnutls_handshake_description_t get_handshake_last_in()
throw();

        ssize_t send (const void *data, size_t sizeofdata);
        ssize_t recv (void *data, size_t sizeofdata);

        bool get_record_direction() throw();

        // maximum packet size
        size_t get_max_size() throw();
        void set_max_size(size_t size);

        size_t check_pending() throw();

        void prf (size_t label_size, const char *label,
                        int server_random_first,
                        size_t extra_size, const char *extra,
                        size_t outsize, char *out);

        void prf_raw ( size_t label_size, const char *label,
                      size_t seed_size, const char *seed,
                      size_t outsize, char *out);

        void set_cipher_priority (const int *list);
        void set_mac_priority (const int *list);
        void set_compression_priority (const int *list);
        void set_kx_priority (const int *list);
        void set_protocol_priority (const int *list);
        void set_certificate_type_priority (const int *list);

/* if you just want some defaults, use the following.
 */
        void set_default_priority (priority_flag flag);

        gnutls_protocol_t get_protocol_version() throw();

        // for resuming sessions
        void set_data ( const void *session_data,
                        size_t session_data_size);
        void get_data (void *session_data,
                       size_t * session_data_size);
        void get_data(gnutls_session_t session,
                        gnutls_datum_t & data);
        void get_id ( void *session_id,
                      size_t * session_id_size);

        bool is_resumed () throw();

        void set_max_handshake_packet_length ( size_t max) throw();

        void clear_credentials() throw();
        void set_credentials( class credentials & cred);

        void set_transport_ptr( gnutls_transport_ptr_t ptr);
        void set_transport_ptr( gnutls_transport_ptr_t recv_ptr,
gnutls_transport_ptr_t send_ptr); gnutls_transport_ptr_t
get_transport_ptr();
        void get_transport_ptr(gnutls_transport_ptr_t * recv_ptr,
                               gnutls_transport_ptr_t * send_ptr);

        void set_transport_lowat (size_t num);
        void set_transport_push_function( gnutls_push_func
push_func); void set_transport_pull_function( gnutls_pull_func
pull_func);

        void set_user_ptr( void* ptr);
        void *get_user_ptr();

        void send_openpgp_key( gnutls_openpgp_key_status_t status);

        gnutls_credentials_type_t get_auth_type();
        gnutls_credentials_type_t get_server_auth_type();
        gnutls_credentials_type_t get_client_auth_type();

        // informational stuff
        void set_dh_prime_bits( unsigned int bits);
        unsigned int get_dh_secret_bits();
        unsigned int get_dh_peers_public_bits();
        unsigned int get_dh_prime_bits();
        void get_dh_group( gnutls_datum_t & gen, gnutls_datum_t &
prime); void get_dh_pubkey( gnutls_datum_t & raw_key);
        void get_rsa_export_pubkey( gnutls_datum& exponent,
gnutls_datum& modulus); unsigned int get_rsa_export_modulus_bits();

        const gnutls_datum* get_our_certificate();
        bool get_peers_certificate(std::vector<gnutls_datum_t>
&out_certs); bool get_peers_certificate(const gnutls_datum_t**
certs, unsigned int *certs_size);

        time_t get_peers_certificate_activation_time();
        time_t get_peers_certificate_expiration_time();
        void verify_peers_certificate( unsigned int& status);


};

class server_session: public session
{

    void set_db_cache_expiration (unsigned int seconds) throw();
    void db_remove ();
    void set_db_retrieve_function ( gnutls_db_retr_func retr_func);
    void set_db_remove_function ( gnutls_db_remove_func rem_func);
    void set_db_store_function ( gnutls_db_store_func store_func);
    void set_db_ptr ( void *ptr);
    void *get_db_ptr ();

        // returns true if session is expired
    bool db_check_entry ( gnutls_datum_t &session_entry);

    // server side only
    const char *get_srp_username();
    const char *get_psk_username();

    void get_server_name (void *data, size_t * data_length,
                          unsigned int *type, unsigned int indx);

    int rehandshake();
    void set_certificate_request( gnutls_certificate_request_t);

};

class client_session: public session
{
    void set_server_name (gnutls_server_name_type_t type,
                          const void *name, size_t name_length);

    bool client_session::get_request_status();
};


class credentials
{
    public:
        credentials(gnutls_credentials_type_t t) : type(t) { }
        virtual ~credentials() { }
        gnutls_credentials_type_t get_type();
    protected:
        friend class session;
        virtual void* ptr();
        gnutls_credentials_type_t type;
};

class certificate_credentials: public credentials
{
    public:
        ~certificate_credentials();
        certificate_credentials();

        void free_keys ();
        void free_cas ();
        void free_ca_names ();
        void free_crls ();

        void set_dh_params ( const dh_params &params);
        void set_rsa_export_params ( const rsa_params& params);
        void set_verify_flags ( unsigned int flags);
        void set_verify_limits ( unsigned int max_bits, unsigned
int max_depth);

        void set_x509_trust_file(const char *cafile,
gnutls_x509_crt_fmt_t type); void set_x509_trust(const
gnutls_datum_t & CA, gnutls_x509_crt_fmt_t type); // FIXME: use
classes instead of gnutls_x509_crt_t void set_x509_trust (
gnutls_x509_crt_t * ca_list, int ca_list_size);

        void set_x509_crl_file( const char *crlfile,
gnutls_x509_crt_fmt_t type); void set_x509_crl(const gnutls_datum_t
& CRL, gnutls_x509_crt_fmt_t type); void set_x509_crl (
gnutls_x509_crl_t * crl_list, int crl_list_size);

        void set_x509_key_file(const char *certfile, const char
*KEYFILE, gnutls_x509_crt_fmt_t type); void set_x509_key(const
gnutls_datum_t & CERT, const gnutls_datum_t & KEY,
gnutls_x509_crt_fmt_t type); // FIXME: use classes
        void set_x509_key ( gnutls_x509_crt_t * cert_list, int
cert_list_size, gnutls_x509_privkey_t key);


        void set_simple_pkcs12_file( const char *pkcs12file,
                 gnutls_x509_crt_fmt_t type, const char *password);

    protected:
        void* ptr();
        gnutls_certificate_credentials_t cred;
};

class certificate_server_credentials: public
certificate_credentials {
    certificate_server_credentials() { }
    public:
        void set_retrieve_function(
gnutls_certificate_server_retrieve_function* func) throw(); void
set_params_function( gnutls_params_function* func) throw(); };

class certificate_client_credentials: public
certificate_credentials {
    public:
        certificate_client_credentials() { }
        void set_retrieve_function(
gnutls_certificate_client_retrieve_function* func) throw(); };




class anon_server_credentials: public credentials
{
    public:
        anon_server_credentials();
        ~anon_server_credentials();
        void set_dh_params ( const dh_params &params);
        void set_params_function ( gnutls_params_function * func)
throw(); protected:
        gnutls_anon_server_credentials_t cred;
};

class anon_client_credentials: public credentials
{
    public:
        anon_client_credentials();
        ~anon_client_credentials();
    protected:
        gnutls_anon_client_credentials_t cred;
};


class srp_server_credentials: public credentials
{
    public:
        srp_server_credentials();
        ~srp_server_credentials();
        void set_credentials_file (const char *password_file, const
char *password_conf_file); void set_credentials_function(
gnutls_srp_server_credentials_function *func); protected:
        void* ptr();
        gnutls_srp_server_credentials_t cred;
};

class srp_client_credentials: public credentials
{
    public:
        srp_client_credentials();
        ~srp_client_credentials();
        void set_credentials (const char *username, const char
*password); void set_credentials_function(
gnutls_srp_client_credentials_function* func); protected:
        void* ptr();
        gnutls_srp_client_credentials_t cred;
};


class psk_server_credentials: public credentials
{
    public:
        psk_server_credentials();
        ~psk_server_credentials();
        void set_credentials_file(const char* password_file);
        void set_credentials_function(
gnutls_psk_server_credentials_function* func); void set_dh_params (
const dh_params &params);
        void set_params_function (gnutls_params_function * func)
throw(); protected:
        void* ptr();
        gnutls_psk_server_credentials_t cred;
};

class psk_client_credentials: public credentials
{
    public:
        psk_client_credentials();
        ~psk_client_credentials();
        void set_credentials (const char *username, const
gnutls_datum_t& key, gnutls_psk_key_flags flags); void
set_credentials_function( gnutls_psk_client_credentials_function*
func); protected:
        void* ptr();
        gnutls_psk_client_credentials_t cred;
};


}; /* namespace */

#endif                          /* GNUTLSXX_H */


-------------------------------------------------------------------
-----

_______________________________________________
Gnutls-dev mailing list
address@hidden
http://lists.gnupg.org/mailman/listinfo/gnutls-dev


--
Rupert Kittinger-Sereinig <address@hidden>
Krenngasse 32
A-8010 Graz
Austria




reply via email to

[Prev in Thread] Current Thread [Next in Thread]