14 #define _CRT_SECURE_NO_WARNINGS 23 #include <arpa/inet.h> 24 #include <sys/types.h> 25 #include <sys/socket.h> 27 #include <netinet/in.h> 28 #define closesocket (::close) 34 #pragma comment(lib, "ws2_32.lib") 38 #ifdef MFEM_USE_GNUTLS 40 #ifndef MFEM_USE_GNUTLS_X509 41 #include <gnutls/openpgp.h> 58 int err_flag = WSAStartup(MAKEWORD(2,2), &wsaData);
61 mfem::out <<
"Error occurred during initialization of WinSock." 70 ~WinsockWrapper() { WSACleanup(); }
73 WinsockWrapper(
const WinsockWrapper&) =
delete;
74 WinsockWrapper& operator=(
const WinsockWrapper&) =
delete;
76 bool Initialized() {
return initialized; }
78 bool initialized =
false;
82 static WinsockWrapper wsInit_;
89 setg(NULL, NULL, NULL);
96 struct sockaddr_in sa;
99 if (!wsInit_.Initialized())
101 mfem_error(
"Attempting to open socket, but Winsock not initialized.");
105 setg(NULL, NULL, NULL);
108 hp = gethostbyname(hostname);
114 memset(&sa, 0,
sizeof(sa));
115 memcpy((
char *)&sa.sin_addr, hp->h_addr, hp->h_length);
116 sa.sin_family = hp->h_addrtype;
117 sa.sin_port = htons(port);
124 #if defined __APPLE__ 129 (
char *)(&on),
sizeof(on)) < 0)
138 (
const struct sockaddr *)&sa,
sizeof(sa)) < 0)
161 ssize_t bw, n = pptr() - pbase();
173 mfem::out <<
"Error in send(): " << strerror(errno) << std::endl;
196 mfem::out <<
"Error in recv(): " << strerror(errno) << std::endl;
199 setg(NULL, NULL, NULL);
200 return traits_type::eof();
203 return traits_type::to_int_type(*
ibuf);
210 return traits_type::eof();
212 if (traits_type::eq_int_type(c, traits_type::eof()))
214 return traits_type::not_eof(c);
216 *pptr() = traits_type::to_char_type(c);
225 const std::streamsize bn = egptr() - gptr();
228 traits_type::copy(s__, gptr(), n__);
232 traits_type::copy(s__, gptr(), bn);
233 setg(NULL, NULL, NULL);
234 std::streamsize remain = n__ - bn;
235 char_type *end = s__ + n__;
245 mfem::out <<
"Error in recv(): " << strerror(errno) << std::endl;
248 return (n__ - remain);
259 if (pptr() + n__ <= epptr())
261 traits_type::copy(pptr(), s__, n__);
270 std::streamsize remain = n__;
271 const char_type *end = s__ + n__;
282 mfem::out <<
"Error in send(): " << strerror(errno) << std::endl;
284 return (n__ - remain);
290 traits_type::copy(pptr(), end - remain, remain);
299 listen_socket = socket(PF_INET, SOCK_STREAM, 0);
300 if (listen_socket < 0)
305 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
306 (
char *)(&on),
sizeof(on)) < 0)
308 closesocket(listen_socket);
312 struct sockaddr_in sa;
313 memset(&sa, 0,
sizeof(sa));
314 sa.sin_family = AF_INET;
315 sa.sin_port = htons(port);
316 sa.sin_addr.s_addr = INADDR_ANY;
317 if (bind(listen_socket, (
const struct sockaddr *)&sa,
sizeof(sa)))
319 closesocket(listen_socket);
324 if (listen(listen_socket, backlog) < 0)
326 closesocket(listen_socket);
338 int err_flag = closesocket(listen_socket);
345 return good() ?
::accept(listen_socket, NULL, NULL) : -1;
354 int socketd =
::accept(listen_socket, NULL, NULL);
364 #ifdef MFEM_USE_GNUTLS 366 static void mfem_gnutls_log_func(
int level,
const char *str)
368 mfem::out <<
"GnuTLS <" << level <<
"> " << str << std::flush;
379 gnutls_global_set_log_function(mfem_gnutls_log_func);
400 #if GNUTLS_VERSION_NUMBER >= 0x021200 402 gnutls_sec_param_to_pk_bits(
403 GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
405 unsigned bits = 1024;
407 mfem::out <<
"Generating DH params (" << bits <<
" bits) ..." 421 static int mfem_gnutls_verify_callback(gnutls_session_t session)
424 #if GNUTLS_VERSION_NUMBER >= 0x030104 425 const char *hostname = (
const char *) gnutls_session_get_ptr(session);
426 int ret = gnutls_certificate_verify_peers3(session, hostname, &status);
429 mfem::out <<
"Error in gnutls_certificate_verify_peers3:" 430 << gnutls_strerror(ret) << std::endl;
431 return GNUTLS_E_CERTIFICATE_ERROR;
435 gnutls_datum_t status_str;
436 gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
437 ret = gnutls_certificate_verification_status_print(
438 status, type, &status_str, 0);
441 mfem::out <<
"Error in gnutls_certificate_verification_status_print:" 442 << gnutls_strerror(ret) << std::endl;
443 return GNUTLS_E_CERTIFICATE_ERROR;
445 mfem::out << status_str.data << std::endl;
446 gnutls_free(status_str.data);
448 #else // --> GNUTLS_VERSION_NUMBER < 0x030104 449 int ret = gnutls_certificate_verify_peers2(session, &status);
452 mfem::out <<
"Error in gnutls_certificate_verify_peers2:" 453 << gnutls_strerror(ret) << std::endl;
454 return GNUTLS_E_CERTIFICATE_ERROR;
458 "The certificate is NOT trusted." :
459 "The certificate is trusted.") << std::endl;
463 return status ? GNUTLS_E_CERTIFICATE_ERROR : 0;
468 const char *privkey_file,
const char *trustedkeys_file,
unsigned int flags)
478 gnutls_certificate_allocate_credentials(&
my_cred));
484 #ifndef MFEM_USE_GNUTLS_X509 486 gnutls_certificate_set_openpgp_key_file(
487 my_cred, pubkey_file, privkey_file, GNUTLS_OPENPGP_FMT_RAW));
491 gnutls_certificate_set_x509_key_file(
492 my_cred, pubkey_file, privkey_file, GNUTLS_X509_FMT_PEM));
510 #ifndef MFEM_USE_GNUTLS_X509 512 gnutls_certificate_set_openpgp_keyring_file(
513 my_cred, trustedkeys_file, GNUTLS_OPENPGP_FMT_RAW));
517 gnutls_certificate_set_x509_trust_file(
518 my_cred, trustedkeys_file, GNUTLS_X509_FMT_PEM);
520 #ifdef MFEM_USE_GNUTLS_DEBUG 521 mfem::out <<
"[GnuTLS_session_params::GnuTLS_session_params] " 522 "number of trusted certificates = " << num_certs << std::endl;
525 GNUTLS_E_SUCCESS : GNUTLS_E_CERTIFICATE_ERROR);
530 #if GNUTLS_VERSION_NUMBER >= 0x021000 533 gnutls_certificate_set_verify_function(
534 my_cred, mfem_gnutls_verify_callback);
544 gnutls_certificate_set_dh_params(
my_cred, dh_params);
551 #ifdef MFEM_USE_GNUTLS_DEBUG 552 mfem::out <<
"[GnuTLS_socketbuf::handshake]" << std::endl;
559 err_flag = gnutls_handshake(
session);
564 mfem::out <<
"handshake successful, TLS version is " 565 << gnutls_protocol_get_name(
566 gnutls_protocol_get_version(
session)) << std::endl;
571 while (err_flag == GNUTLS_E_INTERRUPTED || err_flag == GNUTLS_E_AGAIN);
577 #if (defined(MSG_NOSIGNAL) && !defined(_WIN32) && !defined(__APPLE__)) 578 #define MFEM_USE_GNUTLS_PUSH_FUNCTION 580 static ssize_t mfem_gnutls_push_function(
581 gnutls_transport_ptr_t fd_ptr,
const void *data,
size_t datasize)
583 return send((
int)(
long)fd_ptr, data, datasize, MSG_NOSIGNAL);
589 #ifdef MFEM_USE_GNUTLS_DEBUG 590 mfem::out <<
"[GnuTLS_socketbuf::start_session]" << std::endl;
599 #if GNUTLS_VERSION_NUMBER >= 0x030102 611 const char *priorities;
613 if (gnutls_check_version(
"2.12.0") != NULL)
616 #ifndef MFEM_USE_GNUTLS_X509 617 priorities =
"NONE:+VERS-TLS1.2:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:" 618 "+COMP-ALL:+KX-ALL:+CTYPE-OPENPGP:+CURVE-ALL";
620 priorities =
"NONE:+VERS-TLS1.2:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:" 621 "+COMP-ALL:+KX-ALL:+CTYPE-X509:+CURVE-ALL";
627 #ifndef MFEM_USE_GNUTLS_X509 628 priorities =
"NORMAL:-CTYPE-X.509";
630 priorities =
"NORMAL:";
635 gnutls_priority_set_direct(
session, priorities, &err_ptr));
639 mfem::out <<
"Error ptr = \"" << err_ptr <<
'"' << std::endl;
647 gnutls_credentials_set(
654 const char *hostname = NULL;
655 gnutls_session_set_ptr(
session, (
void*)hostname);
659 gnutls_certificate_server_set_request(
session, GNUTLS_CERT_REQUIRE);
661 #if GNUTLS_VERSION_NUMBER >= 0x030100 662 gnutls_handshake_set_timeout(
663 session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
669 #if GNUTLS_VERSION_NUMBER >= 0x030109 672 gnutls_transport_set_ptr(
session,
679 #if GNUTLS_VERSION_NUMBER < 0x021000 690 err_flag = gnutls_bye(
session, GNUTLS_SHUT_WR);
692 while (err_flag == GNUTLS_E_AGAIN || err_flag == GNUTLS_E_INTERRUPTED);
697 #ifdef MFEM_USE_GNUTLS_PUSH_FUNCTION 700 gnutls_transport_set_push_function(
session, mfem_gnutls_push_function);
714 #ifdef MFEM_USE_GNUTLS_DEBUG 715 mfem::out <<
"[GnuTLS_socketbuf::end_session]" << std::endl;
724 #ifdef MFEM_USE_GNUTLS_DEBUG 725 mfem::out <<
"[GnuTLS_socketbuf::end_session: gnutls_bye]" << std::endl;
735 while (err_flag == GNUTLS_E_AGAIN || err_flag == GNUTLS_E_INTERRUPTED);
745 #ifdef MFEM_USE_GNUTLS_DEBUG 746 mfem::out <<
"[GnuTLS_socketbuf::attach]" << std::endl;
760 #ifdef MFEM_USE_GNUTLS_DEBUG 761 mfem::out <<
"[GnuTLS_socketbuf::open]" << std::endl;
765 if (err_flag) {
return err_flag; }
774 #ifdef MFEM_USE_GNUTLS_DEBUG 775 mfem::out <<
"[GnuTLS_socketbuf::close]" << std::endl;
787 ssize_t bw, n = pptr() - pbase();
788 #ifdef MFEM_USE_GNUTLS_DEBUG 789 mfem::out <<
"[GnuTLS_socketbuf::sync n=" << n <<
']' << std::endl;
794 bw = gnutls_record_send(
session, pptr() - n, n);
795 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
814 #ifdef MFEM_USE_GNUTLS_DEBUG 815 mfem::out <<
"[GnuTLS_socketbuf::underflow ...]" << std::endl;
823 if (br == GNUTLS_E_REHANDSHAKE)
828 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
829 #ifdef MFEM_USE_GNUTLS_DEBUG 830 mfem::out <<
"[GnuTLS_socketbuf::underflow br=" << br <<
']' << std::endl;
842 setg(NULL, NULL, NULL);
843 return traits_type::eof();
846 return traits_type::to_int_type(*
ibuf);
851 #ifdef MFEM_USE_GNUTLS_DEBUG 852 mfem::out <<
"[GnuTLS_socketbuf::xsgetn n__=" << n__ <<
']' << std::endl;
856 const std::streamsize bn = egptr() - gptr();
859 traits_type::copy(s__, gptr(), n__);
863 traits_type::copy(s__, gptr(), bn);
864 setg(NULL, NULL, NULL);
865 std::streamsize remain = n__ - bn;
866 char_type *end = s__ + n__;
872 br = gnutls_record_recv(
session, end - remain, remain);
873 if (br == GNUTLS_E_REHANDSHAKE)
878 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
888 return (n__ - remain);
898 #ifdef MFEM_USE_GNUTLS_DEBUG 899 mfem::out <<
"[GnuTLS_socketbuf::xsputn n__=" << n__ <<
']' << std::endl;
903 if (pptr() + n__ <= epptr())
905 traits_type::copy(pptr(), s__, n__);
914 std::streamsize remain = n__;
915 const char_type *end = s__ + n__;
918 bw = gnutls_record_send(
session, end - remain, remain);
919 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
920 #ifdef MFEM_USE_GNUTLS_DEBUG 921 mfem::out <<
"[GnuTLS_socketbuf::xsputn bw=" << bw <<
']' << std::endl;
929 return (n__ - remain);
935 traits_type::copy(pptr(), end - remain, remain);
953 std::string home_dir(getenv(
"HOME"));
954 std::string client_dir = home_dir +
"/.config/glvis/client/";
955 #ifndef MFEM_USE_GNUTLS_X509 956 std::string pubkey = client_dir +
"pubring.gpg";
957 std::string privkey = client_dir +
"secring.gpg";
958 std::string trustedkeys = client_dir +
"trusted-servers.gpg";
960 std::string pubkey = client_dir +
"cert.pem";
961 std::string privkey = client_dir +
"key.pem";
962 std::string trustedkeys = client_dir +
"trusted-servers.pem";
965 *
state, pubkey.c_str(), privkey.c_str(), trustedkeys.c_str(),
969 mfem::out <<
" public key = " << pubkey <<
'\n' 970 <<
" private key = " << privkey <<
'\n' 971 <<
" trusted keys = " << trustedkeys << std::endl;
972 mfem::out <<
"Error setting GLVis client parameters.\n" 973 "Use the following GLVis script to create your GLVis keys:\n" 974 " bash glvis-keygen.sh [\"Your Name\"] [\"Your Email\"]" 999 std::iostream::rdbuf(
buf__);
1003 :
std::iostream(0), glvis_client(false)
1009 #endif // MFEM_USE_GNUTLS 1016 #ifdef MFEM_USE_GNUTLS 1019 mfem_error(
"The secure option in class mfem::socketstream can only\n" 1020 "be used when GnuTLS support is enabled.");
1026 std::iostream::rdbuf(
buf__);
1032 #ifdef MFEM_USE_GNUTLS 1034 else { setstate(std::ios::failbit); }
1053 int err_flag =
buf__->
open(hostname, port);
1056 setstate(std::ios::failbit);
1068 #ifdef MFEM_USE_GNUTLS void set_result(int result)
static GnuTLS_session_params * params
virtual int attach(int sd)
virtual int_type underflow()
static int num_glvis_sockets
gnutls_certificate_credentials_t my_cred
bool is_open()
Returns true if the socket is open and has a valid socket descriptor. Otherwise returns false...
void check_secure_socket()
GnuTLS_session_params(GnuTLS_global_state &state, const char *pubkey_file, const char *privkey_file, const char *trustedkeys_file, unsigned int flags)
int getsocketdescriptor()
Returns the attached socket descriptor.
gnutls_certificate_credentials_t my_cred
void set_socket(bool secure)
gnutls_dh_params_t get_dh_params()
gnutls_dh_params_t dh_params
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
unsigned int get_flags() const
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)
virtual int close()
Close the current socket descriptor.
virtual int open(const char hostname[], int port)
Open a socket on the 'port' at 'hostname' and store the socket descriptor. Returns 0 if there is no e...
socketstream(bool secure=secure_default)
Create a socket stream without connecting to a host.
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
virtual int_type underflow()
void print_on_error(const char *msg) const
void set_secure_socket(const GnuTLS_session_params &p)
static GnuTLS_session_params & add_socket()
virtual int_type overflow(int_type c=traits_type::eof())
double p(const Vector &x, double t)
virtual int attach(int sd)
Attach a new socket descriptor to the socketbuf. Returns the old socket descriptor which is NOT close...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
GnuTLS_global_state & state
virtual int open(const char hostname[], int port)
Open a socket on the 'port' at 'hostname' and store the socket descriptor. Returns 0 if there is no e...
socketserver(int port, int backlog=4)
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
static void remove_socket()
virtual int close()
Close the current socket descriptor.
void generate_dh_params()
const GnuTLS_session_params & params
static GnuTLS_global_state * state
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)