📄 gnutls.c
字号:
static voidgnutls_SetFD (tls_session_t *p_session, int fd){ gnutls_transport_set_ptr (p_session->p_sys->session, (gnutls_transport_ptr_t)(intptr_t)fd);}typedef int (*tls_prio_func) (gnutls_session_t, const int *);static intgnutls_SetPriority (vlc_object_t *restrict obj, const char *restrict name, tls_prio_func func, gnutls_session_t session, const int *restrict values){ int val = func (session, values); if (val < 0) { msg_Err (obj, "cannot set %s priorities: %s", name, gnutls_strerror (val)); return VLC_EGENERIC; } return VLC_SUCCESS;}static intgnutls_SessionPrioritize (vlc_object_t *obj, gnutls_session_t session){ /* Note that ordering matters (on the client side) */ static const int protos[] = { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; static const int comps[] = { GNUTLS_COMP_DEFLATE, GNUTLS_COMP_NULL, 0 }; static const int macs[] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_RMD160, // RIPEMD GNUTLS_MAC_MD5, //GNUTLS_MAC_MD2, //GNUTLS_MAC_NULL, 0 }; static const int ciphers[] = { GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR_128, //GNUTLS_CIPHER_DES_CBC, //GNUTLS_CIPHER_ARCFOUR_40, //GNUTLS_CIPHER_RC2_40_CBC, //GNUTLS_CIPHER_NULL, 0 }; static const int kx[] = { GNUTLS_KX_DHE_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, //GNUTLS_KX_RSA_EXPORT, //GNUTLS_KX_DHE_PSK, TODO //GNUTLS_KX_PSK, TODO //GNUTLS_KX_SRP_RSA, TODO //GNUTLS_KX_SRP_DSS, TODO //GNUTLS_KX_SRP, TODO //GNUTLS_KX_ANON_DH, 0 }; static const int cert_types[] = { GNUTLS_CRT_X509, //GNUTLS_CRT_OPENPGP, TODO 0 }; int val = gnutls_set_default_priority (session); if (val < 0) { msg_Err (obj, "cannot set default TLS priorities: %s", gnutls_strerror (val)); return VLC_EGENERIC; } if (gnutls_SetPriority (obj, "protocols", gnutls_protocol_set_priority, session, protos) || gnutls_SetPriority (obj, "compression algorithms", gnutls_compression_set_priority, session, comps) || gnutls_SetPriority (obj, "MAC algorithms", gnutls_mac_set_priority, session, macs) || gnutls_SetPriority (obj, "ciphers", gnutls_cipher_set_priority, session, ciphers) || gnutls_SetPriority (obj, "key exchange algorithms", gnutls_kx_set_priority, session, kx) || gnutls_SetPriority (obj, "certificate types", gnutls_certificate_type_set_priority, session, cert_types)) return VLC_EGENERIC; return VLC_SUCCESS;}static intgnutls_Addx509File( vlc_object_t *p_this, gnutls_certificate_credentials_t cred, const char *psz_path, bool b_priv );static intgnutls_Addx509Directory( vlc_object_t *p_this, gnutls_certificate_credentials_t cred, const char *psz_dirname, bool b_priv ){ DIR* dir; if( *psz_dirname == '\0' ) psz_dirname = "."; dir = utf8_opendir( psz_dirname ); if( dir == NULL ) { if (errno != ENOENT) { msg_Err (p_this, "cannot open directory (%s): %m", psz_dirname); return VLC_EGENERIC; } msg_Dbg (p_this, "creating empty certificate directory: %s", psz_dirname); utf8_mkdir (psz_dirname, b_priv ? 0700 : 0755); return VLC_SUCCESS; }#ifdef S_ISLNK else { struct stat st1, st2; int fd = dirfd( dir ); /* * Gets stats for the directory path, checks that it is not a * symbolic link (to avoid possibly infinite recursion), and verifies * that the inode is still the same, to avoid TOCTOU race condition. */ if( ( fd == -1) || fstat( fd, &st1 ) || utf8_lstat( psz_dirname, &st2 ) || S_ISLNK( st2.st_mode ) || ( st1.st_ino != st2.st_ino ) ) { closedir( dir ); return VLC_EGENERIC; } }#endif for (;;) { char *ent = utf8_readdir (dir); if (ent == NULL) break; if ((strcmp (ent, ".") == 0) || (strcmp (ent, "..") == 0)) continue; char path[strlen (psz_dirname) + strlen (ent) + 2]; sprintf (path, "%s"DIR_SEP"%s", psz_dirname, ent); free (ent); gnutls_Addx509File( p_this, cred, path, b_priv ); } closedir( dir ); return VLC_SUCCESS;}static intgnutls_Addx509File( vlc_object_t *p_this, gnutls_certificate_credentials cred, const char *psz_path, bool b_priv ){ struct stat st; int fd = utf8_open (psz_path, O_RDONLY, 0); if (fd == -1) goto error; block_t *block = block_File (fd); if (block != NULL) { close (fd); gnutls_datum data = { .data = block->p_buffer, .size = block->i_buffer, }; int res = b_priv ? gnutls_certificate_set_x509_key_mem (cred, &data, &data, GNUTLS_X509_FMT_PEM) : gnutls_certificate_set_x509_trust_mem (cred, &data, GNUTLS_X509_FMT_PEM); block_Release (block); if (res < 0) { msg_Warn (p_this, "cannot add x509 credentials (%s): %s", psz_path, gnutls_strerror (res)); return VLC_EGENERIC; } msg_Dbg (p_this, "added x509 credentials (%s)", psz_path); return VLC_SUCCESS; } if (!fstat (fd, &st) && S_ISDIR (st.st_mode)) { close (fd); msg_Dbg (p_this, "looking recursively for x509 credentials in %s", psz_path); return gnutls_Addx509Directory (p_this, cred, psz_path, b_priv); }error: msg_Warn (p_this, "cannot add x509 credentials (%s): %m", psz_path); if (fd != -1) close (fd); return VLC_EGENERIC;}/** TLS client session data */typedef struct tls_client_sys_t{ struct tls_session_sys_t session; gnutls_certificate_credentials_t x509_cred;} tls_client_sys_t;/** * Initializes a client-side TLS session. */static int OpenClient (vlc_object_t *obj){ tls_session_t *p_session = (tls_session_t *)obj; int i_val; if (gnutls_Init (obj)) return VLC_EGENERIC; tls_client_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) { gnutls_Deinit (obj); return VLC_ENOMEM; } p_session->p_sys = &p_sys->session; p_session->sock.p_sys = p_session; p_session->sock.pf_send = gnutls_Send; p_session->sock.pf_recv = gnutls_Recv; p_session->pf_set_fd = gnutls_SetFD; p_sys->session.b_handshaked = false; i_val = gnutls_certificate_allocate_credentials (&p_sys->x509_cred); if (i_val != 0) { msg_Err (obj, "cannot allocate X509 credentials: %s", gnutls_strerror (i_val)); goto error; } char *userdir = config_GetUserDataDir (); if (userdir != NULL) { char path[strlen (userdir) + sizeof ("/ssl/private")]; sprintf (path, "%s/ssl", userdir); utf8_mkdir (path, 0755); sprintf (path, "%s/ssl/certs", userdir); gnutls_Addx509Directory (VLC_OBJECT (p_session), p_sys->x509_cred, path, false); sprintf (path, "%s/ssl/private", userdir); gnutls_Addx509Directory (VLC_OBJECT (p_session), p_sys->x509_cred, path, true); free (userdir); } const char *confdir = config_GetConfDir (); { char path[strlen (confdir) + sizeof ("/ssl/certs/ca-certificates.crt")]; sprintf (path, "%s/ssl/certs/ca-certificates.crt", confdir); gnutls_Addx509File (VLC_OBJECT (p_session), p_sys->x509_cred, path, false); } p_session->pf_handshake = gnutls_HandshakeAndValidate; /*p_session->pf_handshake = gnutls_ContinueHandshake;*/ i_val = gnutls_init (&p_sys->session.session, GNUTLS_CLIENT); if (i_val != 0) { msg_Err (obj, "cannot initialize TLS session: %s", gnutls_strerror (i_val)); gnutls_certificate_free_credentials (p_sys->x509_cred); goto error; } if (gnutls_SessionPrioritize (VLC_OBJECT (p_session), p_sys->session.session)) goto s_error; /* minimum DH prime bits */ gnutls_dh_set_prime_bits (p_sys->session.session, 1024); i_val = gnutls_credentials_set (p_sys->session.session, GNUTLS_CRD_CERTIFICATE, p_sys->x509_cred); if (i_val < 0) { msg_Err (obj, "cannot set TLS session credentials: %s", gnutls_strerror (i_val)); goto s_error; } char *servername = var_GetNonEmptyString (p_session, "tls-server-name"); if (servername == NULL ) msg_Err (p_session, "server name missing for TLS session"); p_sys->session.psz_hostname = servername; gnutls_server_name_set (p_sys->session.session, GNUTLS_NAME_DNS, servername, strlen (servername)); return VLC_SUCCESS;s_error: gnutls_deinit (p_sys->session.session); gnutls_certificate_free_credentials (p_sys->x509_cred);error: gnutls_Deinit (obj); free (p_sys); return VLC_EGENERIC;}static void CloseClient (vlc_object_t *obj){ tls_session_t *client = (tls_session_t *)obj; tls_client_sys_t *p_sys = (tls_client_sys_t *)(client->p_sys); if (p_sys->session.b_handshaked == true) gnutls_bye (p_sys->session.session, GNUTLS_SHUT_WR); gnutls_deinit (p_sys->session.session); /* credentials must be free'd *after* gnutls_deinit() */ gnutls_certificate_free_credentials (p_sys->x509_cred); gnutls_Deinit (obj); free (p_sys->session.psz_hostname); free (p_sys);}/** * Server-side TLS */struct tls_server_sys_t{ gnutls_certificate_credentials_t x509_cred; gnutls_dh_params_t dh_params; struct saved_session_t *p_cache; struct saved_session_t *p_store; int i_cache_size; vlc_mutex_t cache_lock; int (*pf_handshake) (tls_session_t *);};/** * TLS session resumption callbacks (server-side) */#define MAX_SESSION_ID 32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -