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)
33 #pragma comment(lib, "ws2_32.lib")
36 #ifdef MFEM_USE_GNUTLS
38 #include <gnutls/openpgp.h>
51 setg(NULL, NULL, NULL);
58 struct sockaddr_in sa;
62 setg(NULL, NULL, NULL);
65 hp = gethostbyname(hostname);
71 memset(&sa, 0,
sizeof(sa));
72 memcpy((
char *)&sa.sin_addr, hp->h_addr, hp->h_length);
73 sa.sin_family = hp->h_addrtype;
74 sa.sin_port = htons(port);
86 (
char *)(&on),
sizeof(on)) < 0)
95 (
const struct sockaddr *)&sa,
sizeof(sa)) < 0)
118 ssize_t bw, n = pptr() - pbase();
130 std::cout <<
"Error in send(): " << strerror(errno) << std::endl;
153 std::cout <<
"Error in recv(): " << strerror(errno) << std::endl;
156 setg(NULL, NULL, NULL);
157 return traits_type::eof();
160 return traits_type::to_int_type(*
ibuf);
167 return traits_type::eof();
169 if (traits_type::eq_int_type(c, traits_type::eof()))
171 return traits_type::not_eof(c);
173 *pptr() = traits_type::to_char_type(c);
182 const std::streamsize bn = egptr() - gptr();
185 traits_type::copy(__s, gptr(), __n);
189 traits_type::copy(__s, gptr(), bn);
190 setg(NULL, NULL, NULL);
191 std::streamsize remain = __n - bn;
192 char_type *end = __s + __n;
202 std::cout <<
"Error in recv(): " << strerror(errno) << std::endl;
205 return (__n - remain);
216 if (pptr() + __n <= epptr())
218 traits_type::copy(pptr(), __s, __n);
227 std::streamsize remain = __n;
228 const char_type *end = __s + __n;
239 std::cout <<
"Error in send(): " << strerror(errno) << std::endl;
241 return (__n - remain);
247 traits_type::copy(pptr(), end - remain, remain);
256 listen_socket = socket(PF_INET, SOCK_STREAM, 0);
257 if (listen_socket < 0)
262 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
263 (
char *)(&on),
sizeof(on)) < 0)
265 closesocket(listen_socket);
269 struct sockaddr_in sa;
270 memset(&sa, 0,
sizeof(sa));
271 sa.sin_family = AF_INET;
272 sa.sin_port = htons(port);
273 sa.sin_addr.s_addr = INADDR_ANY;
274 if (bind(listen_socket, (
const struct sockaddr *)&sa,
sizeof(sa)))
276 closesocket(listen_socket);
280 const int backlog = 4;
281 if (listen(listen_socket, backlog) < 0)
283 closesocket(listen_socket);
295 int err = closesocket(listen_socket);
302 return good() ?
::accept(listen_socket, NULL, NULL) : -1;
311 int socketd =
::accept(listen_socket, NULL, NULL);
321 #ifdef MFEM_USE_GNUTLS
323 static void mfem_gnutls_log_func(
int level,
const char *str)
325 std::cout <<
"GnuTLS <" << level <<
"> " << str << std::flush;
336 gnutls_global_set_log_function(mfem_gnutls_log_func);
357 #if GNUTLS_VERSION_NUMBER >= 0x021200
359 gnutls_sec_param_to_pk_bits(
360 GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
362 unsigned bits = 1024;
364 std::cout <<
"Generating DH params (" << bits <<
" bits) ..."
367 std::cout <<
" done." << std::endl;
378 static int mfem_gnutls_verify_callback(gnutls_session_t session)
381 #if GNUTLS_VERSION_NUMBER >= 0x030104
382 const char *hostname = (
const char *) gnutls_session_get_ptr(session);
383 int ret = gnutls_certificate_verify_peers3(session, hostname, &status);
386 std::cout <<
"Error in gnutls_certificate_verify_peers3:"
387 << gnutls_strerror(ret) << std::endl;
388 return GNUTLS_E_CERTIFICATE_ERROR;
393 gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
394 ret = gnutls_certificate_verification_status_print(status, type, &out, 0);
397 std::cout <<
"Error in gnutls_certificate_verification_status_print:"
398 << gnutls_strerror(ret) << std::endl;
399 return GNUTLS_E_CERTIFICATE_ERROR;
401 std::cout << out.data << std::endl;
402 gnutls_free(out.data);
404 #else // --> GNUTLS_VERSION_NUMBER < 0x030104
405 int ret = gnutls_certificate_verify_peers2(session, &status);
408 std::cout <<
"Error in gnutls_certificate_verify_peers2:"
409 << gnutls_strerror(ret) << std::endl;
410 return GNUTLS_E_CERTIFICATE_ERROR;
413 std::cout << (status ?
414 "The certificate is NOT trusted." :
415 "The certificate is trusted.") << std::endl;
419 return status ? GNUTLS_E_CERTIFICATE_ERROR : 0;
424 const char *privkey_file,
const char *trustedkeys_file,
unsigned int flags)
428 my_flags = status.good() ? flags : 0;
434 gnutls_certificate_allocate_credentials(&
my_cred));
435 status.print_on_error(
"gnutls_certificate_allocate_credentials");
437 if (!status.good()) {
my_cred = NULL; }
441 gnutls_certificate_set_openpgp_key_file(
442 my_cred, pubkey_file, privkey_file, GNUTLS_OPENPGP_FMT_RAW));
443 status.print_on_error(
"gnutls_certificate_set_openpgp_key_file");
459 gnutls_certificate_set_openpgp_keyring_file(
460 my_cred, trustedkeys_file, GNUTLS_OPENPGP_FMT_RAW));
461 status.print_on_error(
"gnutls_certificate_set_openpgp_keyring_file");
464 #if GNUTLS_VERSION_NUMBER >= 0x021000
467 gnutls_certificate_set_verify_function(
468 my_cred, mfem_gnutls_verify_callback);
472 if (status.good() && (flags & GNUTLS_SERVER))
478 gnutls_certificate_set_dh_params(
my_cred, dh_params);
485 #ifdef MFEM_USE_GNUTLS_DEBUG
486 std::cout <<
"[GnuTLS_socketbuf::handshake]" << std::endl;
493 err = gnutls_handshake(session);
494 status.set_result(err);
498 std::cout <<
"handshake successful, TLS version is "
499 << gnutls_protocol_get_name(
500 gnutls_protocol_get_version(session)) << std::endl;
505 while (err == GNUTLS_E_INTERRUPTED || err == GNUTLS_E_AGAIN);
507 status.print_on_error(
"gnutls_handshake");
511 #if (defined(MSG_NOSIGNAL) && !defined(_WIN32) && !defined(__APPLE__))
512 #define MFEM_USE_GNUTLS_PUSH_FUNCTION
514 static ssize_t mfem_gnutls_push_function(
515 gnutls_transport_ptr_t fd_ptr,
const void *data,
size_t datasize)
517 return send((
int)(
long)fd_ptr, data, datasize, MSG_NOSIGNAL);
523 #ifdef MFEM_USE_GNUTLS_DEBUG
524 std::cout <<
"[GnuTLS_socketbuf::start_session]" << std::endl;
533 #if GNUTLS_VERSION_NUMBER >= 0x030102
539 status.print_on_error(
"gnutls_init");
545 #if GNUTLS_VERSION_NUMBER >= 0x030000 // what is the right version here?
546 const char *priorities =
547 "NONE:+VERS-TLS1.2:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:"
548 "+KX-ALL:+CTYPE-OPENPGP:+CURVE-ALL";
550 const char *priorities =
"NORMAL:-CTYPE-X.509";
554 gnutls_priority_set_direct(session, priorities, &err_ptr));
555 status.print_on_error(
"gnutls_priority_set_direct");
558 std::cout <<
"Error ptr = \"" << err_ptr <<
'"' << std::endl;
566 gnutls_credentials_set(
567 session, GNUTLS_CRD_CERTIFICATE,
my_cred));
568 status.print_on_error(
"gnutls_credentials_set");
573 const char *hostname = NULL;
574 gnutls_session_set_ptr(session, (
void*)hostname);
578 gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
580 #if GNUTLS_VERSION_NUMBER >= 0x030100
581 gnutls_handshake_set_timeout(
582 session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
588 #if GNUTLS_VERSION_NUMBER >= 0x030109
591 gnutls_transport_set_ptr(session,
598 #if GNUTLS_VERSION_NUMBER < 0x021000
601 status.set_result(mfem_gnutls_verify_callback(session));
609 err = gnutls_bye(session, GNUTLS_SHUT_WR);
611 while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED);
616 #ifdef MFEM_USE_GNUTLS_PUSH_FUNCTION
619 gnutls_transport_set_push_function(session, mfem_gnutls_push_function);
633 #ifdef MFEM_USE_GNUTLS_DEBUG
634 std::cout <<
"[GnuTLS_socketbuf::end_session]" << std::endl;
640 if (
is_open() && status.good())
642 #ifdef MFEM_USE_GNUTLS_DEBUG
643 std::cout <<
"[GnuTLS_socketbuf::end_session: gnutls_bye]" << std::endl;
649 err = gnutls_bye(session, GNUTLS_SHUT_WR);
650 status.set_result(err);
652 while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED);
653 status.print_on_error(
"gnutls_bye");
656 gnutls_deinit(session);
662 #ifdef MFEM_USE_GNUTLS_DEBUG
663 std::cout <<
"[GnuTLS_socketbuf::attach]" << std::endl;
677 #ifdef MFEM_USE_GNUTLS_DEBUG
678 std::cout <<
"[GnuTLS_socketbuf::open]" << std::endl;
682 if (err) {
return err; }
686 return status.good() ? 0 : -100;
691 #ifdef MFEM_USE_GNUTLS_DEBUG
692 std::cout <<
"[GnuTLS_socketbuf::close]" << std::endl;
699 return status.good() ? err : -100;
704 ssize_t bw, n = pptr() - pbase();
705 #ifdef MFEM_USE_GNUTLS_DEBUG
706 std::cout <<
"[GnuTLS_socketbuf::sync n=" << n <<
']' << std::endl;
711 bw = gnutls_record_send(session, pptr() - n, n);
712 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
715 status.set_result((
int)bw);
717 status.print_on_error(
"gnutls_record_send");
731 #ifdef MFEM_USE_GNUTLS_DEBUG
732 std::cout <<
"[GnuTLS_socketbuf::underflow ...]" << std::endl;
739 br = gnutls_record_recv(session,
ibuf,
buflen);
740 if (br == GNUTLS_E_REHANDSHAKE)
745 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
746 #ifdef MFEM_USE_GNUTLS_DEBUG
747 std::cout <<
"[GnuTLS_socketbuf::underflow br=" << br <<
']' << std::endl;
754 status.set_result((
int)br);
756 status.print_on_error(
"gnutls_record_recv");
759 setg(NULL, NULL, NULL);
760 return traits_type::eof();
763 return traits_type::to_int_type(*
ibuf);
768 #ifdef MFEM_USE_GNUTLS_DEBUG
769 std::cout <<
"[GnuTLS_socketbuf::xsgetn __n=" << __n <<
']' << std::endl;
773 const std::streamsize bn = egptr() - gptr();
776 traits_type::copy(__s, gptr(), __n);
780 traits_type::copy(__s, gptr(), bn);
781 setg(NULL, NULL, NULL);
782 std::streamsize remain = __n - bn;
783 char_type *end = __s + __n;
789 br = gnutls_record_recv(session, end - remain, remain);
790 if (br == GNUTLS_E_REHANDSHAKE)
795 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
800 status.set_result((
int)br);
802 status.print_on_error(
"gnutls_record_recv");
805 return (__n - remain);
815 #ifdef MFEM_USE_GNUTLS_DEBUG
816 std::cout <<
"[GnuTLS_socketbuf::xsputn __n=" << __n <<
']' << std::endl;
820 if (pptr() + __n <= epptr())
822 traits_type::copy(pptr(), __s, __n);
831 std::streamsize remain = __n;
832 const char_type *end = __s + __n;
835 bw = gnutls_record_send(session, end - remain, remain);
836 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
837 #ifdef MFEM_USE_GNUTLS_DEBUG
838 std::cout <<
"[GnuTLS_socketbuf::xsputn bw=" << bw <<
']' << std::endl;
842 status.set_result((
int)bw);
844 status.print_on_error(
"gnutls_record_send");
846 return (__n - remain);
852 traits_type::copy(pptr(), end - remain, remain);
870 std::string home_dir(getenv(
"HOME"));
871 std::string client_dir = home_dir +
"/.config/glvis/client/";
872 std::string pubkey = client_dir +
"pubring.gpg";
873 std::string privkey = client_dir +
"secring.gpg";
874 std::string trustedkeys = client_dir +
"trusted-servers.gpg";
876 *
state, pubkey.c_str(), privkey.c_str(), trustedkeys.c_str(),
880 std::cout <<
" public key = " << pubkey <<
'\n'
881 <<
" private key = " << privkey <<
'\n'
882 <<
" trusted keys = " << trustedkeys << std::endl;
883 std::cout <<
"Error setting GLVis client parameters.\n"
884 "Use the following GLVis script to create your GLVis keys:\n"
885 " bash glvis-keygen.sh [\"Your Name\"] [\"Your Email\"]"
910 std::iostream::rdbuf(
buf__);
914 : std::iostream(0), glvis_client(false)
920 #endif // MFEM_USE_GNUTLS
927 #ifdef MFEM_USE_GNUTLS
930 mfem_error(
"The secure option in class mfem::socketstream can only\n"
931 "be used when GnuTLS support is enabled.");
937 std::iostream::rdbuf(
buf__);
943 #ifdef MFEM_USE_GNUTLS
945 else { setstate(std::ios::failbit); }
967 setstate(std::ios::failbit);
978 #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
virtual std::streamsize xsgetn(char_type *__s, std::streamsize __n)
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()
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 int open(const char hostname[], int port)
socketstream(bool secure=secure_default)
Create a socket stream without connecting to a host.
virtual int_type underflow()
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())
virtual int attach(int sd)
void mfem_error(const char *msg)
void print_on_error(const char *msg) const
virtual std::streamsize xsgetn(char_type *__s, std::streamsize __n)
virtual std::streamsize xsputn(const char_type *__s, std::streamsize __n)
virtual std::streamsize xsputn(const char_type *__s, std::streamsize __n)
virtual int open(const char hostname[], int port)
int open(const char hostname[], int port)
static void remove_socket()
void generate_dh_params()
const GnuTLS_session_params & params
unsigned int get_flags() const
static GnuTLS_global_state * state