2005-06-19 08:20:27 +04:00
/*
Unix SMB / CIFS implementation .
auto - generate self signed TLS certificates
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-06-19 08:20:27 +04:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-06-19 08:20:27 +04:00
*/
# include "includes.h"
2006-08-22 03:00:53 +04:00
# if ENABLE_GNUTLS
2005-06-19 08:20:27 +04:00
# include "gnutls/gnutls.h"
# include "gnutls/x509.h"
2009-02-18 06:46:57 +03:00
# if HAVE_GCRYPT_H
# include <gcrypt.h>
# endif
2005-06-19 08:20:27 +04:00
# define ORGANISATION_NAME "Samba Administration"
# define UNIT_NAME "Samba - temporary autogenerated certificate"
# define LIFETIME 700*24*60*60
2006-04-30 22:46:14 +04:00
# define DH_BITS 1024
2005-06-19 08:20:27 +04:00
/*
auto - generate a set of self signed certificates
*/
void tls_cert_generate ( TALLOC_CTX * mem_ctx ,
2009-02-18 06:46:57 +03:00
const char * hostname ,
2005-06-19 08:20:27 +04:00
const char * keyfile , const char * certfile ,
const char * cafile )
{
gnutls_x509_crt cacrt , crt ;
gnutls_x509_privkey key , cakey ;
uint32_t serial = ( uint32_t ) time ( NULL ) ;
2006-03-30 12:31:39 +04:00
unsigned char keyid [ 100 ] ;
2005-06-19 08:20:27 +04:00
char buf [ 4096 ] ;
size_t bufsize ;
size_t keyidsize = sizeof ( keyid ) ;
time_t activation = time ( NULL ) , expiry = activation + LIFETIME ;
int ret ;
if ( file_exist ( keyfile ) | | file_exist ( certfile ) | | file_exist ( cafile ) ) {
DEBUG ( 0 , ( " TLS autogeneration skipped - some TLS files already exist \n " ) ) ;
return ;
}
# define TLSCHECK(call) do { \
ret = call ; \
if ( ret < 0 ) { \
DEBUG ( 0 , ( " TLS %s - %s \n " , # call , gnutls_strerror ( ret ) ) ) ; \
goto failed ; \
} \
} while ( 0 )
TLSCHECK ( gnutls_global_init ( ) ) ;
2009-02-18 06:46:57 +03:00
DEBUG ( 0 , ( " Attempting to autogenerate TLS self-signed keys for https for hostname '%s' \n " ,
hostname ) ) ;
2005-06-19 08:20:27 +04:00
2009-02-18 06:46:57 +03:00
# ifdef HAVE_GCRYPT_H
DEBUG ( 3 , ( " Enabling QUICK mode in gcrypt \n " ) ) ;
gcry_control ( GCRYCTL_ENABLE_QUICK_RANDOM , 0 ) ;
# endif
2005-06-19 08:20:27 +04:00
DEBUG ( 3 , ( " Generating private key \n " ) ) ;
TLSCHECK ( gnutls_x509_privkey_init ( & key ) ) ;
2006-04-30 22:46:14 +04:00
TLSCHECK ( gnutls_x509_privkey_generate ( key , GNUTLS_PK_RSA , DH_BITS , 0 ) ) ;
2005-06-19 08:20:27 +04:00
DEBUG ( 3 , ( " Generating CA private key \n " ) ) ;
TLSCHECK ( gnutls_x509_privkey_init ( & cakey ) ) ;
2006-04-30 22:46:14 +04:00
TLSCHECK ( gnutls_x509_privkey_generate ( cakey , GNUTLS_PK_RSA , DH_BITS , 0 ) ) ;
2005-06-19 08:20:27 +04:00
DEBUG ( 3 , ( " Generating CA certificate \n " ) ) ;
TLSCHECK ( gnutls_x509_crt_init ( & cacrt ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( cacrt ,
GNUTLS_OID_X520_ORGANIZATION_NAME , 0 ,
ORGANISATION_NAME , strlen ( ORGANISATION_NAME ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( cacrt ,
GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME , 0 ,
UNIT_NAME , strlen ( UNIT_NAME ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( cacrt ,
GNUTLS_OID_X520_COMMON_NAME , 0 ,
2009-02-18 06:46:57 +03:00
hostname , strlen ( hostname ) ) ) ;
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_set_key ( cacrt , cakey ) ) ;
TLSCHECK ( gnutls_x509_crt_set_serial ( cacrt , & serial , sizeof ( serial ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_activation_time ( cacrt , activation ) ) ;
TLSCHECK ( gnutls_x509_crt_set_expiration_time ( cacrt , expiry ) ) ;
TLSCHECK ( gnutls_x509_crt_set_ca_status ( cacrt , 0 ) ) ;
# ifdef GNUTLS_KP_TLS_WWW_SERVER
TLSCHECK ( gnutls_x509_crt_set_key_purpose_oid ( cacrt , GNUTLS_KP_TLS_WWW_SERVER , 0 ) ) ;
# endif
TLSCHECK ( gnutls_x509_crt_set_version ( cacrt , 3 ) ) ;
TLSCHECK ( gnutls_x509_crt_get_key_id ( cacrt , 0 , keyid , & keyidsize ) ) ;
2005-07-15 11:00:12 +04:00
# if HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_set_subject_key_id ( cacrt , keyid , keyidsize ) ) ;
2005-07-15 11:00:12 +04:00
# endif
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_sign ( cacrt , cacrt , cakey ) ) ;
DEBUG ( 3 , ( " Generating TLS certificate \n " ) ) ;
TLSCHECK ( gnutls_x509_crt_init ( & crt ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( crt ,
GNUTLS_OID_X520_ORGANIZATION_NAME , 0 ,
ORGANISATION_NAME , strlen ( ORGANISATION_NAME ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( crt ,
GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME , 0 ,
UNIT_NAME , strlen ( UNIT_NAME ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_dn_by_oid ( crt ,
GNUTLS_OID_X520_COMMON_NAME , 0 ,
2009-02-18 06:46:57 +03:00
hostname , strlen ( hostname ) ) ) ;
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_set_key ( crt , key ) ) ;
TLSCHECK ( gnutls_x509_crt_set_serial ( crt , & serial , sizeof ( serial ) ) ) ;
TLSCHECK ( gnutls_x509_crt_set_activation_time ( crt , activation ) ) ;
TLSCHECK ( gnutls_x509_crt_set_expiration_time ( crt , expiry ) ) ;
TLSCHECK ( gnutls_x509_crt_set_ca_status ( crt , 0 ) ) ;
# ifdef GNUTLS_KP_TLS_WWW_SERVER
TLSCHECK ( gnutls_x509_crt_set_key_purpose_oid ( crt , GNUTLS_KP_TLS_WWW_SERVER , 0 ) ) ;
# endif
TLSCHECK ( gnutls_x509_crt_set_version ( crt , 3 ) ) ;
TLSCHECK ( gnutls_x509_crt_get_key_id ( crt , 0 , keyid , & keyidsize ) ) ;
2005-07-15 11:00:12 +04:00
# if HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_set_subject_key_id ( crt , keyid , keyidsize ) ) ;
2005-07-15 11:00:12 +04:00
# endif
2005-06-19 08:20:27 +04:00
TLSCHECK ( gnutls_x509_crt_sign ( crt , crt , key ) ) ;
DEBUG ( 3 , ( " Exporting TLS keys \n " ) ) ;
bufsize = sizeof ( buf ) ;
TLSCHECK ( gnutls_x509_crt_export ( crt , GNUTLS_X509_FMT_PEM , buf , & bufsize ) ) ;
file_save ( certfile , buf , bufsize ) ;
bufsize = sizeof ( buf ) ;
TLSCHECK ( gnutls_x509_crt_export ( cacrt , GNUTLS_X509_FMT_PEM , buf , & bufsize ) ) ;
file_save ( cafile , buf , bufsize ) ;
bufsize = sizeof ( buf ) ;
TLSCHECK ( gnutls_x509_privkey_export ( key , GNUTLS_X509_FMT_PEM , buf , & bufsize ) ) ;
file_save ( keyfile , buf , bufsize ) ;
gnutls_x509_privkey_deinit ( key ) ;
gnutls_x509_privkey_deinit ( cakey ) ;
gnutls_x509_crt_deinit ( cacrt ) ;
gnutls_x509_crt_deinit ( crt ) ;
gnutls_global_deinit ( ) ;
DEBUG ( 0 , ( " TLS self-signed keys generated OK \n " ) ) ;
return ;
failed :
DEBUG ( 0 , ( " TLS certificate generation failed \n " ) ) ;
}
# else
2007-09-08 20:46:30 +04:00
void tls_cert_dummy ( void ) { }
2005-06-19 08:20:27 +04:00
# endif