📄 gnutls.c
字号:
{ tls_session_sys_t *p_sys; p_sys = (tls_session_sys_t *)(p_session->p_sys); if( p_sys->b_handshaked == VLC_TRUE ) gnutls_bye( p_sys->session, GNUTLS_SHUT_WR ); gnutls_deinit( p_sys->session ); if( p_sys->psz_hostname != NULL ) free( p_sys->psz_hostname ); vlc_object_detach( p_session ); vlc_object_destroy( p_session ); free( p_sys );}static voidgnutls_ClientDelete( tls_session_t *p_session ){ /* On the client-side, credentials are re-allocated per session */ gnutls_certificate_credentials x509_cred = ((tls_client_sys_t *)(p_session->p_sys))->x509_cred; gnutls_SessionClose( p_session ); /* credentials must be free'd *after* gnutls_deinit() */ gnutls_certificate_free_credentials( x509_cred );}inline intis_regular( const char *psz_filename ){#ifdef HAVE_SYS_STAT_H struct stat st; return ( stat( psz_filename, &st ) == 0 ) && S_ISREG( st.st_mode );#else return 1;#endif}static intgnutls_Addx509Directory( vlc_object_t *p_this, gnutls_certificate_credentials cred, const char *psz_dirname, vlc_bool_t private ){ DIR* dir; struct dirent *p_ent; int i_len; if( *psz_dirname == '\0' ) psz_dirname = "."; dir = opendir( psz_dirname ); if( dir == NULL ) { msg_Warn( p_this, "Cannot open directory (%s) : %s", psz_dirname, strerror( errno ) ); return VLC_EGENERIC; } i_len = strlen( psz_dirname ) + 2; while( ( p_ent = readdir( dir ) ) != NULL ) { char *psz_filename; psz_filename = (char *)malloc( i_len + strlen( p_ent->d_name ) ); if( psz_filename == NULL ) { closedir( dir ); return VLC_ENOMEM; } sprintf( psz_filename, "%s/%s", psz_dirname, p_ent->d_name ); /* we neglect the race condition here - not security sensitive */ if( is_regular( psz_filename ) ) { int i; i = (private) ? gnutls_certificate_set_x509_key_file( cred, psz_filename, psz_filename, GNUTLS_X509_FMT_PEM ) : gnutls_certificate_set_x509_trust_file( cred, psz_filename, GNUTLS_X509_FMT_PEM ); if( i < 0 ) { msg_Warn( p_this, "Cannot add x509 certificate (%s) : %s", psz_filename, gnutls_strerror( i ) ); } } free( psz_filename ); } closedir( dir ); return VLC_SUCCESS;}/***************************************************************************** * tls_ClientCreate: ***************************************************************************** * Initializes client-side TLS session data. *****************************************************************************/static tls_session_t *gnutls_ClientCreate( tls_t *p_tls ){ tls_session_t *p_session = NULL; tls_client_sys_t *p_sys = NULL; int i_val; const int cert_type_priority[3] = { GNUTLS_CRT_X509, 0 }; p_sys = (tls_client_sys_t *)malloc( sizeof(struct tls_client_sys_t) ); if( p_sys == NULL ) return NULL; p_session = (struct tls_session_t *)vlc_object_create ( p_tls, sizeof(struct tls_session_t) ); if( p_session == NULL ) { free( p_sys ); return NULL; } p_session->p_sys = p_sys; p_session->sock.p_sys = p_session; p_session->sock.pf_send = gnutls_Send; p_session->sock.pf_recv = gnutls_Recv; p_session->pf_handshake = gnutls_BeginHandshake; p_session->pf_close = gnutls_ClientDelete; p_sys->session.b_handshaked = VLC_FALSE; p_sys->session.psz_hostname = NULL; vlc_object_attach( p_session, p_tls ); i_val = gnutls_certificate_allocate_credentials( &p_sys->x509_cred ); if( i_val != 0 ) { msg_Err( p_tls, "Cannot allocate X509 credentials : %s", gnutls_strerror( i_val ) ); goto error; } if( get_Bool( p_tls, "tls-check-cert" ) ) { /* FIXME: support for changing path/using multiple paths */ char *psz_path; const char *psz_homedir; psz_homedir = p_tls->p_vlc->psz_homedir; psz_path = (char *)malloc( strlen( psz_homedir ) + sizeof( CONFIG_DIR ) + 12 ); if( psz_path == NULL ) { gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } sprintf( psz_path, "%s/"CONFIG_DIR"/ssl/certs", psz_homedir ); gnutls_Addx509Directory( (vlc_object_t *)p_session, p_sys->x509_cred, psz_path, VLC_FALSE ); free( psz_path ); p_session->pf_handshake2 = gnutls_HandshakeAndValidate; } else p_session->pf_handshake2 = gnutls_ContinueHandshake; { /* FIXME: support for changing path/using multiple paths */ char *psz_path; const char *psz_homedir; psz_homedir = p_tls->p_vlc->psz_homedir; psz_path = (char *)malloc( strlen( psz_homedir ) + sizeof( CONFIG_DIR ) + 14 ); if( psz_path == NULL ) { gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } sprintf( psz_path, "%s/"CONFIG_DIR"/ssl/private", psz_homedir ); gnutls_Addx509Directory( (vlc_object_t *)p_session, p_sys->x509_cred, psz_path, VLC_TRUE ); free( psz_path ); } i_val = gnutls_init( &p_sys->session.session, GNUTLS_CLIENT ); if( i_val != 0 ) { msg_Err( p_tls, "Cannot initialize TLS session : %s", gnutls_strerror( i_val ) ); gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } i_val = gnutls_set_default_priority( p_sys->session.session ); if( i_val < 0 ) { msg_Err( p_tls, "Cannot set ciphers priorities : %s", gnutls_strerror( i_val ) ); gnutls_deinit( p_sys->session.session ); gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } i_val = gnutls_certificate_type_set_priority( p_sys->session.session, cert_type_priority ); if( i_val < 0 ) { msg_Err( p_tls, "Cannot set certificate type priorities : %s", gnutls_strerror( i_val ) ); gnutls_deinit( p_sys->session.session ); gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } i_val = gnutls_credentials_set( p_sys->session.session, GNUTLS_CRD_CERTIFICATE, p_sys->x509_cred ); if( i_val < 0 ) { msg_Err( p_tls, "Cannot set TLS session credentials : %s", gnutls_strerror( i_val ) ); gnutls_deinit( p_sys->session.session ); gnutls_certificate_free_credentials( p_sys->x509_cred ); goto error; } return p_session;error: vlc_object_detach( p_session ); vlc_object_destroy( p_session ); free( p_sys ); return NULL;}/***************************************************************************** * TLS session resumption callbacks *****************************************************************************/static int cb_store( void *p_server, gnutls_datum key, gnutls_datum data ){ tls_server_sys_t *p_sys = ((tls_server_t *)p_server)->p_sys; if( ( p_sys->i_cache_size == 0 ) || ( key.size > MAX_SESSION_ID ) || ( data.size > MAX_SESSION_DATA ) ) return -1; vlc_mutex_lock( &p_sys->cache_lock ); memcpy( p_sys->p_store->id, key.data, key.size); memcpy( p_sys->p_store->data, data.data, data.size ); p_sys->p_store->i_idlen = key.size; p_sys->p_store->i_datalen = data.size; p_sys->p_store++; if( ( p_sys->p_store - p_sys->p_cache ) == p_sys->i_cache_size ) p_sys->p_store = p_sys->p_cache; vlc_mutex_unlock( &p_sys->cache_lock ); return 0;}static const gnutls_datum err_datum = { NULL, 0 };static gnutls_datum cb_fetch( void *p_server, gnutls_datum key ){ tls_server_sys_t *p_sys = ((tls_server_t *)p_server)->p_sys; saved_session_t *p_session, *p_end; p_session = p_sys->p_cache; p_end = p_session + p_sys->i_cache_size; vlc_mutex_lock( &p_sys->cache_lock ); while( p_session < p_end ) { if( ( p_session->i_idlen == key.size ) && !memcmp( p_session->id, key.data, key.size ) ) { gnutls_datum data; data.size = p_session->i_datalen; data.data = gnutls_malloc( data.size ); if( data.data == NULL ) { vlc_mutex_unlock( &p_sys->cache_lock ); return err_datum; } memcpy( data.data, p_session->data, data.size ); vlc_mutex_unlock( &p_sys->cache_lock ); return data; } p_session++; } vlc_mutex_unlock( &p_sys->cache_lock ); return err_datum;}static int cb_delete( void *p_server, gnutls_datum key ){ tls_server_sys_t *p_sys = ((tls_server_t *)p_server)->p_sys; saved_session_t *p_session, *p_end; p_session = p_sys->p_cache; p_end = p_session + p_sys->i_cache_size; vlc_mutex_lock( &p_sys->cache_lock ); while( p_session < p_end ) { if( ( p_session->i_idlen == key.size ) && !memcmp( p_session->id, key.data, key.size ) ) { p_session->i_datalen = p_session->i_idlen = 0; vlc_mutex_unlock( &p_sys->cache_lock ); return 0; } p_session++; } vlc_mutex_unlock( &p_sys->cache_lock ); return -1;}/***************************************************************************** * tls_ServerSessionPrepare: ***************************************************************************** * Initializes server-side TLS session data. *****************************************************************************/static tls_session_t *gnutls_ServerSessionPrepare( tls_server_t *p_server ){ tls_session_t *p_session; tls_server_sys_t *p_server_sys; gnutls_session session; int i_val; p_session = vlc_object_create( p_server, sizeof (struct tls_session_t) ); if( p_session == NULL ) return NULL; p_session->p_sys = malloc( sizeof(struct tls_session_sys_t) ); if( p_session->p_sys == NULL ) { vlc_object_destroy( p_session ); return NULL; } vlc_object_attach( p_session, p_server ); p_server_sys = (tls_server_sys_t *)p_server->p_sys; p_session->sock.p_sys = p_session; p_session->sock.pf_send = gnutls_Send; p_session->sock.pf_recv = gnutls_Recv; p_session->pf_handshake = gnutls_BeginHandshake; p_session->pf_handshake2 = p_server_sys->pf_handshake2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -