[gnutls-dev] c++ interface to gnutls.h
Rupert Kittinger-Sereinig
rks at mur.at
Thu Jun 1 23:22:41 CEST 2006
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 ¶ms);
>>> 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 ¶ms);
>>> 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 ¶ms);
>>> 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
>>> Gnutls-dev at gnupg.org
>>> http://lists.gnupg.org/mailman/listinfo/gnutls-dev
--
Rupert Kittinger-Sereinig <rks at mur.at>
Krenngasse 32
A-8010 Graz
Austria
More information about the Gnutls-devel
mailing list